Image 图像中的直线检测

Image 图像中的直线检测,image,matlab,image-processing,computer-vision,edge-detection,Image,Matlab,Image Processing,Computer Vision,Edge Detection,我是图像处理新手,我尝试用这段代码检测垂直线- image=imread('benzene.jpg'); BW = im2bw(image); w1=[-1 2 -1 ; -1 2 -1 ; -1 2 -1]; g=(imfilter(double(BW),w1)); g=abs(g); T=max(g(:)); g=g>=T; imshow(g); 这就是我的形象- 这就是我在执行手术后得到的- 所以我的问题是为什么我要得到这个输出?如果垂直双键被算作两条不同的垂直线,那么有1

我是图像处理新手,我尝试用这段代码检测垂直线-

image=imread('benzene.jpg');  
BW = im2bw(image);
w1=[-1 2 -1 ; -1 2 -1 ; -1 2 -1];
g=(imfilter(double(BW),w1));
g=abs(g);
T=max(g(:));
g=g>=T;
imshow(g);
这就是我的形象-

这就是我在执行手术后得到的-


所以我的问题是为什么我要得到这个输出?如果垂直双键被算作两条不同的垂直线,那么有10条垂直线。另外,如果我想得到水平线、垂直线、45和-45所有的线,我怎么能使用所有的4个掩模得到一个输出呢?

我仍在做这件事的过程中。但到现在为止,我已经得到了这个。我没有用过你的过滤器,而是用了另一个

我使用了你提供的第一张图片。此处介绍了筛选器:

image=imread('benzene.png');
BW=im2bw(图像);
w1=(1/3)*[10-1;10-1;10-1];
g=(imfilter(双(BW),w1));

G(g我的一个简单建议是检测梯度并确定边缘点的方向。请记住,方向是与边缘垂直的方向。因此,如果你想找到垂直线,垂直于垂直线的方向是水平的,即相对于笛卡尔平面为180度或-180度。因此,对于检测到的边缘点的每个方向,如果方向为-180度或180度,则将此位置的输出设置为
true
,否则
false
。要检测梯度方向,请使用来自图像处理t工具箱。我假设这是可用的,因为您使用了
imread
im2bw
,它们都是工具箱的一部分:

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


现在,如果你想检测水平线,你应该找到-90或90度的梯度方向。这是有意义的,因为那些水平线,垂直于水平线的方向实际上是垂直的,这是-90或90度。如果你想要斜线,如果你想要左倾线,look表示45度或-135度的角度,以及右倾直线,或-45度或135度。我会让你找出为什么这些角度确实代表了这类直线

您提供的图像中没有任何水平线,因此我将只查找斜线:

angs=round([lines.theta]);
左倾线条 注意:由于量化误差,我不得不增加容差

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);
im=imread('http://i.stack.imgur.com/bdNOt.png');
tol=20;
[~,ang]=imgradient(im);

out=(ang>=45-tol&ang=-135-tol&ang=135-tol&ang=-45-tol&ang一种不同的方法是使用这样一个事实,即所有描绘键的线都具有相同的纵横比和面积。在过滤图像后,只留下键,我们可以查看方向或组成键的索引列表,以检测它们是否正确垂直或诸如此类。所有这些都可以使用
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)

检查柱状图显示了线条的切割位置,线条的面积比字母小,并且应该具有大致相同的面积。因此,我切割了1000像素以下的区域:

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

请注意,在我开始回答这个问题时,我拍摄的图像是benzene.png文件。现在我意识到您提供的图像与原始图像不同,因此描述键的线条不是分开的,而是有“环”。如果您愿意,我将稍后再看是否可以解决这个问题

编辑:

为了找到新图像的相关线条,在你有戒指的地方,线条的唯一区别是,它们是直的“线条”,而不是弯曲的。所以我求助于心爱的人来挑选它们:

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

你能提供此图像的联机链接吗?我在网上找不到它。我编辑了我的问题。我理解我的错误,但现在我又得到了意外的输出。@roni你可以从这里保存此图像,因为我现在没有此图像的链接。当然,问题是你的过滤器。请阅读一些基本过滤器以获得wrasp:取而代之在形态学运算中,有一种更简单的方法可以检测这些直线(在过滤之后)。只需逐个检测它们(例如通过
imlabel
)然后计算每个高度上的宽度。如果它是常数,那么它是一条直线,否则它就是一些你想要避免的噪音/我在Hough变换的线条中考虑了更多。但是我无法应用它。请使用
out=bwareaopen(out,50);
(可能需要稍微调整阈值)删除与字母相关的行。@Jonas-你读到了我的心思…我实际上刚刚做了lol。很有趣,你和我选择了完全相同的阈值。很好的答案是我自己无法计算出来的!水平方向将是0或90。倾斜方向应为+/-45和+/-135。我将更新我的帖子,让你看到更多具有相同图像的行。@Noober-完成。看一看。非常感谢。但是你是如何决定只剪不到1000的?还有我如何使用
角度
idx
?你能举一些例子吗?非常感谢。事实上,是的,我确实有戒指要处理。我添加了回答戒指的版本。非常感谢。我接受的答案足够好,但我没有我希望找到一些替代方法来获得同样的结果。再次感谢这真的很有帮助。
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]);
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