How to split an image and find the coordinates of points already determined
13 次查看(过去 30 天)
显示 更早的评论
My need is to rotate and cut an image in half (image A) in a similar way to image B (created in paint) based on its length and then extract the coordinates of the blue points of each part.
Image A is the final image resulting from my attached code using the image C at the entrance.
I know that cropping an image is a basic operation, but I couldn't do it. I find it difficult due to the presence of the polygon that was drawn in the figure, which is a ROI.
I would appreciate it if someone could help me with this.
Thanks in advance.
A
B
2 个评论
Rik
2020-6-11
Question title:
How to split an image and find the coordinates of points already determined
Question body:
My need is to rotate and cut an image in half (image A) in a similar way to image B (created in paint) based on its length and then extract the coordinates of the blue points of each part.
Image A is the final image resulting from my attached code using the image C at the entrance.
I know that cropping an image is a basic operation, but I couldn't do it. I find it difficult due to the presence of the polygon that was drawn in the figure, which is a ROI.
I would appreciate it if someone could help me with this.
Thanks in advance.
A
B
回答(1 个)
Image Analyst
2020-5-30
Define "half". Is it based on the caliper width from left to right? Or is it based on the number of pixels in each half (you want them to be as close to each other as possible)? Those are different things. Since you didn't say, now I have to do it both ways.
Try this:
% Initialization steps. Brute force cleanup of everything currently existing to start with a clean slate.
% Just for the demo. If you put this into your own function you'll want to get rid of the close and clear commands.
clc; % Clear the command window.
fprintf('Beginning to run %s.m ...\n', mfilename);
close all; % Close all figures (except those of imtool.)
clear; % Erase all existing variables. Or clearvars if you want.
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 15;
s = load('c2.mat')
binaryImage = s.preenc;
subplot(2, 3, 1)
imshow(binaryImage);
title('Original Image', 'FontSize', fontSize);
xlabel('x', 'FontSize', fontSize);
ylabel('y', 'FontSize', fontSize);
%------------------------------------------------------------------------------------------------------------
% Get the right and left half based on equal area (# pixels) in each half.
% Count the number of pixels going across.
horizontalProfile = sum(binaryImage, 1);
subplot(2, 3, 2)
plot(horizontalProfile, 'b-', 'LineWidth', 2);
grid on;
title('Sum of Pixels in Each Column', 'FontSize', fontSize);
xlabel('Column', 'FontSize', fontSize);
ylabel('Count of Pixels In This Column', 'FontSize', fontSize);
% Get the cumulative count from left to right.
subplot(2, 3, 3)
cProfile = cumsum(horizontalProfile);
% Normalize
cProfile = cProfile / cProfile(end) * 100; % Percentage.
plot(cProfile, 'b-', 'LineWidth', 2);
title('Normalized Count of Pixels', 'FontSize', fontSize);
xlabel('Column', 'FontSize', fontSize);
ylabel('Percentage', 'FontSize', fontSize);
% Draw a line across at 50%.
yline(50, 'Color', 'r', 'LineWidth', 2);
grid on;
% Find out where the cumulative count exceeds 50%.
lastCol = find(cProfile < 50, 1, 'last');
xline(lastCol, 'Color', 'r', 'LineWidth', 2);
% Get left and right half based on number of pixels.
leftHalf = binaryImage(:, 1:lastCol);
rightHalf = binaryImage(:, lastCol + 1 : end);
subplot(2, 4, 5)
imshow(leftHalf);
title('Left Half Image, Based on Area', 'FontSize', fontSize);
subplot(2, 4, 6)
imshow(rightHalf);
title('Right Half Image, Based on Area', 'FontSize', fontSize);
fprintf('Left Half goes from column 1 to column %d, based on areas.\n', lastCol);
%------------------------------------------------------------------------------------------------------------
% Get the right and left half based on overall caliper width.
[r, c] = find(binaryImage);
col1 = min(c);
col2 = max(c);
% Get the mid point.
midColumn = (col1 + col2) / 2
% Get left and right half based on number of pixels.
leftHalf = binaryImage(:, 1:floor(midColumn));
rightHalf = binaryImage(:, ceil(midColumn) + 1 : end);
subplot(2, 4, 7)
imshow(leftHalf);
title('Left Half Image, Based on Width', 'FontSize', fontSize);
subplot(2, 4, 8)
imshow(rightHalf);
title('Right Half Image, Based on Width', 'FontSize', fontSize);
fprintf('Left Half goes from column 1 to column %d, based on caliper width.\n', floor(midColumn));
g = gcf;
g.WindowState = 'maximized'
You'll see in the command window how the widths of the halves are different depending on which definition you used:
Left Half goes from column 1 to column 308, based on areas.
Left Half goes from column 1 to column 317, based on caliper width.
I'm not sure how you're defining the blue dots. You might look up bwboundaries() and then pass that into convhull() to get the convex hull points.
boundaries = bwboundaries(binaryImage);
thisBoundary = boundaries{1};
x = thisBoundary(:, 2);
y = thisBoundary(:, 1);
indexes = convhull(x, y);
hold on;
plot(x(indexes), y(indexes), 'b.-', 'MarkerSize', 13, 'LineWidth', 2);
Or you might look up "minimum perimeter polygon" in a search engine -- this is a much more complicated concept and algorithm.
2 个评论
Image Analyst
2020-5-30
OK, if the points are already determined by painting them in with Photoshop or some paint program, then you can read in the RGB image, get a mask for the blue color, and call bwareafilt() to extract just the small circular dots. Then ask regionprops() for the centroid of the blue dots.
clc; % Clear the command window.
close all; % Close all figures (except those of imtool.)
clearvars;
workspace; % Make sure the workspace panel is showing.
format long g;
format compact;
fontSize = 16;
fprintf('Beginning to run %s.m ...\n', mfilename);
%-----------------------------------------------------------------------------------------------------------------------------------
% Read in image.
folder = pwd;
baseFileName = 'image.png';
fullFileName = fullfile(folder, baseFileName);
% Check if file exists.
if ~exist(fullFileName, 'file')
% The file doesn't exist -- didn't find it there in that folder.
% Check the entire search path (other folders) for the file by stripping off the folder.
fullFileNameOnSearchPath = baseFileName; % No path this time.
if ~exist(fullFileNameOnSearchPath, '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
rgbImage = imread(fullFileName);
[rows, columns, numberOfColorChannels] = size(rgbImage);
% Display the test image full size.
subplot(1, 3, 1);
imshow(rgbImage, []);
axis('on', 'image');
caption = sprintf('Reference Image : "%s"', baseFileName);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Set up figure properties:
% Enlarge figure to full screen.
hFig1 = gcf;
hFig1.Units = 'Normalized';
hFig1.WindowState = 'maximized';
% Get rid of tool bar and pulldown menus that are along top of figure.
% set(gcf, 'Toolbar', 'none', 'Menu', 'none');
% Give a name to the title bar.
hFig1.Name = 'Demo by Image Analyst';
[BW, maskedRGBImage] = createMask(rgbImage);
% Display the binary image.
subplot(1, 3, 2);
imshow(BW, []);
axis('on', 'image');
caption = sprintf('Reference Image : "%s"', baseFileName);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
% Get rid of blobs less than 30 in size.
BW = bwareafilt(BW, [1, 30]);
% Display the binary image.
subplot(1, 3, 3);
imshow(BW, []);
axis('on', 'image');
caption = sprintf('Reference Image : "%s"', baseFileName);
title(caption, 'FontSize', fontSize, 'Interpreter', 'None');
drawnow;
hp = impixelinfo(); % Set up status line to see values when you mouse over the image.
props = regionprops(BW, 'Area', 'Centroid');
allAreas = sort([props.Area], 'ascend')
xy = vertcat(props.Centroid)
xCenters = xy(:, 1)
yCenters = xy(:, 2)
hold on;
plot(xCenters, yCenters, 'yo', 'MarkerSize', 20);
function [BW,maskedRGBImage] = createMask(RGB)
%createMask Threshold RGB image using auto-generated code from colorThresholder app.
% [BW,MASKEDRGBIMAGE] = createMask(RGB) thresholds image RGB using
% auto-generated code from the colorThresholder app. The colorspace and
% range for each channel of the colorspace were set within the app. The
% segmentation mask is returned in BW, and a composite of the mask and
% original RGB images is returned in maskedRGBImage.
% Auto-generated by colorThresholder app on 30-May-2020
%------------------------------------------------------
% Convert RGB image to chosen color space
I = rgb2hsv(RGB);
% Define thresholds for channel 1 based on histogram settings
channel1Min = 0.546;
channel1Max = 0.576;
% Define thresholds for channel 2 based on histogram settings
channel2Min = 0.894;
channel2Max = 1.000;
% Define thresholds for channel 3 based on histogram settings
channel3Min = 0.678;
channel3Max = 0.767;
% Create mask based on chosen histogram thresholds
sliderBW = (I(:,:,1) >= channel1Min ) & (I(:,:,1) <= channel1Max) & ...
(I(:,:,2) >= channel2Min ) & (I(:,:,2) <= channel2Max) & ...
(I(:,:,3) >= channel3Min ) & (I(:,:,3) <= channel3Max);
BW = sliderBW;
% Initialize output masked image based on input image.
maskedRGBImage = RGB;
% Set background pixels where BW is false to zero.
maskedRGBImage(repmat(~BW,[1 1 3])) = 0;
end
Image Analyst
2020-5-31
You said "find the coordinates of points already determined" and "created in paint". So I thought you were starting with that image that you created in paint. So that was a big waste of my time. Since you know where the points were, you can delete them. Just get the roi from drawpolygon and call delete(). Good luck.
另请参阅
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!