Matlab: find the contour and straighten a nearly rectangular image
6 views (last 30 days)
Show older comments
Hello,
I have got this image https://www.dropbox.com/s/5hmy6tb3ym42tic/rect.jpg?m which is rectangle-like but not exactly.
I would like to find rectangular contours and I have tried to use edge and hough but it doesn't find continuous line. I have also tried to erode and dilate but it can't erase the difference of one pixel on the horizontal upper most line for example so it still doesn't find the continuous line. The second part of the problem would be to straighten it.
Another idea I got was to find the corners to link them with straight lines but it doesn't work either.
I am sure it shouldn't be complicated but I can't make it. Any ideas will be welcome!
Cheers
0 Comments
Accepted Answer
Teja Muppirala
on 7 Mar 2013
I've done this before: http://www.mathworks.com/videos/solving-a-sudoku-puzzle-using-a-webcam-68773.html
This is the strategy that I used and it seemed to work on your image as well. Basically you search for the corners, and then use IMTRANSFORM to transorm the corners into a rectangle. (I'll assume your image is called I).
%%1. Get rid of the white border
I2 = imclearborder(im2bw(I));
%%2. Find each of the four corners
[y,x] = find(I2);
[~,loc] = min(y+x);
C = [x(loc),y(loc)];
[~,loc] = min(y-x);
C(2,:) = [x(loc),y(loc)];
[~,loc] = max(y+x);
C(3,:) = [x(loc),y(loc)];
[~,loc] = max(y-x);
C(4,:) = [x(loc),y(loc)];
%%3. Plot the corners
imshow(I); hold all
plot(C([1:4 1],1),C([1:4 1],2),'r','linewidth',3);
%%4. Find the locations of the new corners
L = mean(C([1 4],1));
R = mean(C([2 3],1));
U = mean(C([1 2],2));
D = mean(C([3 4],2));
C2 = [L U; R U; R D; L D];
%%5. Do the image transform
figure
T = cp2tform(C ,C2,'projective');
IT = imtransform(im2bw(I),T); %IM2BW is not necessary
imshow(IT); hold all
0 Comments
More Answers (2)
Image Analyst
on 7 Mar 2013
Carine:
You can straighten your image with imtransform(), like in this demo I wrote for you using your uploaded image:
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
imtool close all; % Close all imtool figures if you have the Image Processing Toolbox.
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 20;
% Change the current folder to the folder of this m-file.
if(~isdeployed)
cd(fileparts(which(mfilename)));
end
% Check that user has the Image Processing Toolbox installed.
hasIPT = license('test', 'image_toolbox');
if ~hasIPT
% User does not have the toolbox installed.
message = sprintf('Sorry, but you do not seem to have the Image Processing Toolbox.\nDo you want to try to continue anyway?');
reply = questdlg(message, 'Toolbox missing', 'Yes', 'No', 'Yes');
if strcmpi(reply, 'No')
% User said No, so exit.
return;
end
end
% Read in a standard MATLAB gray scale demo image.
folder = 'C:\Users\Carine\Documents';
baseFileName = 'rect.jpg';
% Get the full filename, with path prepended.
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% File doesn't exist -- didn't find it there. Check the search path for it.
fullFileName = baseFileName; % No path this time.
if ~exist(fullFileName, 'file')
% Still didn't find it. Alert user.
errorMessage = sprintf('Error: %s does not exist in the search path folders.', fullFileName);
uiwait(warndlg(errorMessage));
return;
end
end
grayImage = imread(fullFileName);
% Get the dimensions of the image.
% numberOfColorBands should be = 1.
[rows columns numberOfColorBands] = size(grayImage);
if numberOfColorBands > 1
grayImage = grayImage(:,:,2); % Take green channel
end
% Binarize the image
binaryImage1 = grayImage > 128;
% Get rid of the white border
binaryImage1 = imclearborder(binaryImage1);
% Display the original gray scale image.
subplot(2, 2, 1);
imshow(binaryImage1, []);
title('Binary Image', 'FontSize', fontSize);
% Enlarge figure to full screen.
set(gcf, 'units','normalized','outerposition',[0 0 1 1]);
% Give a name to the title bar.
set(gcf,'name','Demo by ImageAnalyst','numbertitle','off')
% Fill the object
binaryImage2 = imfill(binaryImage1, 'holes');
% Find the boundaries
boundaries = bwboundaries(binaryImage2);
xCoords = boundaries{1}(:, 2);
yCoords = boundaries{1}(:, 1);
% Find out which index is closest to the upper left corner
distances = sqrt((xCoords - 1).^2 + (yCoords - 1).^2);
[minDistanceUL, minIndexUL] = min(distances)
% Find out which index is closest to the upper right corner
distances = sqrt((xCoords-columns).^2 + (yCoords - 1).^2);
[minDistanceUR, minIndexUR] = min(distances)
% Find out which index is closest to the lower left corner
distances = sqrt((xCoords - 1).^2 + (yCoords - rows).^2);
[minDistanceLL, minIndexLL] = min(distances)
% Find out which index is closest to the lower right corner
distances = sqrt((xCoords - columns).^2 + (yCoords - rows).^2);
[minDistanceLR, minIndexLR] = min(distances)
% Plot circles over the corners, just for visualization purposes - for fun.
xCorners = [xCoords(minIndexUL), xCoords(minIndexUR), xCoords(minIndexLR), xCoords(minIndexLL)]
yCorners = [yCoords(minIndexUL), yCoords(minIndexUR), yCoords(minIndexLR), yCoords(minIndexLL)]
hold on;
plot(xCorners, yCorners, 'ro');
title('Bad image with corners located', 'FontSize', fontSize);
% Determine ideal corner locations - aligned with raster lines
x1 = mean([xCorners(1), xCorners(4)])
x2 = mean([xCorners(2), xCorners(3)])
y1 = mean([yCorners(1), yCorners(2)])
y2 = mean([yCorners(3), yCorners(4)])
% Show this
subplot(2, 2, 2);
imshow(binaryImage1);
hold on;
plot([x1 x2 x2 x1 x1], [y1 y1 y2 y2 y1], 'r-', 'LineWidth', 3);
title('Bad image with perfect rectangular overlaid', 'FontSize', fontSize);
% Warp the image to straighten it.
badXY = [xCorners; yCorners]'
desiredXY = [x1 x2 x2 x1; y1 y1 y2 y2]'
% Transform to a quadrilateral with vertices badXY
% into a quadrilateral with vertices desiredXY.
tform = maketform('projective', badXY, desiredXY);
% Fix/warp the image.
[binaryImage3, xdata, ydata] = imtransform(binaryImage1, ...
tform, 'bicubic', 'size', size(binaryImage1));
% Display the fixed image.
subplot(2, 2, 3);
imshow(binaryImage3);
title('Fixed image', 'FontSize', fontSize);
0 Comments
See Also
Categories
Find more on Call C++ from MATLAB in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!