In this part of the project, I created a matrix that would take 3D coordinates and compute their 2D coordinate counterparts.
matrix(y,:) = [Xi Yi Zi 1 0 0 0 0 -ui*Xi -ui*Yi -ui*Zi ...
0 0 0 0 Xi Yi Zi 1 -vi*Xi -vi*Yi -vi*Zi];
[u1
v1
u2
v2
...
un
vn];
M = matrix \ UV;
M = [M; 1];
M = reshape(M,[],3)';
Here, the equation below is followed to retrieve the camera center:
m4 = M(:, 4:4); % This takes a slice of matrix M equivalent to M's 4th (and last) column
Q = M(:, 1:3); % This takes a slice of matrix M equivalent to M's first 3 columns
Center = (-1 * inv(Q)) * m4;
This part of the project is similar in form to the first, as it is simply mapping out a system of equations to then solve. This time, however, the matrix to be solved for is mapping one set of points to another set of points in the same plane. These points are homogenous.
u_prime = Points_a(y,1);
v_prime = Points_a(y,2);
u = Points_b(y,1);
v = Points_b(y,2);
matrix(:, y) = [u*u_prime u*v_prime u v*u_prime v*v_prime v u_prime v_prime 1];
[U, S, V] = svd(matrix);
f = V(:, end);
F = reshape(f, [3 3])';
[U, S, V] = svd(F);
S(3,3) = 0;
F = U*S*V';
In this section, estimate_fundamental_matrix will get called repeatedly, as the algorithm searches for the "best" predictor. I decided to perform 1000 iterations, computing inliers for each fundamental matrix as I go. I have defined an outlier as any pair of values for which xFx' is not between -0.005 and 0.005. After computing inliers, I use the number of inliers to choose whether or not to replace the current "best fundamental matrix." After 1000 iterations, the best fundamental matrix (that which has the maximum number of inliers) and its inliers get returned. The range of -.005 to .005 was decided upon after testing many other options. This number is small enough so that it is selective, but not too conservative such that a small number of inliers gets returned.
Rescaling the data leads to better numerical conditioning. With much smaller discrepancies between numbers, the estimation becomes more precise with fewer rounding errors. This is performed as follows:
a_scale_matrix = [a_scale,0,0; 0,a_scale,0; 0,0,1];
a_shift_matrix = [1,0,-1*a_u_mean; 0,1,-1*a_v_mean; 0,0,1];
a_transform = a_scale_matrix * a_shift_matrix;
F_matrix = b_transform' * F * a_transform;
The effects: