Project 3 / Camera Calibration and Fundamental Matrix Estimation with RANSAC

Table of Contents

  1. Intro
  2. Code
  3. Results

1. Intro

This project is an implementation of the RANSAC algorithm, along with camera calibration techniques. We estimate the camerica projection and fundamental matrices utilizing 2d and 3d points.

We calibrate the camera given the points, solved through decomposition and linear regression. We get the coordinates of the camera, and solve for the fundamental matrix of rank 2. Then, we implement RANSAC with the fndamental matrix,solving matching features.

2. Code

2a. Camera Calibration

The projection of the 3D world onto the 2D is represented by 'x = K [ R | t ] X', notable the instrinsic and extrinsic matrix for camera positioning and calibration.

This is the calculate_project_matrix main code. We solve the equations.


%Create matrix
M = zeros(3,4);
%set num of points for the algorithm
numPoints = size(Points_2D,1);

a = zeros(numPoints*2, 11);
b = zeros(numPoints*2, 1);


%we use this in order to figure out the camera position and angle.
%this is solved in a least squares regression linear equation

for i= 1:numPoints
   
   X = Points_3D(i,1z);
   Y = Points_3D(i,2);
   Z = Points_3D(i,3);
   
   u = Points_2D(i,1);
   v = Points_2D(i,2);
   
   %odd rows of matrix a
   a(2*i-1,:) = [X Y Z 1 0 0 0 0 -u*X -u*Y -u*Z];
   %even rows
   a(2*i,:) = [0 0 0 0 X Y Z 1 -v*X -v*Y -v*Z];
   
   b(2*i-1) = u;
   b(2*i) = v;
end


M = a\b;
M = [M;1];
M = reshape(M,[],3)';

This is code for figuring out the camera center.


Center = -M(:,1:3)\M(:,4); 

2b. Fundamental Matrix Estimations

Now, we estimate the F matrix based on 2 sets of corresponding matches between the two images. Because we have 9 unknowns in the system of the current fundamental matrix, we need 8+ points to solve for the free variables. There is similarity with the camera calibration with the linear equations solving.

This is from estimate_fundamental_matrix. The code both solves the F matrix as well as having an implementation of matrix normalization. The normalization follows the following:



Points_num = size(Points_a,1);
A = [];
B = -ones(Points_num,1);

%this manages some matrix normalization to transform the matrices and
%rescale them back to penalize the parameters of F in the least squares estimate.


%means of points.
u_a = sum(Points_a(:,1))/numPoints;
v_a = sum(Points_a(:,2))/numPoints;
s = numPoints/sum(((Points_a(:,1)-u_a).^2 + (Points_a(:,2)-v_a).^2).^(1/2));
transA = [s 0 0; 0 s 0; 0 0 1]*[1 0 -u_a; 0 1 -v_a; 0 0 1];
%rescaling the matrix
Points_a = transA*[Points_a ones(numPoints,1)]';
Points_a = Points_a';

u_b = sum(Points_b(:,1))/numPoints;
v_b = sum(Points_b(:,2))/numPoints;
s = numPoints/sum(((Points_b(:,1)-u_b).^2 + (Points_b(:,2)-v_b).^2).^(1/2));
transB = [s 0 0; 0 s 0; 0 0 1]*[1 0 -u_b; 0 1 -v_b; 0 0 1];
%rescaling the matrix
Points_b = transB*[Points_b ones(numPoints,1)]';
Points_b = Points_b';

%this solves for the f Matrix

for n = 1:numPoints
    u1 = Points_a(n,1);
    v1 = Points_a(n,2);
    u2 = Points_b(n,1);
    v2 = Points_b(n,2);
    A(end+1,:) = [u1*u2 v1*u2 u2 u1*v2 v1*v2 v2 u1 v1];
end

F_matrix = A\B;
F_matrix = [F_matrix;1];
F_matrix = reshape(F_matrix,[],3);
F_matrix = transA'*F_matrix*transB;
F_matrix = F_matrix';
[U,S,V] = svd(F_matrix);
S(3,3) = 0;
F_matrix = U*S*V';

2c. Ransac

Now, the code has keypoints, descriptors, matches, camera calibration, and knows how to estimate. We now implement the RANSAC algorithm. We select some random matches/pairs, compute a solution, and interate, eventually finding the best fit given data and outliers.



%various variables to adjust the threshhold and iterations. I chose a large 10k iterations, and a low threshhold.
threshold = 0.001;
bestPoints = 0;
iterations = 10000;

i = 1;
while i < iterations
    count = 0;
    iter = 1;
    k = randsample(size(matches_a, 1), 8);
    pointsA(1:8, :) = matches_a(k, :);
    pointsB(1:8, :) = matches_b(k, :);
    fMatrix = estimate_fundamental_matrix(pointsA, pointsB);
    i = i + 1;

    for j = 1:size(matches_a, 1)
        score = abs([matches_b(j, :), 1]*fMatrix*[matches_a(j, :), 1]');
        if score < threshold
            count = count + 1;
            tempA(iter, :) = matches_a(j, :);
            tempB(iter, :) = matches_b(j, :);
            iter = iter + 1;
        end
    end

    if(count > bestPoints)
        Best_Fmatrix = fMatrix;
        bestPoints = count;
        inliers_a = tempA;
        inliers_b = tempB;
    end
end

3. Results

This is the result for my matrix projection for the normalized pairs.

0.7679 -0.4938 -0.0234 0.0067

-0.0852 -0.0915 -0.9065 -0.0878

0.1827 0.2988 -0.0742 1.0000

This is my camera center. (-1.5126, -2.3517, 0.2827)

This is my coordinate and projections on the 2D Plane

This is my visualization on the 3D plane.

This is the results of Part 2.

This is the results of Part 3.

Inliers: 29

F Matrix for Mount Rushmore.

-0.0000 0.0000 -0.0391

-0.0000 -0.0000 0.0372

0.0389 -0.0338 0.9963

Inliers: 36

F Matrix for Notre Dame.

0.0000 0.0000 -0.0245

-0.0000 -0.0000 0.0290

0.0220 -0.0238 -0.5585

Inliers: 11

F Matrix for Episcopal Gaudi..

0.0000 0.0000 -0.0267

-0.0000 -0.0000 0.0596

0.0144 -0.0409 -1.6638

Inliers: 9

F Matrix for Woodruff Dorm..

-0.0001 0.0000 0.0062

-0.0002 0.0000 0.0933

0.2230 -0.0913 -90.3128