我正在尝试检测焊接图像中的接缝以进行自动焊接过程。 我想在原始图像中找到检测到的线条(所需图像中的红线)的像素位置。
我使用了以下代码,最后从图像中删除了噪音,以达到下面的结果。
clc,clear,clf;
im = imread('https://i.stack.imgur.com/UJcKA.png');
imshow(im);title('Original image'); pause(0.5);
sim = edge(im, 'sobel');
imshow(sim);title('after Sobel'); pause(0.5);
mask = im > 5;
se = strel('square', 5);
mask_s = imerode(mask, se);
mask(mask_s) = false;
mask = imdilate(mask, se);
sim(mask) = false;
imshow(sim);title('after mask');pause(0.5);
sim= medfilt2(sim);
imshow(sim);title('after noise removal')
不幸的是,图像中没有任何东西能够完美地找到接缝。
任何帮助都将不胜感激。
Download原始图片。
答案 0 :(得分:3)
您需要使滤镜对噪音更具鲁棒性。这可以通过给予它更大的支持来实现:
filter = [ones(2,9);zeros(1,9);-ones(2,9)];
msk = imerode(im > 0, ones(11)); % only object pixels, discarding BG
fim =imfilter(im,filter);
robust = bwmorph((fim>0.75).*msk,'skel',inf); % get only strong pixels
健壮的面具看起来像:
正如您所看到的,接缝线被很好地检测到,我们只需将其选为最大的连接组件:
st = regionprops(bwlabel(robust,8), 'Area', 'PixelList');
[ma mxi] = max([st.Area]); % select the region with the largest area
现在我们可以将一个多边形(第二度)拟合到似乎:
pp=polyfit(st(mxi).PixelList(:,1), st(mxi).PixelList(:,2), 2);
这就是图像:
imshow(im, 'border','tight');hold on;
xx=1:size(im,2);plot(xx,polyval(pp,xx)+2,'r');
请注意由于滤镜宽度导致的+2
Y偏移。
PS,
您可能会发现this thread相关。
答案 1 :(得分:3)
Shai给出了一个很好的答案,但我想补充一点关于为什么你的噪音过滤不起作用的背景。
为什么中值过滤不起作用
Wikipedia表明中值滤波会在保留边缘的同时消除噪音,这就是您可能选择使用它的原因。但是,在你的情况下几乎肯定不会起作用,这就是原因:
中位数过滤在图像上滑动窗口。在每个区域中,它将中心像素替换为周围窗口的中值。 medfilt2
默认使用3x3窗口。让我们看一下您线附近的3x3区块,
围绕[212 157]的3x3区块看起来像这样
[0 0 0
1 1 1
0 0 0]
中值为0!因此,即使我们处于线段的中间,像素也会被过滤掉。
中值过滤的替代方法
Shai的去除噪声的方法改为找到最大的连接像素组并忽略较小的像素组。如果您还想从图像中删除这些小组,Matlab会提供一个过滤器bwareaopen
,用于从二进制图像中删除小对象。
例如,如果您更换行
sim= medfilt2(sim);
与
sim= bwareaopen(sim, 4);
结果好多了
替代边缘检测器
最后一点,Shai使用水平渐变滤镜来查找图像中的水平边缘。它很有效,因为你的边缘是水平的。如果边缘不总是水平的,则可能需要使用另一种边缘检测方法。在您的原始代码中,您使用Sobel,但Matlab提供了许多选项,如果您调整其阈值,所有这些选项都会表现得更好。例如,在下图中,我使用四个不同的边缘检测器突出显示了代码选择的像素(使用bwareaopen修改)。