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-
And this is what I got after performming the operations-
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?
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:
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:
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:
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);
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);