Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Line detection in image

I am new to image processing and I was trying to detect vertical lines using this code-

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);

This was my image-

enter image description here

And this is what I got after performming the operations- enter image description here

So my question is why am I getting this output?There are 10 vertical lines if vertical double bonds are counted as 2 distinct vertical lines.Also what if I want to get horizontal,vertical,45 and -45 all the lines,how can I use all the 4 masks to get one single output?

like image 293
Noober Avatar asked Jun 19 '15 09:06

Noober


1 Answers

One simple suggestion I have is to detect the gradient and determine the orientation of an edge point. Bear in mind that the orientation is in the direction that is perpendicular to the edge. Therefore, if you want to find vertical lines, the direction that is perpendicular to a vertical line is horizontal, which is either 180 degrees or -180 degrees with respect to the Cartesian plane. As such, for each orientation of the edge points that are detected, if the orientation is either -180 degrees or 180 degrees, then set the output of this location to be true, else false. To detect the gradient orientations, use imgradient from the image processing toolbox for that. I'm assuming this is available as you have used both imread and im2bw and they are both part of that toolbox:

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

The code uses a variable called tol to define a tolerance in the angles you want to detect to account for noise or edges that look vertical but when the angle is computed, it may not appear to be. Basically, we are looking for any points whose angles are within 180 degrees or -180 degrees.

This is what we get:

enter image description here

As a means of post-processing, you could use bwareaopen to filter out pixel regions whose areas fall below a certain amount. Taking advantage of the fact that the vertical lines have a larger area than the other pixels, you could do something like this:

out_filter = bwareaopen(out, 50);

We get:

enter image description here


Now if you want to detect horizontal lines, you should find gradient orientations that are either -90 or 90 degrees. This makes sense because those lines that are horizontal, the direction perpendicular to a horizontal line is indeed vertical, and that's either -90 or 90 degrees. If you want slanted lines, if you want a left leaning line, look for angles of either 45 degrees or -135 degrees and a right leaning line, either -45 degrees or 135 degrees. I'll let you work out why these angles are indeed representative of those kinds of lines.

You don't have any horizontal lines in the image you provided, so I'll just look for slanted lines:

Left leaning lines

Note: I had to increase the tolerance due to quantization errors.

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

Right leaning lines:

Also had to increase the tolerance here as well:

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

like image 195
rayryeng Avatar answered Oct 13 '22 03:10

rayryeng