Why does hough not find line? - matlab

I use the following code to extract lines from a given 25x25 black&white-image:
[H, theta, rho] = hough(image);
peaks = houghpeaks(H, 20,'NHoodSize',[19 19]);
lines = houghlines(image, theta, rho, peaks, 'FillGap', 1, 'MinLength', 3);
I then plot the found lines on the given image. The result looks like this:
What I can't understand is, why this procedure does not find a line on the left border of the image, going from top to bottom (or vice versa). Instead for example the pink line is found, which I would think has less evidence in hough space to be there (since it touches less white pixels).
Does anyone have an intuition why this might be the case?
I tried changing the parameters a little bit or add some padding to the image, but nothing has worked so far.
edit:
original image as requested:
In

The default threshold value is too high so the line is not found. I also reduced the nhood size since you want to find horizontal and vertical lines and not angles, so they will all be very close to each other. Also note at the top I set the edges to zero, in the image you posted there is a thin border of 204's around the outside, this just elmiminates the border. Here is my script.
clc;clearvars;close all;
im=imread('B5oOc.png');
im=rgb2gray(im);
im(:,1:2)=0;
im(1,:)=0;
im(end,:)=0;
im(:,end)=0;
BW=edge(im,'canny');
[H, T, R] = hough(BW);
P = houghpeaks(H, 20,'NHoodSize',[1 1],'threshold',ceil(0.3*max(H(:))));
lines = houghlines(BW, T, R, P, 'FillGap', 1, 'MinLength', 3);
imshow(imadjust(mat2gray(H)),'XData',T,'YData',R,...
'InitialMagnification','fit');
title('Hough Transform of Image');
xlabel('\theta'), ylabel('\rho');
axis on, axis normal, hold on;
colormap(hot);
x = T(P(:,2));
y = R(P(:,1));
plot(x,y,'s','color','blue');
figure;
imagesc(im);hold on;colormap gray;
axis image;
max_len = 0;
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');
% Plot beginnings and ends of lines
plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');
% Determine the endpoints of the longest line segment
len = norm(lines(k).point1 - lines(k).point2);
if ( len > max_len)
max_len = len;
xy_long = xy;
end
end
% highlight the longest line segment
plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','red');
The output is this:

Related

Automatically remove straight lines with Hough transform

I am doing a thesis on optical character recognition. My job is to properly segment text characters from images.
Problem is, every text line in this language has words in which often characters are connected by straight lines. These lines may or may not be of equal thickness.
So far using projection profile, I have been able to segment characters that are not attached to any straight lines. But to segment characters that are connected by straight lines, I have to remove those lines. I prefer to use Hough transform to detect and remove those lines (meaning in a BW image, if a pixel in the line is black, then make it white).
See a sample image containing text:
Sample Image
This is a line segmented from the above image using projection profile.
And These are the detected lines using Hough Transform.
Code for Hough transformation. Use This image to test it.
I = imread('line0.jpg');
%I = rgb2gray(I);
BW = edge(I,'canny');
[H,T,R] = hough(BW);
imshow(H,[],'XData',T,'YData',R,'InitialMagnification','fit');
xlabel('\theta'),ylabel('\rho');
axis on, axis normal, hold on;
P = houghpeaks(H,1,'threshold',ceil(0.3*max(H(:))));
x = T(P(:,2));
y = R(P(:,1));
plot(x,y,'s','color','blue');
% Find lines and plot them
lines = houghlines(BW,T,R,P,'FillGap',5,'MinLength',7);
figure, imshow(I), hold on
grid on
max_len = 0;
for k = 1:length(lines)
xy = [lines(k).point1;lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',1,'Color','green');
% plot beginnings and ends of lines
plot(xy(1,1),xy(1,2),'o','LineWidth',2,'Color','red');
plot(xy(2,1),xy(2,2),'o','LineWidth',2,'Color','blue');
% determine the endpoints of the longest line segment
len = norm(lines(k).point1 - lines(k).point2);
if( len > max_len )
max_len = len;
xy_long = xy;
end
end
Any ideas on how I can do it? Any help will be appreciated!
From houghlines you just need to replace the indices of the line with white (255 in this case). You might have to play around with the padding a bit, to take off one or two more pixels.
EDIT: Here is a version attempts to determine the padding.
%% OCR
I = imread('CEBML.jpg');
BW = edge(I,'canny');
[H,T,R] = hough(BW);
P = houghpeaks(H,1,'threshold',ceil(0.3*max(H(:))));
x = T(P(:,2));
y = R(P(:,1));
% Find lines and plot them
lines = houghlines(BW,T,R,P,'FillGap',5,'MinLength',7);
subplot(2,1,1)
grid on
imshow(I)
title('Input')
hold on
px = 5; % Number of padding pixels to probe
white_threshold = 30; % White threshold
ln_length = .6; % 60 %
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
buf_y = xy(1,1):xy(2,1); % Assuming it's a straight line!
buf_x = [repmat(xy(1,2),1,xy(2,1) - xy(1,1)),xy(2,2)] + [-px:px]';
I_idx = sub2ind(size(I),buf_x, repmat(buf_y,size(buf_x,1),1));
% Consider lines that are below white threshold, and are longer than xx
% of the found line.
idx = sum(I(I_idx) <= white_threshold,2) >= ln_length * size(I_idx,2);
I(I_idx(idx,:)) = 255;
% Some visualisation
[ixx,jyy] = ind2sub(size(I),I_idx(idx,:));
plot(jyy,ixx,'.r');% Pixels set to white
plot(xy(:,1),xy(:,2),'-b','LineWidth',2); % Found lines
end
subplot(2,1,2)
grid on
imshow(I)
title('Output')

Filtering Hough transform to only find horizontal and vertical lines in Matlab

I'm trying to write some code that will find lines in an image and draw a red line over the found lines. I've managed to do this using the Hough transform but my problem is I need it to only find horizontal and vertical lines and leave out lines of all other slopes.
I figure that I could solve this by finding the slope of the lines that the code finds and only display red lines over the horizontal and vertical lines using an if statement, but I'm having trouble figuring out how to extract the x and y values from the points I find.
Does anyone have any suggestions for how to solve this problem?
Here is my code below:
function findlineshv(I)
% Read Image
img = imread(I);
% Convert to black and white because
% edge function only works with BW imgs
bwImage = rgb2gray(img);
% figure(1),imshow(bwImage);
% find edges using edge function
b=edge(bwImage,'sobel');
% show edges
% figure(1),imshow(b);
% compute the Hough transform of the edges found
% by the edge function
[hou,theta,rho] = hough(b);
% define peaks, x and y
peaks = houghpeaks(hou,5,'threshold',ceil(0.3*max(hou(:))));
x = theta(peaks(:,2));
y = rho(peaks(:,1));
lines = houghlines(bwImage,theta,rho,peaks,'FillGap',5,'MinLength',7);
figure, imshow(bwImage), hold on
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',3,'Color','red');
end
You can do this by simply setting the desired theta values in the Hough function.
start_angle = 80;
end_angle = 100;
theta_resolution = 0.5:
[H,T,R] = hough(b, 'Theta', start_angle:theta_resolution:end_angle);
This can be done by using required Theta range as answered earlier. Adding this to mention that the Theta range has to be within [-90, 90).
For Horizontal line detection, use range -90:-85 (modify limits as required)
For Vertical line detection, use range -3:3 (modify limits as required)
I = imread('circuit.tif');I = edge(I,'canny');
%% Hough Transform based Horizontal line detection
[H,theta,rho] = hough(I,'Theta',-90:0.5:-85);
P = houghpeaks(H,5,'threshold',ceil(0.3*max(H(:))));
lines = houghlines(I,theta,rho,P,'FillGap',5,'MinLength',3);
figure, imshow(I), hold on
max_len = 0;
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');
% Plot beginnings and ends of lines
plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');
% Determine the endpoints of the longest line segment
len = norm(lines(k).point1 - lines(k).point2);
if ( len > max_len)
max_len = len;
xy_long = xy;
end
end
% highlight the longest line segment
plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','red');
Changing the angle limits as following yields vertical lines:
[H,theta,rho] = hough(I,'Theta',-3:0.5:-3);
Ref: https://www.mathworks.com/help/images/hough-transform.html

How to perform hough transform on canny edge image

After some pre- processing, edge detection and thinning i got the following image and the image is of type double
and in order to remove the isolated pixels within regions i used dilation as
se90 = strel('line', 2, 90);
se0 = strel('line', 2, 0);
BWsdil = imdilate(Edge, [se90 se0]);
vertical dilation followed by horizontal dilation
Actually i want to segment the objects which is labeled within rectangle(ellipse-like structure).
It is noticed that the black rectangle are ruptured during dilation
if i increase the threshold i will lose the segment in the bottom rectangle.
If i'm proceed with this result i'm end up in an error and even basic segmentation algorithms are not working without preprocessing. please help
Can your suggest any other technique to improve mask
if i do connected component analysis on gradient image.i will get border of ellipse instead of ellipse as shown
i tried hough transform but i'm getting some bad results
close all;clear all
I=imread('Sub1.png');
load edge
rotI = imrotate(I,33,'crop');
[H,T,R] = hough(Edge);
imshow(H,[],'XData',T,'YData',R,...
'InitialMagnification','fit');
xlabel('\theta'), ylabel('\rho');
axis on, axis normal, hold on;
P = houghpeaks(H,25,'threshold',ceil(0.3*max(H(:))));
x = T(P(:,2)); y = R(P(:,1));
plot(x,y,'s','color','white');
lines = houghlines(Edge,T,R,P,'FillGap',5,'MinLength',7);
figure, imshow(rotI), hold on
max_len = 0;
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green');
% Plot beginnings and ends of lines
plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red');
% Determine the endpoints of the longest line segment
len = norm(lines(k).point1 - lines(k).point2);
if ( len > max_len)
max_len = len;
xy_long = xy;
end
end

Hough Transform: Converted polar coordinates back to Cartesian, but still can't plot them

So I have already implemented every part of a Hough Transform on my own, except for actually plotting the lines back onto the original image.
I can set up my array of data that I have like this.
points | theta | rho
-------|-------|----
[246,0] -90 -246
[128,0] -90 -128
[9,0] -90 -9
[0,9] 0 9
[0,128] 0 128
[0,246] 0 246
The points are the points that were converted from the peaks in Polar Coordinates. So now I need to draw all six of these lines and I have had no luck.
Edit
So I tried to change my code based off suggestions. This is what I came up with.
function help(img, outfile, peaks, rho, theta)
imshow(img);
x0 = 1;
xend = size(img,2);
peaks_len=length(peaks);
for i=1:peaks_len
peak=peaks(i,:);
r_ind=peak(1);
t_ind=peak(2);
r=rho(r_ind);
th=theta(t_ind);
%display([r,th,peak]);
%// if a vertical line, then draw a vertical line centered at x = r
% display([r, th]);
if (th == 0)
display('th=0');
display([1, size(img,1)]);
line([r r], [1 size(img,1)], 'Color', 'green');
else
%// Compute starting y coordinate
y0 = abs((-cosd(th)/sind(th))*x0 + (r / sind(th)))+11;%-25;
%// Compute ending y coordinate
yend = abs((-cosd(th)/sind(th))*xend + (r / sind(th)))+11;%-25;
display('y');
display([y0, yend]);
display('x');
display([x0 xend]);
%// Draw the line
line([x0 xend], [y0 yend], 'Color', 'green');
end
end
end
I had to change from r==0 to th==0 because th=0 would give NAN errors when r was not 0.
Based off the peaks, I then used that to get the data I needed to then calculate some values... but for some reason this isn't plotting well.
If you notice the + 11 for both y values. I had to do that to get the lines to be where they need to. I have a feeling something else went wrong.
I did change it so that my Rho values are all now positive.
If you recall from the parameterization of the Hough space, the direct relation between rho,theta to x,y is:
rho = x*cos(theta) + y*sin(theta)
Bear in mind that x,y represent the column and row location respectively. In addition, the origin is defined at the top-left corner of the image. Now that you want to plot the equation of the line, you have your rho and theta. Simply re-arrange the equation so that you can solve for an equation of the line of the form y = mx + b:
As such , simply loop over each rho and theta you have and draw a line that starts from the origin at x = 0 up to the limit of your image x = width-1. However, because MATLAB is 1-indexed, we need to go from x = 1 to x = width. Supposing that your rho and theta are stored in separate arrays of the same lengths and you have your edge image stored in im, you can do something like this:
imshow(im); %// Show the image
hold on; %// Hold so we can draw lines
numLines = numel(rho); %// or numel(theta);
%// These are constant and never change
x0 = 1;
xend = size(im,2); %// Get the width of the image
%// For each rho,theta pair...
for idx = 1 : numLines
r = rho(idx); th = theta(idx); %// Get rho and theta
%// Compute starting y coordinate
y0 = (-cosd(th)/sind(th))*x0 + (r / sind(th)); %// Note theta in degrees to respect your convention
%// Compute ending y coordinate
yend = (-cosd(th)/sind(th))*xend + (r / sind(th));
%// Draw the line
line([x0 xend], [y0 yend], 'Color', 'blue');
end
The above code is pretty simple. First, show the image using imshow in MATLAB. Next, use hold on so we can draw our lines in the image that will go on top of the image. Next, we calculate how many rho,theta pairs there are, and then we define the two x coordinates to be 1 and width as we will use these to determine where the starting and ending y coordinates are, given these x coordinates. Next, for each rho,theta pair we have, determine the corresponding y coordinates, then use line to draw a line from the starting and ending (x,y) coordinates in blue. We repeat this until we run out of lines.
Don't be alarmed if the y coordinates that are produced go out of bounds in the image. line will be intelligent enough to simply cap the result.
When theta = 0
The above code works assuming that you have no vertical lines detected in the Hough Transform, or when theta = 0. If theta = 0 (like in your case), this means that we have a vertical line which would thus produce an infinite slope and our formulation of y = mx + b is invalid. Should theta = 0, the equation of the line becomes x = rho. As such, you will need an additional if statement inside your loop that will detect this:
imshow(im); %// Show the image
hold on; %// Hold so we can draw lines
numLines = numel(rho); %// or numel(theta);
%// These are constant and never change
x0 = 1;
xend = size(im,2); %// Get the width of the image
%// For each rho,theta pair...
for idx = 1 : numLines
r = rho(idx); th = theta(idx); %// Get rho and theta
%// if a vertical line, then draw a vertical line centered at x = r
if (th == 0)
line([r r], [1 size(im,1)], 'Color', 'blue');
else
%// Compute starting y coordinate
y0 = (-cosd(th)/sind(th))*x0 + (r / sind(th)); %// Note theta in degrees to respect your convention
%// Compute ending y coordinate
yend = (-cosd(th)/sind(th))*xend + (r / sind(th));
%// Draw the line
line([x0 xend], [y0 yend], 'Color', 'blue');
end
end
In order to draw the vertical line, I need to know how high the image is so that we can draw a vertical line from the top of the image (y = 1) down to the bottom of the image (y = height) which is anchored at x = rho. As such, the above code should now properly handle any line, as well as the degenerate case when the slope is infinite. Therefore, this second version of the code is what you're after.
Good luck!

How to Find rectangular region using hough line in Matlab?

Edit :
I use this code but did't finded plate region. How do I find the plate ?
This code gives only horizontal lines but I must find vertical and horizontal lines.
I = imread('image.jpg');
I= rgb2gray(I);
%I(:,1:2)=0;
%I(1,:)=0;
%I(end,:)=0;
%I(:,end)=0;
BW = edge(I,'canny');
%imshow(BW)
[H,T,R] = hough(BW);
%{
imshow(H,[],'XData',T,'YData',R,...
'InitialMagnification','fit');
xlabel('\theta'), ylabel('\rho');
axis on, axis normal, hold on;
%}
P = houghpeaks(H, 20,'NHoodSize',[1 1],'threshold',ceil(0.1*max(H(:))));
lines = houghlines(BW, T, R, P, 'FillGap', 40, 'MinLength', 1);
%P = houghpeaks(H,7,'NHoodSize','threshold',ceil(0.4*max(H(:))));
%lines = houghlines(BW,T,R,P,'FillGap',40,'MinLength',90);
x = T(P(:,2)); y = R(P(:,1));
%plot(x,y,'s','color','blue');
% Find lines and plot them
figure;
imagesc(I);hold on;colormap gray;
axis image;
max_len = 0;
for k = 1:length(lines)
xy = [lines(k).point1; lines(k).point2];
% Plot beginnings and ends of lines
%plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red')
plot(xy(1,1),xy(2,2),'x','LineWidth',2,'Color','blue');
%plot(xy(2,2),xy(2,2),'x','LineWidth',2,'Color','green');
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green'); %connect red and blue point
% Determine the endpoints of the longest line segment
len = norm(lines(k).point1 - lines(k).point2);
if ( len > max_len)
max_len = len;
xy_long = xy;
end
end
This part draws connect red and blue point. How to connect blue blue point and red red point ? If I can it , I find plate area.
% Plot beginnings and ends of lines
%plot(xy(1,1),xy(1,2),'x','LineWidth',2,'Color','yellow');
plot(xy(2,1),xy(2,2),'x','LineWidth',2,'Color','red')
plot(xy(1,1),xy(2,2),'x','LineWidth',2,'Color','blue');
%plot(xy(2,2),xy(2,2),'x','LineWidth',2,'Color','green');
plot(xy(:,1),xy(:,2),'LineWidth',2,'Color','green'); %connect red and blue point
then , Probably lines = houghlines(BW, T, R, P, 'FillGap', 40, 'MinLength', 90); this part change.