图像中的线检测

时间:2015-06-19 09:28:17

标签: image matlab image-processing computer-vision edge-detection

我是图像处理的新手,我试图使用此代码检测垂直线 -

sessionID

这是我的形象 -

enter image description here

这是我在执行操作后得到的 - enter image description here

所以我的问题是为什么我得到这个输出?如果垂直双键被计为2条不同的垂直线,则有10条垂直线。如果我想要获得水平,垂直,45和-45所有线条,如何使用所有4个掩码来获得单个输出?

3 个答案:

答案 0 :(得分:14)

我的一个简单建议是检测渐变并确定边缘点的方向。请记住,方向是与边缘垂直的方向。因此,如果要查找垂直线,垂直于垂直线的方向是水平的,相对于笛卡尔平面为180度或-180度。因此,对于检测到的边缘点的每个方向,如果方向是-180度或180度,则将该位置的输出设置为true,否则为false。要检测渐变方向,请使用图像处理工具箱中的imgradient。我假设这是可用的,因为您同时使用了imreadim2bw,它们都是该工具箱的一部分:

im = imread('http://i.stack.imgur.com/bdNOt.png');
tol = 5;
[~,ang] = imgradient(im);
out = (ang >= 180 - tol | ang <= -180 + tol);
imshow(out);

该代码使用一个名为tol的变量来定义您想要检测的角度的公差,以考虑看起来垂直的噪声或边缘,但是当计算角度时,它可能看起来不是。基本上,我们正在寻找角度在180度或-180度范围内的任何点。

这就是我们得到的:

enter image description here

作为后期处理的一种方法,您可以使用bwareaopen过滤掉区域低于特定数量的像素区域。利用垂直线比其他像素具有更大面积的事实,你可以做这样的事情:

out_filter = bwareaopen(out, 50);

我们得到:

enter image description here

现在,如果要检测水平线,则应找到-90或90度的渐变方向。这是有道理的,因为那些水平线,垂直于水平线的方向确实是垂直的,并且它们是-90度或90度。如果你想要斜线,如果你想要左倾斜线,寻找45度或-135度和右倾斜线的角度,-45度或135度。我将让你弄清楚为什么这些角度确实代表了那些线条。

您提供的图片中没有任何水平线,所以我只是寻找斜线:

左倾斜线

注意:由于量化错误,我不得不增加容差。

im = imread('http://i.stack.imgur.com/bdNOt.png');
tol = 20;
[~,ang] = imgradient(im);
out = (ang >= 45 - tol & ang <= 45 + tol) | (ang >= -135 - tol & ang <= -135 + tol);
out_filter = bwareaopen(out, 50);
imshow(out_filter);

enter image description here

右倾斜线:

此外还必须增加容差:

im = imread('http://i.stack.imgur.com/bdNOt.png');
tol = 20;
[~,ang] = imgradient(im);
out = (ang >= 135 - tol & ang <= 135 + tol) | (ang >= -45 - tol & ang <= -45 + tol);
out_filter = bwareaopen(out, 50);
imshow(out_filter);

enter image description here

答案 1 :(得分:7)

另一种方法是使用描绘债券的所有线具有相同的纵横比和面积的事实。在对图像进行过滤之后,我们可以查看方向或构成它们的索引列表,以检测它们是否是垂直的或诸如此类的。所有这些都可以使用regionprops完成。

image=rgb2gray(imread('benzene.png'));  
d=abs(255-image); % inverse the image
d=im2bw(d);
stat=regionprops(d,'Area', 'Orientation','PixelIdxList'); 
areas=[stat.Area];
hist(areas)

enter image description here

检查直方图显示线条的切割位置,线条的面积小于字母,并且它们应具有大致相同的区域。所以我切割了1000像素以下的区域:

idx=find(areas<1000);
angs=round([stat(idx).Orientation]);

现在您可以使用angsidx来获取您想要的任何类型的行。例如,我们只绘制30度线:

d2=zeros(size(d));
d2(vertcat(stat(idx(angs==30)).PixelIdxList))=1;
imagesc(d2)

enter image description here

请注意,当我开始回答这个问题时,我拍摄的图像是苯.png文件。现在我意识到你提供了一个与原始图像不同的图像,这样描绘债券的线条并不是分开的,而是你有&#34; ring&#34;。我稍后会看到,如果你想要我,我也可以解决这个问题。

修改

要找到新图像的相关行,你有戒指,这些行的唯一区别是,它们是直的&#34;线&#34;而不弯曲。所以我求助于心爱的Hough transform来接他们:

image=imread('http://i.stack.imgur.com/bdNOt.png');
d=abs(1-image); % inverse the image
BW=im2bw(d);
BW = bwmorph(BW,'skel',1);
[H, T, R] = hough(BW,'Theta',-90:10:80);
P = houghpeaks(H, 100,'NHoodSize',[3 3],'threshold',1);
lines = houghlines(BW, T, R, P, 'FillGap',5, 'MinLength', 35);

让我们获得检测到的线的角度:

angs=round([lines.theta]);

您会看到此处angs将生成0,-60或60度的值。

假设您只想绘制0度的那些:

p1=vertcat(lines(angs==0).point1);
p2=vertcat(lines(angs==0).point2);

imshow(BW, 'InitialMag',200, 'Border','tight'), hold on

for k = 1:size(p1,1)
   line([p1(k,1) p2(k,1)],[p1(k,2) p2(k,2)], 'LineWidth',4,...
   'Color',[1 0 0]); hold on
end
hold off

enter image description here

答案 2 :(得分:2)

我仍然在做这件事。但到现在为止我已经得到了这个。我没有使用过滤器,而是使用了不同的过滤器。

我使用了您提供的第一张图片。这里介绍了过滤器:image_filters

enter image description here

image=imread('benzene.png');  
BW = im2bw(image);
w1=(1/3)*[1 0 -1;1 0 -1;1 0 -1];
g=(imfilter(double(BW),w1));
g(g<1)=0;
imshow(g);

我得到的输出是这样的:你可以看到结果还没有完成。我建议你尝试两件事:使用形态侵蚀算子去除小元素。您也可以使用连接的组件来执行此操作。

output

在此期间尝试做我的建议。如果我得到答案,我会更新它。