# Scale 2D coordinates with respect to the centroid

20 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

### 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

### Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!