Matlab Hough transform for line detection - matlab

I am trying to detect the white straight lines on the image using the hough transform.
Binary image with White = 1, Black= 0 - Lines detected in green and longest line detected in red
The following code only detects sections of a curved line as straight and is ignoring (failing to identify) the truly straight lines. How can I modify it to find only the proper straight lines among the white lines?
load('image.mat')
%Binarize image
image(image== 0) = 1;
image= image- ones(size(image),'int8');
image= logical(image);
% imshow(BW_active,[0 1])
[H,theta,rho] = hough(image, 'RhoResolution',0.5);
P = houghpeaks(H);
lines = houghlines(image,theta,rho,P); %,'FillGap',20,'MinLength',7);
figure, imshow(image, [0 1]), hold on
max_len = 0;
% from Mathworks
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)image
max_len = len;
xy_long = xy;
end
end
% highlight the longest line segment
plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','red');
Here there is the .mat file.
https://drive.google.com/file/d/0BxCvoDCdJJYoOFZLeklCX2dzc2c/view?usp=sharing

Related

why the hough transform can't find the line at right-below corner of the image?

I am trying use hough transform to find the edge, the following image's right-below corner line can't be found. why?
My code
BW = imread("edge/30.1.tif");
[H,theta,rho] = hough(BW);
imshow(imadjust(rescale(H)),[],...
'XData',theta,...
'YData',rho,...
'InitialMagnification','fit');
xlabel('\theta (degrees)')
ylabel('\rho')
axis on
axis normal
hold on
colormap(gca,hot);
P = houghpeaks(H,5,'threshold',ceil(0.3*max(H(:))));
x = theta(P(:,2));
y = rho(P(:,1));
plot(x,y,'s','color','black');
lines = houghlines(BW,theta,rho,P,'FillGap',5,'MinLength',7);
figure, imshow(BW), 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');

Calculate angles from extracted leaf veins

I'm trying to calculate the angles that exist between leaf veins in matlab. What I've thought is to detect the lines (veins) using Hough and then calculate the angles. But the result I get when I try to detect the lines is a little strange.
Here is the code:
[H,theta,rho] = hough(vein);
P = houghpeaks(H,4);
x = theta(P(:,2));
y = rho(P(:,1));
%lines = houghlines(BW,theta,rho,P,'FillGap',2,'MinLength',4);
lines = houghlines(BW,theta,rho,P);
figure, imshow(vein), 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');
Any ideas?
I suppose you just mixed the names of the matrices.
In your code, there is vein matrix and BW matrix.
You are using:
vein here: [H,theta,rho] = hough(vein);
BW here: lines = houghlines(BW,theta,rho,P);
I added the line BW = vein;, and the result is much less strange:
vein = imbinarize(rgb2gray(imread('https://i.stack.imgur.com/cuwb0.jpg'))); %Read image, and convert to binary
BW = vein; %Copy vein to BW
[H,theta,rho] = hough(vein);
P = houghpeaks(H,4);
x = theta(P(:,2));
y = rho(P(:,1));
%lines = houghlines(BW,theta,rho,P,'FillGap',2,'MinLength',4);
lines = houghlines(BW,theta,rho,P);
figure, imshow(vein), 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');
Result:

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

Match Lines of Rectangles

I'm trying to find rectangles in an image in Matlab. I use houghlines function to find lines. It finds lines with points but not in order. Is there any way to find match same rectangle's lines? Some points are close but some points have distance to other line's points.
this code from matlab's houghlines's example:
I = imread('e1.jpg');
I =rgb2gray(I);
rotI = imrotate(I,360,'crop');
BW = edge(rotI,'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,20,'threshold',ceil(0.3*max(H(:))));
x = T(P(:,2)); y = R(P(:,1));
plot(x,y,'s','color','white');
% Find lines and plot them
lines = houghlines(BW,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
% highlight the longest line segment
plot(xy_long(:,1),xy_long(:,2),'LineWidth',2,'Color','blue');
I can't add image because of reputation but it has 3 black rectangles in white backroung