I'm trying to detect lines in a image using the Hough Transform. I almost get it, but the lines after binarize are a too harsh to be considered straight (see images, probably you need see them in full size). Is there any way (maybe some "bwmorph" operation) to soften the binarized lines, and make them straighter to be easier for the hough transform to detect them as a single line?
My code right now is:
F=getframe;
I = rgb2gray(frame2im(F));
BW = imbinarize(I, 'adaptive', 'Sensitivity', 0.35);
BW = bwmorph(BW,'thin', inf);
You don't necessarily need to skeletonize first, but you do need to adjust your parameters for the hough transform, specifically how you want it to detect peaks and fill gaps. Here's an example of a transform I did on your figure (https://www.mathworks.com/help/images/ref/houghlines.html):
bw = (imbinarize(I, graythresh(I)));
dilatedImage = imdilate(bw,strel('disk',10));
thinnedImage = bwmorph(dilatedImage,'thin',inf);
[H,theta,rho] = hough(thinnedImage);
P = houghpeaks(H,20,'threshold',0);
lines = houghlines(thinnedImage,theta,rho,P,'FillGap',400,'MinLength',300);
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
The output looks like this:
Related
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')
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
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
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
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: