how to straighten lines in an image?
6 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
noam Y
el 6 de Dic. de 2017
Comentada: Image Analyst
el 9 de Dic. de 2017
hello I'm trying to detect lanes in an image and for that I want a way to choose only the lanes part of the image and straighten it to a rectangle, I think there's some function in OpenCV so I was wondering if there is one in Matlab as well or some other way to straighten the image at certain points.
thanks :).
0 comentarios
Respuesta aceptada
Image Analyst
el 6 de Dic. de 2017
Try imwarp().
2 comentarios
Image Analyst
el 9 de Dic. de 2017
You can use imtransform(). Here's a snippet from my program. Go ahead and use/adapt it it you want:
while strcmpi(reply, 'Redraw') > 0
hold off;
imshow(original_RGB_Image);
% hold on;
title('Original Image', 'FontSize', 18);
set(gcf, 'units','normalized','outerposition',[0 0 1 1]); % Maximize figure.
[rows, columns, numberOfColors] = size(original_RGB_Image);
userPrompt = sprintf('Left click at the centers of the corner spots on the 96 well plate\ngoing counter-clockwise from the upper left spot.\nFor the 4th spot (upper right) right-click to finish the quadrilateral.');
uiwait(msgbox(userPrompt));
numberOfVertices = 0;
while numberOfVertices ~= 5
[~, xCorners, yCorners] = roipolyold();
numberOfVertices = length(xCorners);
% Take the first 5 points. If it's less than 5, let them know.
if numberOfVertices > 5
% Take the first 5.
xCorners = xCorners(1:5);
yCorners = yCorners(1:5);
numberOfVertices = length(xCorners); % Recalculate it.
elseif numberOfVertices < 5
userPrompt = sprintf('You clicked %d points.\nPlease click exactly 4 points only.\n\nRemember LEFT-CLICK the first 3 corners,\nthen RIGHT-CLICK the last (4th) point.', numberOfVertices-1);
uiwait(msgbox(userPrompt));
end
end
if printToCommandWindow
fprintf(1, 'x=%.1f ', xCorners);
fprintf(1, '\n');
fprintf(1, 'y=%.1f ', yCorners);
end
% Sort the corners into the first one being the upper left, and then going counter-clockwise after that.
% It won't work otherwise.
[xCorners, yCorners] = sortCorners(xCorners, yCorners, rows, columns);
% Draw the quadrilateral.
hold on;
plot([xCorners(1) xCorners(2) xCorners(3) xCorners(4) xCorners(1)], [yCorners(1) yCorners(2) yCorners(3) yCorners(4) yCorners(1)], 'linewidth', 3, 'color', [1 0 1]); % Top line
caption = sprintf('(%.1f, %.1f)', xCorners(1), yCorners(1));
text(xCorners(1)-25, yCorners(1)+9, caption, 'fontsize', 8, 'Color', [1 1 0]);
caption = sprintf('(%.1f, %.1f)', xCorners(2), yCorners(2));
text(xCorners(2)-25, yCorners(2)+9, caption, 'fontsize', 8, 'Color', [1 1 0]);
caption = sprintf('(%.1f, %.1f)', xCorners(3), yCorners(3));
text(xCorners(3)-25, yCorners(3)+9, caption, 'fontsize', 8, 'Color', [1 1 0]);
caption = sprintf('(%.1f, %.1f)', xCorners(4), yCorners(4));
text(xCorners(4)-25, yCorners(4)+9, caption, 'fontsize', 8, 'Color', [1 1 0]);
% Create the desired coordinates;
x1 = mean([xCorners(1) xCorners(2)]);
x2 = mean([xCorners(3) xCorners(4)]);
y1 = mean([yCorners(1) yCorners(4)]);
y2 = mean([yCorners(2) yCorners(3)]);
% T = maketform('projective',U,X) builds a TFORM struct T for a two-dimensional projective transformation
% that maps each row of U to the corresponding row of X.
% The U and X arguments are each 4-by-2 and define the corners of input and output quadrilaterals.
% No three corners can be collinear.
U = [xCorners(1), yCorners(1);...
xCorners(2), yCorners(2);...
xCorners(3), yCorners(3);...
xCorners(4), yCorners(4)];
X = [x1 y1; x1 y2; x2 y2; x2 y1];
T = maketform('projective', U, X);
% tformfwd([10 20],T)
% Let's see where the corners of the image get moved to.
imageCornersX = [1 1 columns columns];
imageCornersY = [1 rows rows 1];
[mappedCornerLocationsX, mappedCornerLocationsY] = tformfwd(T, imageCornersX, imageCornersY);
if printToCommandWindow
fprintf(1, '%6.3f\n', mappedCornerLocationsX);
fprintf(1, '%6.3f\n', mappedCornerLocationsY);
end
newUpperLeftX = min(mappedCornerLocationsX);
newUpperLeftY = min(mappedCornerLocationsY) ;
% Transform (warp) the image.
transformedImage = imtransform(original_RGB_Image, T);
clear('original_RGB_Image'); % Free up memory for wimpy 32 bit computers.
axes(handles.axesImage);
imshow(transformedImage);
% subplot(1,2,2);
figure(handleToOriginal);
imshow(transformedImage, []);
% set(gcf, 'units','normalized','outerposition',[0 0 1 1]); % Maximize figure.
title('Transformed image', 'FontSize', 18);
drawnow;
hold on;
diameter = UserSettings.circleDiameter; % Diameter of spot or width of rectangle.
% Draw the shapes and bounding box.
% The line was drawn in the centers of the circles, but the circles are drawn with the rectangle function which actually has
% the (x,y) location as the upper left of the bounding box of the circle.
xSpacing = abs(x2 - x1) / (UserSettings.columns - 1);
ySpacing = abs(y2 - y1) / (UserSettings.rows - 1);
% Draw the bounding box.
line([x1 - newUpperLeftX, x2 - newUpperLeftX], [y1 - newUpperLeftY, y1 - newUpperLeftY], 'linewidth', 3, 'color', [1 0 1]); % Top line
line([x1 - newUpperLeftX, x1 - newUpperLeftX], [y1 - newUpperLeftY, y2 - newUpperLeftY], 'linewidth', 3, 'color', [1 0 1]); % Left line
line([x1 - newUpperLeftX, x2 - newUpperLeftX], [y2 - newUpperLeftY, y2 - newUpperLeftY], 'linewidth', 3, 'color', [1 0 1]); % Bottom line
line([x2 - newUpperLeftX, x2 - newUpperLeftX], [y1 - newUpperLeftY, y2 - newUpperLeftY], 'linewidth', 3, 'color', [1 0 1]); % Right line
% Make up arrays of the dpecified shape.
if UserSettings.isCircle
% Initialize an image to hold one single small circle.
smallCircleRadius = diameter / 2.0;
smallCircleImage = zeros(2*smallCircleRadius, 2*smallCircleRadius);
[x, y] = meshgrid(1:smallCircleRadius*2, 1:smallCircleRadius*2);
singleShapeImage = false(2*smallCircleRadius, 2*smallCircleRadius);
singleShapeImage((x - smallCircleRadius).^2 + (y - smallCircleRadius).^2 <= smallCircleRadius.^2) = true;
else
% The shapes are rectangles.
% Initialize an image to hold one single small rectangle.
singleShapeImage = true(diameter);
end
hold off;
% imshow(singleShapeImage, []);
% drawnow;
[transformedRows, transformedCols, transformedNumberOfColors] = size(transformedImage);
shapeMaskArray = false([transformedRows, transformedCols]);
[singleHeight, singleWidth] = size(singleShapeImage);
% x1, x2, y1, and y2 all refer to the center of the circle, not the upper left of the bounding box.
for row = 1 : UserSettings.rows
% yctr0 = (row - 1) * ySpacing + y1;
yctr = (row - 1) * ySpacing + y1 - newUpperLeftY;
boxY = yctr - diameter/2;
for col = 1 : UserSettings.columns
% xctr0 = (col - 1) * xSpacing + x1;
% plot(xctr0, yctr0, '+');
xctr = (col - 1) * xSpacing + x1 - newUpperLeftX;
boxX = xctr - diameter/2;
rectangle('Position',[boxX, boxY, diameter, diameter], 'Curvature',[1,1], 'EdgeColor', [0 .5 0], 'LineWidth', 2);
% caption = sprintf('(%d, %d)', round(xctr), round(yctr));
% text(xctr-25, yctr+9, caption, 'fontsize', 8, 'Color', [1 1 0]);
centers(row, col, 1) = xctr;
centers(row, col, 2) = yctr;
% Find the square in the big image where we're going to add a small circle.
x1b = ClipToRange(boxX, 1, transformedCols);
x2b = ClipToRange((x1b + singleWidth - 1), 1, transformedCols);
y1b = ClipToRange(boxY, 1, transformedRows);
y2b = ClipToRange((y1b + singleHeight - 1), 1, transformedRows);
% Add in one small circle to the existing big image.
shapeMaskArray(y1b:y2b, x1b:x2b) = shapeMaskArray(y1b:y2b, x1b:x2b) + singleShapeImage;
end
end
% It might be 2 if shapes overlap. Make sure the max is 1
shapeMaskArray = min(shapeMaskArray, 1);
% imshow(shapeMaskArray);
% drawnow;
% handleToMaskFigure = figure;
% imshow(circleMaskArray, []);
% set(gcf, 'units','normalized','outerposition',[0 0 1 1]); % Maximize figure.
% Make a visualization where the masked array regions are full brightness but the out of mask regions are half brightness.
% Mask the image using bsxfun() function
maskedRgbImage = bsxfun(@times, transformedImage, cast(shapeMaskArray, class(transformedImage)));
outsideMaskRgbImage = uint8(bsxfun(@times, transformedImage, cast(~shapeMaskArray, class(transformedImage)))/2); % Half brightness.
imshow(maskedRgbImage + outsideMaskRgbImage);
drawnow;
clear('maskedRgbImage', 'outsideMaskRgbImage'); % Free up memory
[labeledImage, numberOfBlobs] = bwlabel(shapeMaskArray, 8); % Label each blob so we can make measurements of it
clear('shapeMaskArray'); % Free up memory.
% Get each plane and its measurements. Then free up the image to reduce memory usage as much as possible for 32 bit computers.
redPlane = transformedImage(:, :, 1);
blobMeasurementsR = regionprops(labeledImage, redPlane, 'all');
clear('redPlane');
greenPlane = transformedImage(:, :, 2);
blobMeasurementsG = regionprops(labeledImage, greenPlane, 'all');
clear('greenPlane');
bluePlane = transformedImage(:, :, 3);
blobMeasurementsBlue = regionprops(labeledImage, bluePlane, 'all');
clear('bluePlane');
if printToCommandWindow
fprintf(1,'Blob # Mean Red, Mean Green, Mean Blue, Centroid-x Centroid-y\n');
end
for k = 1 : numberOfBlobs % Loop through all blobs.
% Find the mean of each blob. (R2008a has a nice way where you can pass the original image
% directly into regionprops.)
thisBlobsPixelsR = blobMeasurementsR(k).PixelIdxList; % Get list of pixels in current blob.
thisBlobsPixelsG = blobMeasurementsG(k).PixelIdxList; % Get list of pixels in current blob.
thisBlobsPixelsBlue = blobMeasurementsBlue(k).PixelIdxList; % Get list of pixels in current blob.
meanGLR = blobMeasurementsR(k).MeanIntensity; % Mean again, but only for version >= R2008a
meanGLG = blobMeasurementsG(k).MeanIntensity; % Mean again, but only for version >= R2008a
meanGLBlue = blobMeasurementsBlue(k).MeanIntensity; % Mean again, but only for version >= R2008a
blobCentroid = blobMeasurementsR(k).Centroid; % Get centroid.
if printToCommandWindow
fprintf(1,' #%d: %8.2f %8.2f %8.2f, %8.1f %8.1f\n', k, meanGLR, meanGLG, meanGLBlue, blobCentroid);
end
text(blobCentroid(1), blobCentroid(2), num2str(k), 'Color', 'g');
end
drawnow;
% Ask user if it's okay.
userPrompt = sprintf('Please verify the mask placement.\nDo you want to accept it, or redraw it?');
reply = questdlg(userPrompt, ...
'Mask OK?', 'Accept', 'Redraw', 'Accept');
drawnow;
% reply = '' for Upper right X, otherwise it's the exact wording.
end
Más respuestas (0)
Ver también
Categorías
Más información sobre Image Processing and Computer Vision en Help Center y File Exchange.
Productos
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!