How to perform hough transform on canny edge image - matlab

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

Related

Matlab - Hough Transform detect harsh lines (not perfectly stright after binarize)

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:

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

Matlab and ImageJ detecting bone fracture

I'm trying to detect a fracture in a picture using imageJ and Matlab, both of them are required. Here is the original image:
I already established the connection between matlab and imageJ and I've opened the image on imageJ and started by doing some things. First, I used the Find Edges function in imageJ menu to get an outline of the bone. After I did a constrast enhancement to enhance the outline. My problem now is, having only an outline and a black background how can I make an algorithm or something like it that will tell me that the lines don't connect? (meaning there is a fracture in the bone). I did something similar to what is on this video in the part when he ticks the sobel edge detection.
https://www.youtube.com/watch?v=Hxn2atZl5us
Gave it a shot in MATLAB only. You can use the Hough transform to find what the largest-contributing angles are to the edge-filtered image, then use that information to go one step more and detect where the break is with some typical image processing tricks.
No promises on how this will work on any images that are not the one that you provided, but the steps are reasonable to refine for additional sample breadth.
img = imread('http://i.stack.imgur.com/mHo7s.jpg');
ImgBlurSigma = 2; % Amount to denoise input image
MinHoughPeakDistance = 5; % Distance between peaks in Hough transform angle detection
HoughConvolutionLength = 40; % Length of line to use to detect bone regions
HoughConvolutionDilate = 2; % Amount to dilate kernel for bone detection
BreakLineTolerance = 0.25; % Tolerance for bone end detection
breakPointDilate = 6; % Amount to dilate detected bone end points
%%%%%%%%%%%%%%%%%%%%%%%
img = (rgb2gray(img)); % Load image
img = imfilter(img, fspecial('gaussian', 10, ImgBlurSigma), 'symmetric'); % Denoise
% Do edge detection to find bone edges in image
% Filter out all but the two longest lines
% This feature may need to be changed if break is not in middle of bone
boneEdges = edge(img, 'canny');
boneEdges = bwmorph(boneEdges, 'close');
edgeRegs = regionprops(boneEdges, 'Area', 'PixelIdxList');
AreaList = sort(vertcat(edgeRegs.Area), 'descend');
edgeRegs(~ismember(vertcat(edgeRegs.Area), AreaList(1:2))) = [];
edgeImg = zeros(size(img, 1), size(img,2));
edgeImg(vertcat(edgeRegs.PixelIdxList)) = 1;
% Do hough transform on edge image to find angles at which bone pieces are
% found
% Use max value of Hough transform vs angle to find angles at which lines
% are oriented. If there is more than one major angle contribution there
% will be two peaks detected but only one peak if there is only one major
% angle contribution (ie peaks here = number of located bones = Number of
% breaks + 1)
[H,T,R] = hough(edgeImg,'RhoResolution',1,'Theta',-90:2:89.5);
maxHough = max(H, [], 1);
HoughThresh = (max(maxHough) - min(maxHough))/2 + min(maxHough);
[~, HoughPeaks] = findpeaks(maxHough,'MINPEAKHEIGHT',HoughThresh, 'MinPeakDistance', MinHoughPeakDistance);
% Plot Hough detection results
figure(1)
plot(T, maxHough);
hold on
plot([min(T) max(T)], [HoughThresh, HoughThresh], 'r');
plot(T(HoughPeaks), maxHough(HoughPeaks), 'rx', 'MarkerSize', 12, 'LineWidth', 2);
hold off
xlabel('Theta Value'); ylabel('Max Hough Transform');
legend({'Max Hough Transform', 'Hough Peak Threshold', 'Detected Peak'});
% Locate site of break
if numel(HoughPeaks) > 1;
BreakStack = zeros(size(img, 1), size(img, 2), numel(HoughPeaks));
% Convolute edge image with line of detected angle from hough transform
for m = 1:numel(HoughPeaks);
boneKernel = strel('line', HoughConvolutionLength, T(HoughPeaks(m)));
kern = double(bwmorph(boneKernel.getnhood(), 'dilate', HoughConvolutionDilate));
BreakStack(:,:,m) = imfilter(edgeImg, kern).*edgeImg;
end
% Take difference between convolution images. Where this crosses zero
% (within tolerance) should be where the break is. Have to filter out
% regions elsewhere where the bone simply ends.
brImg = abs(diff(BreakStack, 1, 3)) < BreakLineTolerance*max(BreakStack(:)) & edgeImg > 0;
[BpY, BpX] = find(abs(diff(BreakStack, 1, 3)) < BreakLineTolerance*max(BreakStack(:)) & edgeImg > 0);
brImg = bwmorph(brImg, 'dilate', breakPointDilate);
brReg = regionprops(brImg, 'Area', 'MajorAxisLength', 'MinorAxisLength', ...
'Orientation', 'Centroid');
brReg(vertcat(brReg.Area) ~= max(vertcat(brReg.Area))) = [];
% Calculate bounding ellipse
brReg.EllipseCoords = zeros(100, 2);
t = linspace(0, 2*pi, 100);
brReg.EllipseCoords(:,1) = brReg.Centroid(1) + brReg.MajorAxisLength/2*cos(t - brReg.Orientation);
brReg.EllipseCoords(:,2) = brReg.Centroid(2) + brReg.MinorAxisLength/2*sin(t - brReg.Orientation);
else
brReg = [];
end
% Draw ellipse around break location
figure(2)
imshow(img)
hold on
colormap('gray')
if ~isempty(brReg)
plot(brReg.EllipseCoords(:,1), brReg.EllipseCoords(:,2), 'r');
end
hold off

Why does hough not find line?

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: