|
| 1 | +%Camera Calibration Experiments: |
| 2 | +% Jeremy Bredfeldt - Morgridge Institutes for Research |
| 3 | +% Sept 2013 |
| 4 | + |
| 5 | +%Trying to derive the camera calibration matrices from first principles |
| 6 | +%If we know the pose of the camera, then what are the camera matrices? |
| 7 | +%With this, we can ROM check the calibrations generated by the calibration routines |
| 8 | + |
| 9 | +%Then can we use these matrices to triangulate points properly in 3D, based on 2 camera poses? |
| 10 | + |
| 11 | +%Place the origin in the south, west, floor level corner of the atrium |
| 12 | +%Positive x = points east |
| 13 | +%Positive y = points north |
| 14 | +%Positive z = up |
| 15 | +%Rotations: Cameras start pointing in positive z direction, and rotated from there |
| 16 | +% Bottom of camera is pointing in neg y direction |
| 17 | +% Use right hand rule for direction of rotation |
| 18 | + |
| 19 | +%Atrium dimensions |
| 20 | +%39624 mm in x direction |
| 21 | +ax = 39624; |
| 22 | +%10947 mm in y direction |
| 23 | +ay = 10947; |
| 24 | +%15240 mm in z direction |
| 25 | +az = 15240; |
| 26 | + |
| 27 | +%Camera sensor and lens |
| 28 | +%Focal length = 4.2 mm |
| 29 | +fx = 4.2; |
| 30 | +fy = fx; |
| 31 | +%Sensor = 4.54 mm X 3.42 mm |
| 32 | +sx = 4.54/2; |
| 33 | +sy = 3.42/2; |
| 34 | +%Image size = 1280 X 720 pixels |
| 35 | +ix = 1280; |
| 36 | +iy = 720; |
| 37 | + |
| 38 | +%These are in the world's reference frame, to actually get camera matrices, these must be inverted. |
| 39 | +%--Translation-- |
| 40 | +%Camera 1 (west side) |
| 41 | +Cx1 = 0; |
| 42 | +Cy1 = ay/2; %centered in y dim |
| 43 | +Cz1 = az; |
| 44 | +C1 = [Cx1; Cy1; Cz1]; |
| 45 | + |
| 46 | +%Camera 2 (east side) |
| 47 | +Cx2 = ax; |
| 48 | +Cy2 = ay/2; |
| 49 | +Cz2 = az; |
| 50 | +C2 = [Cx2; Cy2; Cz2]; |
| 51 | + |
| 52 | +%--Rotation-- |
| 53 | +%Camera 1 |
| 54 | +thx1 = 0; |
| 55 | +thy1 = pi/1.5; %point 45 deg down |
| 56 | +thz1 = 0; |
| 57 | +Rcx1 = [1 0 0; 0 cos(thx1) -sin(thx1); 0 sin(thx1) cos(thx1)]; |
| 58 | +Rcy1 = [cos(thy1) 0 sin(thy1); 0 1 0; -sin(thy1) 0 cos(thy1)]; |
| 59 | +Rcz1 = [cos(thz1) -sin(thz1) 0; sin(thz1) cos(thz1) 0; 0 0 1]; |
| 60 | +Rc1 = Rcx1*Rcy1*Rcz1; |
| 61 | + |
| 62 | +%Camera 2 |
| 63 | +thx2 = 0; |
| 64 | +thy2 = -pi/1.5; %point 45 deg down |
| 65 | +thz2 = pi; |
| 66 | +Rcx2 = [1 0 0; 0 cos(thx2) -sin(thx2); 0 sin(thx2) cos(thx2)]; |
| 67 | +Rcy2 = [cos(thy2) 0 sin(thy2); 0 1 0; -sin(thy2) 0 cos(thy2)]; |
| 68 | +Rcz2 = [cos(thz2) -sin(thz2) 0; sin(thz2) cos(thz2) 0; 0 0 1]; |
| 69 | +Rc2 = Rcx2*Rcy2*Rcz2; |
| 70 | + |
| 71 | +%Get the actual camera matrices (inverse of the previously written matrices): |
| 72 | +R1 = Rc1'; |
| 73 | +R2 = Rc2'; |
| 74 | +t1 = -R1*C1; %origin in cam 1 ref frame |
| 75 | +t2 = -R2*C2; %origin in cam 2 ref frame |
| 76 | + |
| 77 | +%--Extrinsic-- |
| 78 | +E1 = [R1 t1]; |
| 79 | +E2 = [R2 t2]; |
| 80 | + |
| 81 | +%--Intrinsic-- |
| 82 | +%Assume no skew or translation, and fx and fy are same |
| 83 | +%Assume both cameras are the same |
| 84 | +K = [fx 0 0; 0 fy 0; 0 0 1]; |
| 85 | + |
| 86 | +%--Final Matrices-- |
| 87 | +P1 = K*E1; |
| 88 | +P2 = K*E2; |
| 89 | + |
| 90 | +%--Tests-- |
| 91 | + |
| 92 | +%3D point, middle of the atrium floor: |
| 93 | +x1 = [ax/1.5; ay/3; 6000; 1]; |
| 94 | +%x1 = [C2; 1]; |
| 95 | + |
| 96 | +%Project these points onto the camera image planes |
| 97 | +y11 = P1*x1; |
| 98 | +y12 = P2*x1; |
| 99 | + |
| 100 | +c1x = y11(1)/y11(3) |
| 101 | +c1y = y11(2)/y11(3) |
| 102 | +c2x = y12(1)/y12(3) |
| 103 | +c2y = y12(2)/y12(3) |
| 104 | + |
| 105 | +%Draw the spots on the images |
| 106 | +figure(2); clf; |
| 107 | +plot(c1x,c1y,'r*'); |
| 108 | +axis equal; |
| 109 | +xlim([-sx sx]); |
| 110 | +ylim([-sy sy]); |
| 111 | +title('Camera 1'); |
| 112 | +figure(3); clf; |
| 113 | +plot(c2x,c2y,'k*'); |
| 114 | +axis equal; |
| 115 | +xlim([-sx sx]); |
| 116 | +ylim([-sy sy]); |
| 117 | +title('Camera 2'); |
| 118 | + |
| 119 | +%Create plots of the results |
| 120 | +figure(1); |
| 121 | +clf; |
| 122 | +%draw atrium floor |
| 123 | +plot3([0 ax ax 0 0],[0 0 ay ay 0],[0 0 0 0 0]); |
| 124 | +hold on; |
| 125 | +%draw camera centers |
| 126 | +%plot3(C1(1),C1(2),C1(3),'r*'); |
| 127 | +%plot3(C2(1),C2(2),C2(3),'k*'); |
| 128 | +%draw camera directions |
| 129 | +zd = 2000; |
| 130 | +d = [0; 0; zd; 1]; |
| 131 | +D1 = [Rc1 C1]*d; |
| 132 | +D2 = [Rc2 C2]*d; |
| 133 | +plot3([C1(1) D1(1)],[C1(2) D1(2)],[C1(3) D1(3)],'r'); |
| 134 | +plot3([C2(1) D2(1)],[C2(2) D2(2)],[C2(3) D2(3)],'k'); |
| 135 | + |
| 136 | +%draw camera frustrum |
| 137 | +%create rays in camera frame, then transform to world frame |
| 138 | +%4 rays |
| 139 | +f1 = [sx*zd/fx; sy*zd/fy; zd; 1]; |
| 140 | +f2 = [-sx*zd/fx; sy*zd/fy; zd; 1]; |
| 141 | +f3 = [-sx*zd/fx; -sy*zd/fy; zd; 1]; |
| 142 | +f4 = [sx*zd/fx; -sy*zd/fy; zd; 1]; |
| 143 | +%rays for first camera |
| 144 | +F11 = [Rc1 C1]*f1; |
| 145 | +F12 = [Rc1 C1]*f2; |
| 146 | +F13 = [Rc1 C1]*f3; |
| 147 | +F14 = [Rc1 C1]*f4; |
| 148 | +plot3([C1(1) F11(1)],[C1(2) F11(2)],[C1(3) F11(3)],'r'); |
| 149 | +plot3([C1(1) F12(1)],[C1(2) F12(2)],[C1(3) F12(3)],'r'); |
| 150 | +plot3([C1(1) F13(1)],[C1(2) F13(2)],[C1(3) F13(3)],'r'); |
| 151 | +plot3([C1(1) F14(1)],[C1(2) F14(2)],[C1(3) F14(3)],'r'); |
| 152 | + |
| 153 | +%rays for second camera |
| 154 | +F21 = [Rc2 C2]*f1; |
| 155 | +F22 = [Rc2 C2]*f2; |
| 156 | +F23 = [Rc2 C2]*f3; |
| 157 | +F24 = [Rc2 C2]*f4; |
| 158 | +plot3([C2(1) F21(1)],[C2(2) F21(2)],[C2(3) F21(3)],'k'); |
| 159 | +plot3([C2(1) F22(1)],[C2(2) F22(2)],[C2(3) F22(3)],'k'); |
| 160 | +plot3([C2(1) F23(1)],[C2(2) F23(2)],[C2(3) F23(3)],'k'); |
| 161 | +plot3([C2(1) F24(1)],[C2(2) F24(2)],[C2(3) F24(3)],'k'); |
| 162 | + |
| 163 | +%draw test point |
| 164 | +plot3(x1(1),x1(2),x1(3),'b*'); |
| 165 | +%draw projection result |
| 166 | + |
| 167 | +xlabel('South Wall (x, mm)'); |
| 168 | +ylabel('West Wall (y, mm)'); |
| 169 | +zlabel('(z, mm)'); |
| 170 | +axis equal; |
| 171 | + |
| 172 | +na = 0.01; |
| 173 | +%now triangulate to find the 3d location again, using the camera matrices |
| 174 | +M = triangulateJYB(P1,[c1x+na*randn c1y+na*randn],P2,[c2x+na*randn c2y+na*randn]); |
| 175 | +plot3(M(1),M(2),M(3),'ro'); |
0 commit comments