Scale 2D coordinates with respect to the centroid
17 views (last 30 days)
Show older comments
I would like to scale, with respect to the centroid, curves_2.txt such that the Y (or X) coordinates of the marked points of curves_2.txt go to coincide with the Y (or X) coordinates of the marked points of curves_1.txt.
For example, in the image below:
- the point in the green box should go from a value of X=194.887 to X=222
- the point in the pink box must go from a value of X=320,887 to X=293
- the point in the blue box must go from a value of Y=372.21 to Y=360
- the point in the purple box must go from a value of Y=323.21 to Y=333
Is there any way to do this scaling operation (or something similar)? Thanks in advance!
Accepted Answer
Mathieu NOE
on 3 Jan 2023
hello again Alberto
I opted for a simple x, y shrink ratios computation, sufficient to make the red curve match the black one (the new curve is the green one)
I didn't use any of your selected points , I simply used the points with max x and y distance to the centroids
I admit , a very basic approach (no need to worry about centroids shift as they are already overlaid)
load('Curves.mat')
x_curve_1 = sum(curve_1(:,1))/length(curve_1(:,1));
y_curve_1 = sum(curve_1(:,2))/length(curve_1(:,2));
G_curve_1 = [x_curve_1, y_curve_1];
x_curve_2 = sum(curve_2(:,1))/length(curve_2(:,1));
y_curve_2 = sum(curve_2(:,2))/length(curve_2(:,2));
G_curve_2 = [x_curve_2, y_curve_2];
% compute x, y shrink factors based on max ratios
x_factor = max(curve_2(:,1) - G_curve_2(1))./max(curve_1(:,1) - G_curve_1(1));
y_factor = max(curve_2(:,2) - G_curve_2(2))./max(curve_1(:,2) - G_curve_1(2));
x_curve_2new = G_curve_2(1) + (curve_2(:,1) - G_curve_2(1))/x_factor;
y_curve_2new = G_curve_2(2) + (curve_2(:,2) - G_curve_2(2))/y_factor;
figure
plot(curve_1(:,1), curve_1(:,2),'k.', 'MarkerSize', 10);
hold on
plot(curve_2(:,1), curve_2(:,2),'r.', 'MarkerSize', 10);
plot(x_curve_2new, y_curve_2new,'g.', 'MarkerSize', 10);
plot(G_curve_1(:,1), G_curve_1(:,2),'k*', 'MarkerSize', 10);
plot(G_curve_2(:,1), G_curve_2(:,2),'rd', 'MarkerSize', 10);
2 Comments
Image Analyst
on 6 Jan 2023
@Alberto Acri he used x_factor and y_factor. You could put in any factor youi want. Did you even see my answer below where I changed the size from 0.4 to 1.6?
More Answers (2)
William Rose
on 3 Jan 2023
Let's call the curves "curve a" and "curve b". You want to map Xa1=194.887 to Xb1=222, and Xa2=320.887 to Xb2=293. Use the transformation Xb = c1 + c2*Xa:
222=c1 + c2*194.887
293=c1 + c2*320.887
which can be written
which is easily solved to get c1 and c2.
c=inv([1,194.887;1,320.887])*[222;293]
Likewise, for the y transformation, you want to map Ya1=372.21 to Yb1=360 and Ya2=323.21 to Yb2=333, so you do the transformation Yb = d1 + d2*Ya. You determine d1 and d2 by solving
360=d1 + d2*372.21
333=d1 + d2*323.21
d=inv([1,372.21;1,323.21])*[360;333]
Then you use c to transform all the X values from curve a to curve b. You use d to transform the Y values. Good luck!
0 Comments
Image Analyst
on 3 Jan 2023
Try this (Thanks Matt for uploading the mat file):
% Optional initialization steps
clc; % Clear the command window.
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 = 18;
s = load('Curves.mat')
x = s.curve_1(:, 1);
y = s.curve_1(:, 2);
plot(x, y, 'b.', 'MarkerSize',14)
binaryImage = false(max(y), max(x));
for k = 1 : length(x)
binaryImage(y(k), x(k)) = true;
end
imshow(binaryImage)
axis xy; % Flip image
% Get distance transform
edtImage = bwdist(binaryImage);
imshow(edtImage, []);
% threshold(1, 4, edtImage)
mask = imfill(edtImage == 1, 'holes');
% Take largest blob
mask = bwareafilt(mask, 1);
% Get edges
% Plot the borders of all the blobs in the overlay above the original grayscale image
% using the coordinates returned by bwboundaries().
imshow(mask);
% bwboundaries() returns a cell array, where each cell contains the row/column coordinates for an object in the image.
% Here is where we actually get the boundaries for each blob.
boundaries = bwboundaries(mask);
% boundaries is a cell array - one cell for each blob.
% In each cell is an N-by-2 list of coordinates in a (row, column) format. Note: NOT (x,y).
% Column 1 is rows, or y. Column 2 is columns, or x.
numberOfBoundaries = size(boundaries, 1); % Count the boundaries so we can use it in our for loop
% Here is where we actually plot the boundaries of each blob in the overlay.
hold on; % Don't let boundaries blow away the displayed image.
for k = 1 : numberOfBoundaries
thisBoundary = boundaries{k}; % Get boundary for this specific blob.
x = thisBoundary(:,2); % Column 2 is the columns, which is x.
y = thisBoundary(:,1); % Column 1 is the rows, which is y.
plot(x, y, 'r-', 'LineWidth', 2); % Plot boundary in red.
end
hold off;
caption = sprintf('%d Outlines, from bwboundaries()', numberOfBoundaries);
fontSize = 15;
title(caption, 'FontSize', fontSize);
axis('on', 'xy'); % Make sure image is not artificially stretched because of screen's aspect ratio.
% Find centroid and bounding box.
props = regionprops(mask, 'BoundingBox');
% Crop image.
mask = imcrop(mask, props.BoundingBox);
% Recompute centroid on sub image.
props = regionprops(mask, 'Centroid');
figure;
imshow(mask, 'InitialMagnification',1000);
hold on
axis('on', 'image')
xCentroid = props.Centroid(1);
yCentroid = props.Centroid(2);
plot(xCentroid, yCentroid, 'r+', 'LineWidth', 2, 'MarkerSize', 120);
axis xy; % Flip image
% If you want you can get the boundary (x,y) in the new subimage coordinates.
boundaries = bwboundaries(mask);
thisBoundary = boundaries{1}; % Get boundary for this specific blob.
x = thisBoundary(:,2); % Column 2 is the columns, which is x.
y = thisBoundary(:,1); % Column 1 is the rows, which is y.
% Plot curve with a variety of magnification factors
figure
mags = 0.4 : 0.2 : 1.6;
for k = 1 : numel(mags)
thisCurvex = mags(k) * (x - xCentroid) + xCentroid;
thisCurvey = mags(k) * (y - yCentroid) + yCentroid;
plot(thisCurvex, thisCurvey, '-', 'LineWidth', 3);
hold on;
end
plot(xCentroid, yCentroid, 'r+', 'LineWidth', 2, 'MarkerSize', 120);
grid on;
You can see the curves, which has the (x,y) sorted clockwise, displayed all with the same centroid but different magnifications.
10 Comments
Image Analyst
on 8 Jan 2023
To scale curve 2 so that it matched curve 3, make these changes:
scale = sqrt(area3/area2)
xFit = scale * (x2 - xc2) + xc3;
yFit = scale * (y2 - yc2) + yc3;
Basically just swap 2 and 3.
See Also
Categories
Find more on Get Started with Curve Fitting Toolbox in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!