how can I verify that a set of 4 points have undergone an affine transformation - affinetransform

I have two images containing same object with 4 corners.
I have a correspondence for those 4 points between images.
Let us call these points as A,B,C,D .
I have (x,y) coordinates of A in image 1 and image 2 .
Similiarly , for points B,C,D .
My aim is to verify that if there exists an affine transformation that satisfies this coordinate change of these 4 points.
How should I proceed ?
It would be beneficial if there is a code in python or c so that I can quickly verify for many images.
My understanding is that a general affine transformation can be described by
x'=ax+by+c
y'=dx+ey+f
So there are six unknowns.
Thanks for reading.

Let's say your points are A=(x1,y1); B=(x2,y2); C=(x3;y3); D=(x4,y4) in image 1 and A'=(x1',y1'); B'=(x2',y2'); C'=(x3';y3'); D'=(x4',y4') in image 2.
You already figured out that finding the affine transformation requires you to find the six unknowns. To find them, just write down the system of linear equations and solve:
x1' = a x1 + b y1 + c
y1' = d x1 + e y1 + f
x2' = a x2 + b y2 + c
y2' = d x2 + e y2 + f
x3' = a x3 + b y3 + c
y3' = d x3 + e y3 + f
x4' = a x4 + b y4 + c
y4' = d x4 + e y4 + f
You can actually split this into two systems of linear equations:
x1' = a x1 + b y1 + c
x2' = a x2 + b y2 + c
x3' = a x3 + b y3 + c
x4' = a x4 + b y4 + c
and
y1' = d x1 + e y1 + f
y2' = d x2 + e y2 + f
y3' = d x3 + e y3 + f
y4' = d x4 + e y4 + f
Since you are only interested in whether there exists an affine transformation (but not in the values of a, b, c, d, e, f itself), you just have to determine if these two systems of linear equations have a solution or not.
The Rouché–Capelli theorem tells us that a system of linear equations has a solution if and only if the rank of the coefficient matrix equals the rank of the augmented matrix.
In your case, the coefficient matrix for both systems of linear equations is
| x1 y1 1 |
| x2 y2 1 |
| x3 y3 1 |
| x4 y4 1 |
The augmented matrix for the first system of linear equations is
| x1 y1 1 x1' |
| x2 y2 1 x2' |
| x3 y3 1 x3' |
| x4 y4 1 x4' |
and for the second system of linear equations it is
| x1 y1 1 y1' |
| x2 y2 1 y2' |
| x3 y3 1 y3' |
| x4 y4 1 y4' |
Now compute the ranks of these three matrices (for example with numpy.linalg.matrix_rank) and if they are all equal, there exists an affine transformation.

Related

How to find transformation matrix from the output with Gaussian noise?

For the below given input and output, the matrix A can be found out by pseudoinverse or mrdivision in MATLAB. Similarly, I would now like to know, how to determine A, if my output signal Y matrix contains additive zero mean, uncorrelated, Gaussian noise?
x1 = [1 1 1]';
x2 = [0 1 1]';
x3 = [0 0 1]';
x4 = [1 0 1]';
y1 = [1 2 0]';
y2 = [-1 0 3]';
y3 = [3 1 1]';
y4 = [5 3 -2]';
X = [x1 x2 x3 x4];
Y = [y1 y2 y3 y4];
A = Y/X
Also, I have modelled the unknown noisy output as below:
y1_n = y1 + sqrt(var(y1))*randn(size(y1));
y2_n = y2 + sqrt(var(y2))*randn(size(y2));
y3_n = y3 + sqrt(var(y3))*randn(size(y3));
y4_n = y4 + sqrt(var(y4))*randn(size(y4));
Y = [y1_n y2_n y3_n y4_n];
The statement A = Y/X solves the linear system of equations A*X = Y. If the system is overdetermined, as in your case, the solution given is the least squares solution. Thus, if you have additive, zero mean, uncorrelated, Gaussian noise on Y, then A = Y/X will give you the best possible, unbiased, estimate of A.
Note that the noise you add to your Y matrix is quite large, hence the estimate of A is far away from the ideal. If you add less noise, the estimate will be closer:
x1 = [1 1 1]';
x2 = [0 1 1]';
x3 = [0 0 1]';
x4 = [1 0 1]';
X = [x1 x2 x3 x4];
y1 = [1 2 0]';
y2 = [-1 0 3]';
y3 = [3 1 1]';
y4 = [5 3 -2]';
Y = [y1 y2 y3 y4];
for n = [1,0.1,0.01,0]
Y_n = Y + n*randn(size(Y));
A = Y_n/X;
fprintf('n = %f, A = \n',n)
disp(A)
end
Output:
n = 1.000000, A =
2.9728 -5.5407 2.8011
2.6563 -1.3166 0.6596
-3.3366 1.1349 1.5342
n = 0.100000, A =
2.0011 -4.0256 2.9402
1.9223 -1.0029 1.0921
-3.1383 1.9874 1.0913
n = 0.010000, A =
1.9903 -3.9912 2.9987
1.9941 -1.0001 1.0108
-3.0015 2.0001 1.0032
n = 0.000000, A =
2.0000 -4.0000 3.0000
2.0000 -1.0000 1.0000
-3.0000 2.0000 1.0000
Of course if you make X and Y larger by adding more vectors you'll get a better estimate too, and will be able to compensate more noisy data.

large number of linear equations in MATLAB

I want to use solve() to solve a large system of linear equations. The solve() function needs equations and variables. I use a loop to generate the equations and my variables are contained in a large array. This is a simple code of what I am trying to do:
x = sym('x',[1 3])
eqn = sym('eqn', [1,3])
eqn1 = 2*x1 + x2 + x3 - 2 == 0
eqn2 = 2*x2 -x2 -x1- x3 == 3
eqn3 = 2*x2+ x1 + 3*x3 == -10
Y = solve(eqn, x)
MATLAB does not recognize my variable x1. I have solved the same system using the following code:
syms x1 x2 x3
eqn1 = 2*x1 + x2 + x3 == 2
eqn2 = 2*x2 -x2 -x1 - x3 == 3
eqn3 = 2*x2+ x1 + 3*x3 == -10
X = solve([eqn1, eqn2, eqn3, eqn4], [x1 x2 x3])
structfun(#subs,X)
But this is useless for a very large number of equations. What am I doing wrong?
You don't need symbolic (syms) for that. This is a standard linear system of equations that can be represented as:
Ax = b where A = [2 1 1; -1 1 -1; 1 2 3], x = [x1; x2; x3] and b = [0; 3; -10]
To solve for x, you would first define
A = [2 1 1; -1 1 -1; 1 2 3]
and
b = [0; 3; -10]
and then solve using
x = A\b
PS. There are some odd things in your question, eg. in eq.2 eqn2 = 2*x2 -x2 -x1- x3 == 3 I assume you omitted simplying this to -x1 +x2 -x3 ==3.
PS2. This is pretty standard Matlab, you can find a lot of info under the standard mldivide page in the documentation along with a lot similar questions here on SO.

Symbolic comprision operation and summation cant get right answer

I'm confused about MATLAB's symbolic operation precedence. My code does not produce the desired output.
syms x1 x2 x3 x4
aa=((x1 == 0 & x2 == 0 & x3 == 0 & x4 == 0) + ((9*x1)/50 + (327*x2)/2000 + (1841*x3)/20000 + (1799*x4)/20000));
bb=eval(subs(aa, [x1 x2 x3 x4], [0.2 0.2 0.2 0.2]))
I expect the output of
bb=
0.1051
but the actual output is
bb =
logical
0
Why does MATLAB do this?
I use MATLAB R2018b
Case 1: x == y
syms x y z
aa = (x == y) + z
Meaning
aa = [x or y] + z = x + z = y + z
Wherever you have x, you can replace it by y, interchangeably.
It does not check if x and y are the same
Case 2: isequal(x, y)
syms x y z
aa = (x == y) + z
aa = isequal(x, y) + z
Meaning
aa = [check if x and y are the same] + z = 0 + z = z
Modify the given code to this using isequal()
syms x1 x2 x3 x4
aa=((isequal(x1, 0)& isequal(x2, 0) & isequal(x3, 0) & isequal(x4, 0)) + ...
((9*x1)/50 + (327*x2)/2000 + (1841*x3)/20000 + (1799*x4)/20000));
bb=eval(subs(aa, [x1 x2 x3 x4], [0.2 0.2 0.2 0.2]));
Result
bb = 0.1051
I think MATLAB tries to reduce the number of brackets necessary to produce the simplest output. Note that if a is equal to b, a+c is also equal to b+c, so the statement is not wrong. If you call simplify(aa) you even get a simple a == b, which is indeed the simplest form as one can cancel the c on both sides:
syms a b c
aa=(a==b)+c
aa =
a + c == b + c
pretty(aa)
a + c == b + c
simplify(aa)
ans =
a == b
With respect to your edited question: why are you using symbolic variables at all? They are slow and cumbersome (not to speak about the unspeakable evil that is eval). Using numeric computation does yield the correct result:
syms x1 x2 x3 x4
aa=((x1 == 0 & x2 == 0 & x3 == 0 & x4 == 0) + ((9*x1)/50 + (327*x2)/2000 + (1841*x3)/20000 + (1799*x4)/20000));
bb=eval(subs(aa, [x1 x2 x3 x4], [0.2 0.2 0.2 0.2]))
bb =
logical
0
x1=0.2;x2=0.2;x3=0.2;x4=0.2;
(x1 == 0 & x2 == 0 & x3 == 0 & x4 == 0)
ans =
logical
0
((9*x1)/50 + (327*x2)/2000 + (1841*x3)/20000 + (1799*x4)/20000)
ans =
0.1051
aa=((x1 == 0 & x2 == 0 & x3 == 0 & x4 == 0) + ((9*x1)/50 + (327*x2)/2000 + (1841*x3)/20000 + (1799*x4)/20000))
aa =
0.1051
I suspect the problem is somewhere in the belly of subs and/or eval.

Trouble using fmincon in MATLAB

I am writing an algorithm for my project , and at some point I need to find the value of alpha that will minimize a function subject to constraints.
Error : Using horzcat Nonscalar arrays of function handles are not
allowed; use cell arrays instead.
This is what I have
syms x1 x2 x3 x4;
syms alpha;
f=(exp(x1))*(4*(x1).^2 + 2*(x2).^2 + 4*(x1)*(x2) + 2*(x2) + 1) + 0*x3 + 0*x4;
%constraints must be equal to 0
g1=x1*x2-x1-x2+x3+1.5;
g2=x1*x2-x4+10;
%Give initial values, given that x1 is between -10 and -9 and x2 is between
%1 and 1.5, and the slacks x3 and x4 are strictly between 0 and 1.
lb=[-10 1 0 0];
ub=[-9 1.5 1 1];
xo=[-9 1 0.1 0.1];
if (-10<=xo(1)) && (xo(1)<=-9) && (1<=xo(2)) && (xo(2)<=1.5)
xi(1)=xo(1);
xi(2)=xo(2);
xd(1)=xo(3);
xd(2)=xo(4);
end
%Evaluation of Gradient of f
gradfi(1,1)=subs(diff(f,x1),{x1 x2 x3 x4},{xi(1) xi(2) xd(1) xd(2)});
gradfi(2,1)=subs(diff(f,x2),{x1 x2 x3 x4},{xi(1) xi(2) xd(1) xd(2)});
gradfd(1,1)=subs(diff(f,x3),{x1 x2 x3 x4},{xi(1) xi(2) xd(1) xd(2)});
gradfd(2,1)=subs(diff(f,x4),{x1 x2 x3 x4},{xi(1) xi(2) xd(1) xd(2)});
%Evaluation of Jacobian Matrix
Ji1=subs(jacobian(g1,[x1 x2]),{x1 x2 x3 x4},{xi(1) xi(2) xd(1) xd(2)});
Ji2=subs(jacobian(g2,[x1 x2]),{x1 x2 x3 x4},{xi(1) xi(2) xd(1) xd(2)});
Ji=[Ji1;Ji2];
Jd1=subs(jacobian(g1,[x3 x4]),{x1 x2 x3 x4},{xi(1) xi(2) xd(1) xd(2)});
Jd2=subs(jacobian(g2,[x3 x4]),{x1 x2 x3 x4},{xi(1) xi(2) xd(1) xd(2)});
Jd=[Jd1;Jd2];
gammai=-(gradfi - ((gradfd.')*Jd^(-1)*Ji).');
deltad=-Jd^(-1)*Ji*(gammai);
x1=xi(1)+gammai(1)*alpha;
x2=xi(2)+gammai(2)*alpha;
x3=xd(1)+deltad(1)*alpha;
x4=xd(2)+deltad(1)*alpha;
falpha =matlabFunction((exp(x1))*(4*(x1).^2 + 2*(x2).^2 + 4*(x1)*(x2) + 2*(x2) + 1) + 0*x3 + 0*x4);
c=([-10-x1; x1+9; -x2+1;x2-1.5;-x3;x3-1;-x4;x4-1]);
ceq=([x1*x2-x1-x2+x3+1.5;x1*x2-x4+10]);
const=([matlabFunction(c), ceq]);
[alpha]=fmincon(falpha,0,[],[],[],[],[],[],const);

Solve for influence of nodes in graph in Matlab

I have a directed, unweighted graph with 5 nodes: x1 through x5. The edges are:
x1->x3
x2->x1
x2->x5
x3->x2
x3->x4
x4->x5
x5->x2
I want to solve this set of equations corresponding to the graph:
x1 = alpha * x2
x2 = alpha * (x3 + x5)
x3 = alpha * x1
x4 = alpha * x3
x5 = alpha * (x2 + x4)
x1 + x2 + x3 + x4 + x5 = 1
How can I set up these equations and solve in Matlab? I want the values of x1 through x5 for which the equations hold.
Here is the solution that worked for me:
syms a b c d e alpha
S = solve(-a+alpha*b==0, -b+alpha*c+alpha*d==0, alpha*a-c==0, alpha*c-d==0, ...
alpha*d-e==0, a+b+c+d+e==1);
S = [S.a S.b S.c S.d S.e S.alpha]