Discover MakerZone

MATLAB and Simulink resources for Arduino, LEGO, and Raspberry Pi

Learn more

Discover what MATLAB® can do for your career.

Opportunities for recent engineering grads.

Apply Today

Thread Subject:
affine mapping (scale, rotation, translation)

Subject: affine mapping (scale, rotation, translation)

From: Bruno

Date: 31 Aug, 2009 18:27:19

Message: 1 of 12

Hello,

given 4 vertices of a rectangle, and an inside point p1(x,y),
how to translate the shape to the reference point p2(x,y)?
There may be a scaling given by 's' and a rotation given by 'r', in radians.

After some time, I solved this by:
> calculating the 4 diagonals involving p1 and the vertices (modulus, angle)
> applying the scale and rotation
> translating them to rectangular coordinates
> drawing the new shape around p2

I'm sure there are more straightforward ways to do this. Could I use maketform( )
and tformarray( )? Remember that it's not an image, but a set of points. And what
about 'affine mapping', how could I use this kind of arrays:

scale = 1.2; % scale factor
angle = 40*pi/180; % rotation angle
tx = 0; % x translation
ty = 0; % y translation

sc = scale*cos(angle);
ss = scale*sin(angle);

T = [ sc -ss;
      ss sc;
      tx ty];

By the way, I was going crazy drawing a rectangle using line( ), because the points
must be in sequence... I didn't find any particular set of functions to draw geometric shapes,
is there any? Rectangle( ) won't do it, because it's not always colinear with axes (can be rotated).

thanks a lot,
Bruno Marchesi.

----

The actual code I've came with is something like this:

keyb1x = grupo(5, 1); keyb1y = grupo(6, 1);
u = repmat([keyb1x, keyb1y], 5,1);
vb = [ 1,1; 1, size(Ib,1); size(Ib,2), size(Ib,1); size(Ib,2), 1; 1,1];
y = vb - u;

z = [ sqrt(y(:,1).^2+y(:,2).^2).*em , atan2(y(:,2),y(:,1)) + am ];

w = [ z(:,1) .* cos(z(:,2)) , z(:,1) .* sin(z(:,2))];

keya1x = grupo(1, 1); keya1y = grupo(2, 1);
o = repmat([keya1x, keya1y], 5,1);

f = o+w;

h = line( f(:,1), f(:,2) ); set(h,'linewidth', 2.0, 'color', 'magenta') ;

Subject: affine mapping (scale, rotation, translation)

From: Matt

Date: 31 Aug, 2009 18:40:23

Message: 2 of 12

"Bruno " <bruno.marchesi@gmail.com> wrote in message <h7h4m7$e5$1@fred.mathworks.com>...
> Hello,
>
> given 4 vertices of a rectangle, and an inside point p1(x,y),
> how to translate the shape to the reference point p2(x,y)?
> There may be a scaling given by 's' and a rotation given by 'r', in radians.
>
> After some time, I solved this by:
> > calculating the 4 diagonals involving p1 and the vertices (modulus, angle)
> > applying the scale and rotation
> > translating them to rectangular coordinates
> > drawing the new shape around p2
>
> I'm sure there are more straightforward ways to do this. Could I use maketform( )
> and tformarray( )? Remember that it's not an image, but a set of points. And what
> about 'affine mapping', how could I use this kind of arrays:
>
> scale = 1.2; % scale factor
> angle = 40*pi/180; % rotation angle
> tx = 0; % x translation
> ty = 0; % y translation
>
> sc = scale*cos(angle);
> ss = scale*sin(angle);
>
> T = [ sc -ss;
> ss sc;
> tx ty];

Looks fine. To transform a point (x,y), just premultiply T by [x,y,1].
 

Subject: affine mapping (scale, rotation, translation)

From: Bruno

Date: 1 Sep, 2009 11:44:03

Message: 3 of 12

"Matt " <xys@whatever.com> wrote in message <h7h5en$ij0$1@fred.mathworks.com>...
> "Bruno " <bruno.marchesi@gmail.com> wrote in message <h7h4m7$e5$1@fred.mathworks.com>...
> > Hello,
> >
> > given 4 vertices of a rectangle, and an inside point p1(x,y),
> > how to translate the shape to the reference point p2(x,y)?
> > There may be a scaling given by 's' and a rotation given by 'r', in radians.
> >
> > After some time, I solved this by:
> > > calculating the 4 diagonals involving p1 and the vertices (modulus, angle)
> > > applying the scale and rotation
> > > translating them to rectangular coordinates
> > > drawing the new shape around p2
> >
> > I'm sure there are more straightforward ways to do this. Could I use maketform( )
> > and tformarray( )? Remember that it's not an image, but a set of points. And what
> > about 'affine mapping', how could I use this kind of arrays:
> >
> > scale = 1.2; % scale factor
> > angle = 40*pi/180; % rotation angle
> > tx = 0; % x translation
> > ty = 0; % y translation
> >
> > sc = scale*cos(angle);
> > ss = scale*sin(angle);
> >
> > T = [ sc -ss;
> > ss sc;
> > tx ty];
>
> Looks fine. To transform a point (x,y), just premultiply T by [x,y,1].
>

It didn't work at all. Looking to the intermediate results, something is not ok.
Suppose scale = 1.2 and angle = 0 (no rotation), tx=ty=0.
All x and y values increase, which is clearly not right.

If there are 4 rectangle corners, it is expected that some coordinates increase, while
others decrease, to expand the area of the shape. This method doesn't appear to accomplish that.


Thank you

Subject: affine mapping (scale, rotation, translation)

From: Matt

Date: 1 Sep, 2009 13:52:02

Message: 4 of 12

"Bruno " <bruno.marchesi@gmail.com> wrote in message <h7j1e3$hsp$1@fred.mathworks.com>...

> If there are 4 rectangle corners, it is expected that some coordinates increase, while
> others decrease, to expand the area of the shape. This method doesn't appear to accomplish that.


That's only true if some of the coordinates are negative. Otherwise, there's no reason why all coordinates can't increase. When I run your example as follows, I get exactly what I expect and no coordinates decrease:

 
scale = 1.2; % scale factor
angle = 0; % rotation angle
tx = 0; % x translation
ty = 0; % y translation

sc = scale*cos(angle);
ss = scale*sin(angle);

T = [ sc -ss;
      ss sc;
      tx ty];

vertices=[0 0 ; 1 0; 0 1; 1 1]

vertices(:,3)=1;


newvertices=vertices*T,

%%%%Output

vertices =

     0 0
     1 0
     0 1
     1 1


newvertices =

         0 0
    1.2000 0
         0 1.2000
    1.2000 1.2000


The original points are the vertices of a unit square and the new vertices are those of a square 1.2 times as big.

Subject: affine mapping (scale, rotation, translation)

From: Bruno

Date: 1 Sep, 2009 15:20:03

Message: 5 of 12

"Matt " <xys@whatever.com> wrote in message <h7j8u2$c13$1@fred.mathworks.com>...
> "Bruno " <bruno.marchesi@gmail.com> wrote in message <h7j1e3$hsp$1@fred.mathworks.com>...
>
> > If there are 4 rectangle corners, it is expected that some coordinates increase, while
> > others decrease, to expand the area of the shape. This method doesn't appear to accomplish that.
>
>
> That's only true if some of the coordinates are negative. Otherwise, there's no reason why all coordinates can't increase. When I run your example as follows, I get exactly what I expect and no coordinates decrease:
>
>
> scale = 1.2; % scale factor
> angle = 0; % rotation angle
> tx = 0; % x translation
> ty = 0; % y translation
>
> sc = scale*cos(angle);
> ss = scale*sin(angle);
>
> T = [ sc -ss;
> ss sc;
> tx ty];
>
> vertices=[0 0 ; 1 0; 0 1; 1 1]
>
> vertices(:,3)=1;
>
>
> newvertices=vertices*T,
>
> %%%%Output
>
> vertices =
>
> 0 0
> 1 0
> 0 1
> 1 1
>
>
> newvertices =
>
> 0 0
> 1.2000 0
> 0 1.2000
> 1.2000 1.2000
>
>
> The original points are the vertices of a unit square and the new vertices are those of a square 1.2 times as big.

You see, your example is not wrong at all. But what about the inherent translation that occured in it? Maybe it's easier to see with these:

10 10
40 10
10 20
20 40

if we only multiply everything, we get:

20 20
80 20
20 40
40 80

Again, it's not wrong. But what I was looking for is that after scalling,
the translation should be kept (as it was) zero. And it is not.

In this example, the only corner that would be greater in both (x,y) directions
after scalling is the last one (20,40), but it would be smaller than (40,80).

thank you

Subject: affine mapping (scale, rotation, translation)

From: Matt

Date: 1 Sep, 2009 16:25:03

Message: 6 of 12

"Bruno " <bruno.marchesi@gmail.com> wrote in message <h7je33$aou$1@fred.mathworks.com>...

> Again, it's not wrong. But what I was looking for is that after scalling,
> the translation should be kept (as it was) zero. And it is not.

It's a little unclear what you're using to define the rectangle's origin and hence its translational position. I assume from your original post that the origin is given by the vector p1 somewhere inside the rectangle. Then you'd probably do best to decompose T into a sequence of four 3x3 homogenous transform matrices, the first for translation, the second for rotation, the third for scaling, and the fourth for translation back to p1. This would look as follows

%%%transform matrices:

Translation=[0 0 -p1(1); 0 0 -p1(2); 0 0 1];
Rotation =[cos(r) -sin(r) 0 ; sin(r) cos(r) 0 ; 0 0 1];
Scaling=[s 0 0; 0 s 0; 0 0 1];
UnTranslation=inv(Translation);

TotalTransform=UnTranslation*Scaling*Rotation*Translation;

Now, to transform a point (x,y), represent it as a column vector X=[x;y;1] in homogeneous coordinates and obtain the transformed point as

Xnew=TotalTransform*X;

Xnew(3)=[]; %Strip away the "1" - return to normal coordinates

Subject: affine mapping (scale, rotation, translation)

From: Bruno

Date: 2 Sep, 2009 11:04:03

Message: 7 of 12

"Matt " <xys@whatever.com> wrote in message <h7jhsv$qir$1@fred.mathworks.com>...
> "Bruno " <bruno.marchesi@gmail.com> wrote in message <h7je33$aou$1@fred.mathworks.com>...
>
> > Again, it's not wrong. But what I was looking for is that after scalling,
> > the translation should be kept (as it was) zero. And it is not.
>
> It's a little unclear what you're using to define the rectangle's origin and hence its translational position. I assume from your original post that the origin is given by the vector p1 somewhere inside the rectangle. Then you'd probably do best to decompose T into a sequence of four 3x3 homogenous transform matrices, the first for translation, the second for rotation, the third for scaling, and the fourth for translation back to p1. This would look as follows
>
> %%%transform matrices:
>
> Translation=[0 0 -p1(1); 0 0 -p1(2); 0 0 1];
> Rotation =[cos(r) -sin(r) 0 ; sin(r) cos(r) 0 ; 0 0 1];
> Scaling=[s 0 0; 0 s 0; 0 0 1];
> UnTranslation=inv(Translation);
>
> TotalTransform=UnTranslation*Scaling*Rotation*Translation;
>
> Now, to transform a point (x,y), represent it as a column vector X=[x;y;1] in homogeneous coordinates and obtain the transformed point as
>
> Xnew=TotalTransform*X;
>
> Xnew(3)=[]; %Strip away the "1" - return to normal coordinates

You're right, it was unclear. What is needed is to maintain the scalled rectangle center
the same as it was before the transforms. If it's just scalling, the center must not change.
That's equivalent to say that when only a scalling/rotation operation is set , the total translation has to be zero.

I saw that the code you've (kindly) provided points to this behaviour, but still the following test code issues a warning because of the inverse (or the matrix division). I could not work that around. So the expression is not functional yet.

thank you

p1=[40,90];
s = 1.0;
r = 0.0;

%pp = zeros(500,650); imagesc(pp); colormap 'gray'; axis off; hold on
%plot(p1(1), p1(2), 'rx');

Translation=[0 0 -p1(1); 0 0 -p1(2); 0 0 1];
Rotation =[cos(r) -sin(r) 0 ; sin(r) cos(r) 0 ; 0 0 1];
Scaling=[s 0 0; 0 s 0; 0 0 1];
UnTranslation=inv(Translation);

TotalTransform=UnTranslation*Scaling*Rotation*Translation;
% or
TotalTransform=Translation\Scaling*Rotation*Translation;

%Now, to transform a point (x,y), represent it as a column vector X=[x;y;1] in homogeneous coordinates and obtain the transformed point as
X=[p1(1);p1(2);1];
Xnew=TotalTransform*X;

Xnew(3)=[]; %Strip away the "1" - return to normal coordinates

Subject: affine mapping (scale, rotation, translation)

From: Matt

Date: 2 Sep, 2009 15:16:03

Message: 8 of 12

"Bruno " <bruno.marchesi@gmail.com> wrote in message <h7ljf2$k3m$1@fred.mathworks.com>...

> I saw that the code you've (kindly) provided points to this behaviour, but still the following test code issues a warning because of the inverse (or the matrix division). I could not work that around. So the expression is not functional yet.
============

Sorry. This line

 Translation=[0 0 -p1(1); 0 0 -p1(2); 0 0 1]; %error

should really be

Translation=[1 0 -p1(1); 0 1 -p1(2); 0 0 1]; %correct version

You will see now that p1 will not change regardless of s and r.

Subject: affine mapping (scale, rotation, translation)

From: Bruno

Date: 2 Sep, 2009 17:34:20

Message: 9 of 12

"Matt " <xys@whatever.com> wrote in message <h7m27j$ig6$1@fred.mathworks.com>...
> "Bruno " <bruno.marchesi@gmail.com> wrote in message <h7ljf2$k3m$1@fred.mathworks.com>...
>
> > I saw that the code you've (kindly) provided points to this behaviour, but still the following test code issues a warning because of the inverse (or the matrix division). I could not work that around. So the expression is not functional yet.
> ============
>
> Sorry. This line
>
> Translation=[0 0 -p1(1); 0 0 -p1(2); 0 0 1]; %error
>
> should really be
>
> Translation=[1 0 -p1(1); 0 1 -p1(2); 0 0 1]; %correct version
>
> You will see now that p1 will not change regardless of s and r.

Indeed the expression solves ok now.
But it's not the correct result.
I think I'll give up for now.

thank you

Subject: affine mapping (scale, rotation, translation)

From: Matt

Date: 2 Sep, 2009 19:50:25

Message: 10 of 12

"Bruno " <bruno.marchesi@gmail.com> wrote in message <h7maas$kkg$1@fred.mathworks.com>...

> Indeed the expression solves ok now.
> But it's not the correct result.


It's working fine for me. In the following example, I take a unit square centered at the origin, scale by 2 and rotate by 45 degrees. I get exactly what I expect, namely a rhombus with vertices on the x,y axes:

p1=[0,0]; %center of square
s = 2.0;
r = pi/4;


Translation=[1 0 -p1(1); 0 1 -p1(2); 0 0 1];
Rotation =[cos(r) -sin(r) 0 ; sin(r) cos(r) 0 ; 0 0 1];
Scaling=[s 0 0; 0 s 0; 0 0 1];
UnTranslation=inv(Translation);

TotalTransform=UnTranslation*Scaling*Rotation*Translation;

%Vertices of unit square centered at p1
X=bsxfun(@plus, [0 0 ; 0 1; 1 0; 1 1]'-.5, p1(:));

X(3,:)=1; %move to homogeneous coordinates.

Xnew=TotalTransform*X;

Xnew(3,:)=[],%Strip away the "1" - return to normal coordinates

>>Xnew =

   -0.0000 -1.4142 1.4142 0.0000
   -1.4142 0.0000 -0.0000 1.4142

Subject: affine mapping (scale, rotation, translation)

From: m krustofski

Date: 7 Sep, 2009 01:16:03

Message: 11 of 12

Hello
Um...I'm not very good at matlab...I am trying to do the same thing with a 3d matrix. Does anyone have any ideas? i have a lot of trouble understanding how to apply stuff like this to my proiect.
thanks
mrs. krusty the clown

Subject: affine mapping (scale, rotation, translation)

From: Bruno

Date: 9 Sep, 2009 13:45:22

Message: 12 of 12

"Matt " <xys@whatever.com> wrote in message <h7mia1$s7s$1@fred.mathworks.com>...
> "Bruno " <bruno.marchesi@gmail.com> wrote in message <h7maas$kkg$1@fred.mathworks.com>...
>
> > Indeed the expression solves ok now.
> > But it's not the correct result.
>
>
> It's working fine for me. In the following example, I take a unit square centered at the origin, scale by 2 and rotate by 45 degrees. I get exactly what I expect, namely a rhombus with vertices on the x,y axes:
>
> p1=[0,0]; %center of square
> s = 2.0;
> r = pi/4;
>
>
> Translation=[1 0 -p1(1); 0 1 -p1(2); 0 0 1];
> Rotation =[cos(r) -sin(r) 0 ; sin(r) cos(r) 0 ; 0 0 1];
> Scaling=[s 0 0; 0 s 0; 0 0 1];
> UnTranslation=inv(Translation);
>
> TotalTransform=UnTranslation*Scaling*Rotation*Translation;
>
> %Vertices of unit square centered at p1
> X=bsxfun(@plus, [0 0 ; 0 1; 1 0; 1 1]'-.5, p1(:));
>
> X(3,:)=1; %move to homogeneous coordinates.
>
> Xnew=TotalTransform*X;
>
> Xnew(3,:)=[],%Strip away the "1" - return to normal coordinates
>
> >>Xnew =
>
> -0.0000 -1.4142 1.4142 0.0000
> -1.4142 0.0000 -0.0000 1.4142

Yes, it worked indeed. After some housekeeping around the code I was dwelling
with, it appears to be all ok.

I reproduced this part of the project right below.

Should you care to have your name mentioned in future works/publications,
please email me your full reference text, ok?

thank you

---------------------------------------------------------------------------

kbx = grupo(5, 1); kby = grupo(6, 1);
kax = grupo(1, 1); kay = grupo(2, 1);


y = - [kbx, kby];
y = y';
y(3,:)=1;


p1=[-kax,-kay];
s = em;
r = am;

Translation=[1 0 -p1(1); 0 1 -p1(2); 0 0 1];
Rotation =[cos(r) -sin(r) 0 ; sin(r) cos(r) 0 ; 0 0 1];
Scaling=[s 0 0; 0 s 0; 0 0 1];

pa = Translation*Scaling*Rotation*y;


pa(3,:)=[];
pa = pa';

% ------------------------------------------------------------


I = mask;

scale = em; % scale factor
alfa = -am; % rotation angle
tx = pa(1); % x translation
ty = pa(2); % y translation
%tx = kax-kbx-23; % x translation
%ty = kay-kby+33; % y translation

sc = scale*cos(alfa);
ss = scale*sin(alfa);

T = [ sc -ss;
      ss sc;
      tx ty];
  
t_nonsim = maketform('affine',T);
[I_nonreflective_similarity,xdata, ydata] = imtransform(I,t_nonsim,'FillValues',.3);

%figure; pp = ones(500,650); imagesc(pp); colormap 'gray'; axis off; hold on
%imshow(I_nonreflective_similarity);
imshow(I_nonreflective_similarity,'XData',xdata,'YData',ydata)
I = I_nonreflective_similarity;

wa=size(Ia,2); ha = size(Ia,1);
wm=size(I,2); hm = size(I,1);
x1 = xdata(1); x2 = xdata(2);
y1 = ydata(1); y2 = ydata(2);

if x1 > 1, vx1 = x1; mx1 = 1; else vx1 = 1; mx1 = 1 - x1; end
if y1 > 1, vy1 = y1; my1 = 1; else vy1 = 1; my1 = 1 - y1; end
if x2 < wa, vx2 = x2; mx2 = wm; else vx2 = wa; mx2 = wm - (x2 - wa); end
if y2 < ha, vy2 = y2; my2 = hm; else vy2 = ha; my2 = hm - (y2 - ha); end

cut = im2single(rgb2gray(Ia));

cut = cut(vy1:vy2, vx1:vx2);
ROI = I(my1:my2, mx1:mx2);

mcut = ROI .* cut;

figure; imshow(mcut); colormap 'gray'; axis off;

Tags for this Thread

What are tags?

A tag is like a keyword or category label associated with each thread. Tags make it easier for you to find threads of interest.

Anyone can tag a thread. Tags are public and visible to everyone.

Contact us