检测图像中的水位

信息处理 图像处理 opencv 边缘检测
2022-02-11 07:22:36

我设计了一个形状像圆角矩形的表面,我想在我从中拍摄的照片中检测它的确切边界。示例照片是这样的:

示例图像

我已经尝试对图像进行阈值处理,但即使经过高斯平滑,阈值也不会给我一个确切的边界。

有没有人知道一种技术可以给我精确的边界,不管照明等问题如何?

更新: 对不起,我没有很好地说明问题,实际上我没有意识到真正的问题(尽管我认为它并没有太大变化):

这是新照片。这张照片是在一个塑料桶内俯视拍摄的,里面有少量的水,我需要从桶壁上分割出水中的区域,以便稍后检测水中的物体。有一些照明从下面照亮了桶的底部(实际上放置了一块有机玻璃而不是原来的底部)。

新图片

问题是墙壁上的光反射使其与水的颜色相同,在某些区域(例如示例图像的底部中心),很难找到水位。

此外,我将不胜感激有关如何区分与有机玻璃相关的边界和与水位相关的边界的任何提示。

谢谢

2个回答

看看最短路径的威力。

解决方案大致遵循我在这里所做的:检测和隔离图像的一部分

在这种情况下,我们首先通过将水位灰度以上的每个像素值限制为相同的强度来处理图像。

在此处输入图像描述

然后在使用高斯滤波器的差异创建的反向边缘图像上执行最短路径,我们得到:

在此处输入图像描述

导致以下分段:

在此处输入图像描述

此解决方案所需的我的 MATLAB 函数:

http://imageprocessing.com.au/research/code/polarTransform.m http://imageprocessing.com.au/research/code/circularShortestPath.m http://imageprocessing.com.au/research/code/linearShortestPath。米

代码:

clear all
close all

%% Load image
I = imread('CabQx.jpg');
I = double(rgb2gray(I));
figure
imagesc(I);
colormap gray(256); 
title('Image');

%% Adjust intensity
Ia = I;
Ia(Ia > 49) = 49;
figure
imagesc(Ia);
colormap gray(256); 
title('Adjusted Image');

%% Bandpass Kernel
H1 = fspecial('gaussian',[100,100],8); % *** Changed filter size
H2 = fspecial('gaussian',[100,100],2);  % *** 
H = H2-H1;
H = mat2gray(H);
figure;
imagesc(H);
colorbar;
colormap gray(256); 
title('Bandpass kernel');

%% Edge Kernel
Hedge = imag(hilbert(H));
figure;
imagesc(Hedge);
colormap gray(256); 
title('Edge Kernel');

%% Edge filtered image
G = sqrt(imfilter(Ia,Hedge,'replicate').^2 + imfilter(Ia,Hedge.','replicate').^2);
G = max(G(:)) - G;
imagesc(G);
colormap gray(256); 
title('Inverse edge filtered image');

%% Shortest path
% Mid point
[r,c] = size(G);
r = floor(r/2);
c = floor(c/2);
% Min radius and max radius
min_radius = 100;
max_radius = 1000;
% Shortest path
[ path, energy, lastIndex, pathImage ] = ...
    circularShortestPath(G, 100, [c,r], [min_radius,max_radius], [400,720*2]);
figure;
imagesc(I);
hold on;
plot(path(:,1),path(:,2),'r','LineWidth',2);
hold off;
colormap gray(256); 
title('Shortest path');

%% Segment
figure
imagesc(I);
hold on;
fill(path(:,1),path(:,2),'r');
hold off;
colormap gray(256); 
title('Mask')

%%
J = zeros(size(I));
mask = roipoly(J,path(:,1),path(:,2));
segmentedI = I .* mask;
figure;
imagesc(segmentedI);
colormap gray(256); 
title('Segmented image');

使用水平集或活动轮廓。他们擅长处理此类问题,并且通常对噪声具有鲁棒性。它们在某些方面也是亚像素精度的。最好的部分是存在许多开源项目:

  1. 主动轮廓分割
  2. 稀疏场活动轮廓
  3. 分段测地线路径的组合