diff options
author | Leo Chan <leochanj@live.unc.edu> | 2020-10-22 01:53:21 -0400 |
---|---|---|
committer | Joshua Bakita <jbakita@cs.unc.edu> | 2020-10-22 01:56:35 -0400 |
commit | d17b33131c14864bd1eae275f49a3f148e21cf29 (patch) | |
tree | 0d8f77922e8d193cb0f6edab83018f057aad64a0 /SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib | |
parent | 601ed25a4c5b66cb75315832c15613a727db2c26 (diff) |
Squashed commit of the sb-vbs branch.
Includes the SD-VBS benchmarks modified to:
- Use libextra to loop as realtime jobs
- Preallocate memory before starting their main computation
- Accept input via stdin instead of via argc
Does not include the SD-VBS matlab code.
Fixes libextra execution in LITMUS^RT.
Diffstat (limited to 'SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib')
74 files changed, 8209 insertions, 0 deletions
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/Distor2Calib.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/Distor2Calib.m new file mode 100755 index 0000000..a82f583 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/Distor2Calib.m | |||
@@ -0,0 +1,391 @@ | |||
1 | function [fc_2,Rc_2,Tc_2,H_2,distance,V_vert,V_hori,x_all_c,V_hori_pix,V_vert_pix,V_diag1_pix,V_diag2_pix]=Distor2Calib(k_dist,grid_pts_centered,n_sq_x,n_sq_y,Np,W,L,Xgrid_2,f_ini,N_iter,two_focal); | ||
2 | |||
3 | % Computes the calibration parameters knowing the | ||
4 | % distortion factor k_dist | ||
5 | |||
6 | % grid_pts_centered are the grid point coordinates after substraction of | ||
7 | % the optical center. | ||
8 | |||
9 | % can give an optional guess for the focal length f_ini (can set to []) | ||
10 | % can provide the number of iterations for the Iterative Vanishing Point Algorithm | ||
11 | |||
12 | % if the focal length is known perfectly, then, there is no need to iterate, | ||
13 | % and therefore, one can fix: N_iter = 0; | ||
14 | |||
15 | % California Institute of Technology | ||
16 | % (c) Jean-Yves Bouguet - October 7th, 1997 | ||
17 | |||
18 | |||
19 | |||
20 | %keyboard; | ||
21 | |||
22 | if exist('two_focal'), | ||
23 | if isempty(two_focal), | ||
24 | two_focal=0; | ||
25 | end; | ||
26 | else | ||
27 | two_focal = 0; | ||
28 | end; | ||
29 | |||
30 | |||
31 | if exist('N_iter'), | ||
32 | if ~isempty(N_iter), | ||
33 | disp('Use number of iterations provided'); | ||
34 | else | ||
35 | N_iter = 10; | ||
36 | end; | ||
37 | else | ||
38 | N_iter = 10; | ||
39 | end; | ||
40 | |||
41 | if exist('f_ini'), | ||
42 | if ~isempty(f_ini), | ||
43 | disp('Use focal provided'); | ||
44 | if length(f_ini)<2, f_ini=[f_ini;f_ini]; end; | ||
45 | fc_2 = f_ini; | ||
46 | x_all_c = [grid_pts_centered(1,:)/fc_2(1);grid_pts_centered(2,:)/fc_2(2)]; | ||
47 | x_all_c = comp_distortion(x_all_c,k_dist); % we can this time!!! | ||
48 | else | ||
49 | fc_2 = [1;1]; | ||
50 | x_all_c = grid_pts_centered; | ||
51 | end; | ||
52 | else | ||
53 | fc_2 = [1;1]; | ||
54 | x_all_c = grid_pts_centered; | ||
55 | end; | ||
56 | |||
57 | |||
58 | dX = W/n_sq_x; | ||
59 | dY = L/n_sq_y; | ||
60 | |||
61 | |||
62 | N_x = n_sq_x+1; | ||
63 | N_y = n_sq_y+1; | ||
64 | |||
65 | |||
66 | x_grid = zeros(N_x,N_y); | ||
67 | y_grid = zeros(N_x,N_y); | ||
68 | |||
69 | |||
70 | |||
71 | |||
72 | |||
73 | %%% Computation of the four vanishing points in pixels | ||
74 | |||
75 | |||
76 | x_grid(:) = grid_pts_centered(1,:); | ||
77 | y_grid(:) = grid_pts_centered(2,:); | ||
78 | |||
79 | for k=1:n_sq_x+1, | ||
80 | [U,S,V] = svd([x_grid(k,:);y_grid(k,:);ones(1,n_sq_y+1)]); | ||
81 | vert(:,k) = U(:,3); | ||
82 | end; | ||
83 | |||
84 | for k=1:n_sq_y+1, | ||
85 | [U,S,V] = svd([x_grid(:,k)';y_grid(:,k)';ones(1,n_sq_x+1)]); | ||
86 | hori(:,k) = U(:,3); | ||
87 | end; | ||
88 | |||
89 | % 2 principle Vanishing points: | ||
90 | [U,S,V] = svd(vert); | ||
91 | V_vert = U(:,3); | ||
92 | [U,S,V] = svd(hori); | ||
93 | V_hori = U(:,3); | ||
94 | |||
95 | |||
96 | |||
97 | % Square warping: | ||
98 | |||
99 | |||
100 | vert_first = vert(:,1) - dot(V_vert,vert(:,1))/dot(V_vert,V_vert) * V_vert; | ||
101 | vert_last = vert(:,n_sq_x+1) - dot(V_vert,vert(:,n_sq_x+1))/dot(V_vert,V_vert) * V_vert; | ||
102 | |||
103 | hori_first = hori(:,1) - dot(V_hori,hori(:,1))/dot(V_hori,V_hori) * V_hori; | ||
104 | hori_last = hori(:,n_sq_y+1) - dot(V_hori,hori(:,n_sq_y+1))/dot(V_hori,V_hori) * V_hori; | ||
105 | |||
106 | |||
107 | x1 = cross(hori_first,vert_first); | ||
108 | x2 = cross(hori_first,vert_last); | ||
109 | x3 = cross(hori_last,vert_last); | ||
110 | x4 = cross(hori_last,vert_first); | ||
111 | |||
112 | x1 = x1/x1(3); | ||
113 | x2 = x2/x2(3); | ||
114 | x3 = x3/x3(3); | ||
115 | x4 = x4/x4(3); | ||
116 | |||
117 | |||
118 | |||
119 | [square] = Rectangle2Square([x1 x2 x3 x4],W,L); | ||
120 | |||
121 | y1 = square(:,1); | ||
122 | y2 = square(:,2); | ||
123 | y3 = square(:,3); | ||
124 | y4 = square(:,4); | ||
125 | |||
126 | H2 = cross(V_vert,V_hori); | ||
127 | |||
128 | V_diag1 = cross(cross(y1,y3),H2); | ||
129 | V_diag2 = cross(cross(y2,y4),H2); | ||
130 | |||
131 | V_diag1 = V_diag1 / norm(V_diag1); | ||
132 | V_diag2 = V_diag2 / norm(V_diag2); | ||
133 | |||
134 | V_hori_pix = V_hori; | ||
135 | V_vert_pix = V_vert; | ||
136 | V_diag1_pix = V_diag1; | ||
137 | V_diag2_pix = V_diag2; | ||
138 | |||
139 | |||
140 | % end of computation of the vanishing points in pixels. | ||
141 | |||
142 | |||
143 | |||
144 | |||
145 | |||
146 | |||
147 | |||
148 | |||
149 | if two_focal, % only if we attempt to estimate two focals... | ||
150 | % Use diagonal lines also to add two extra vanishing points (?) | ||
151 | N_min = min(N_x,N_y); | ||
152 | |||
153 | if N_min < 2, | ||
154 | use_diag = 0; | ||
155 | two_focal = 0; | ||
156 | disp('Cannot estimate two focals (no existing diagonals)'); | ||
157 | else | ||
158 | use_diag = 1; | ||
159 | Delta_N = abs(N_x-N_y); | ||
160 | N_extra = round((N_min - Delta_N - 1)/2); | ||
161 | diag_list = -N_extra:Delta_N+N_extra; | ||
162 | N_diag = length(diag_list); | ||
163 | diag_1 = zeros(3,N_diag); | ||
164 | diag_2 = zeros(3,N_diag); | ||
165 | end; | ||
166 | else | ||
167 | % Give up the use of the diagonals (so far) | ||
168 | % it seems that the error is increased | ||
169 | use_diag = 0; | ||
170 | end; | ||
171 | |||
172 | |||
173 | |||
174 | % The vertical lines: vert, Horizontal lines: hori | ||
175 | vert = zeros(3,n_sq_x+1); | ||
176 | hori = zeros(3,n_sq_y+1); | ||
177 | |||
178 | for counter_k = 1:N_iter, % the Iterative Vanishing Points Algorithm to | ||
179 | % estimate the focal length accurately | ||
180 | |||
181 | x_grid(:) = x_all_c(1,:); | ||
182 | y_grid(:) = x_all_c(2,:); | ||
183 | |||
184 | for k=1:n_sq_x+1, | ||
185 | [U,S,V] = svd([x_grid(k,:);y_grid(k,:);ones(1,n_sq_y+1)]); | ||
186 | vert(:,k) = U(:,3); | ||
187 | end; | ||
188 | |||
189 | for k=1:n_sq_y+1, | ||
190 | [U,S,V] = svd([x_grid(:,k)';y_grid(:,k)';ones(1,n_sq_x+1)]); | ||
191 | hori(:,k) = U(:,3); | ||
192 | end; | ||
193 | |||
194 | % 2 principle Vanishing points: | ||
195 | [U,S,V] = svd(vert); | ||
196 | V_vert = U(:,3); | ||
197 | [U,S,V] = svd(hori); | ||
198 | V_hori = U(:,3); | ||
199 | |||
200 | |||
201 | |||
202 | % Square warping: | ||
203 | |||
204 | |||
205 | vert_first = vert(:,1) - dot(V_vert,vert(:,1))/dot(V_vert,V_vert) * V_vert; | ||
206 | vert_last = vert(:,n_sq_x+1) - dot(V_vert,vert(:,n_sq_x+1))/dot(V_vert,V_vert) * V_vert; | ||
207 | |||
208 | hori_first = hori(:,1) - dot(V_hori,hori(:,1))/dot(V_hori,V_hori) * V_hori; | ||
209 | hori_last = hori(:,n_sq_y+1) - dot(V_hori,hori(:,n_sq_y+1))/dot(V_hori,V_hori) * V_hori; | ||
210 | |||
211 | |||
212 | x1 = cross(hori_first,vert_first); | ||
213 | x2 = cross(hori_first,vert_last); | ||
214 | x3 = cross(hori_last,vert_last); | ||
215 | x4 = cross(hori_last,vert_first); | ||
216 | |||
217 | x1 = x1/x1(3); | ||
218 | x2 = x2/x2(3); | ||
219 | x3 = x3/x3(3); | ||
220 | x4 = x4/x4(3); | ||
221 | |||
222 | |||
223 | |||
224 | [square] = Rectangle2Square([x1 x2 x3 x4],W,L); | ||
225 | |||
226 | y1 = square(:,1); | ||
227 | y2 = square(:,2); | ||
228 | y3 = square(:,3); | ||
229 | y4 = square(:,4); | ||
230 | |||
231 | H2 = cross(V_vert,V_hori); | ||
232 | |||
233 | V_diag1 = cross(cross(y1,y3),H2); | ||
234 | V_diag2 = cross(cross(y2,y4),H2); | ||
235 | |||
236 | V_diag1 = V_diag1 / norm(V_diag1); | ||
237 | V_diag2 = V_diag2 / norm(V_diag2); | ||
238 | |||
239 | |||
240 | |||
241 | |||
242 | % Estimation of the focal length, and normalization: | ||
243 | |||
244 | % Compute the ellipsis of (1/f^2) positions: | ||
245 | % a * (1/fx)^2 + b * (1/fx)^2 = -c | ||
246 | |||
247 | |||
248 | a1 = V_hori(1); | ||
249 | b1 = V_hori(2); | ||
250 | c1 = V_hori(3); | ||
251 | |||
252 | a2 = V_vert(1); | ||
253 | b2 = V_vert(2); | ||
254 | c2 = V_vert(3); | ||
255 | |||
256 | a3 = V_diag1(1); | ||
257 | b3 = V_diag1(2); | ||
258 | c3 = V_diag1(3); | ||
259 | |||
260 | a4 = V_diag2(1); | ||
261 | b4 = V_diag2(2); | ||
262 | c4 = V_diag2(3); | ||
263 | |||
264 | |||
265 | if two_focal, | ||
266 | |||
267 | |||
268 | A = [a1*a2 b1*b2;a3*a4 b3*b4]; | ||
269 | b = -[c1*c2;c3*c4]; | ||
270 | |||
271 | f = sqrt(abs(1./(inv(A)*b))); | ||
272 | |||
273 | else | ||
274 | |||
275 | f = sqrt(abs(-(c1*c2*(a1*a2 + b1*b2) + c3*c4*(a3*a4 + b3*b4))/(c1^2*c2^2 + c3^2*c4^2))); | ||
276 | |||
277 | f = [f;f]; | ||
278 | |||
279 | end; | ||
280 | |||
281 | |||
282 | |||
283 | % REMARK: | ||
284 | % if both a and b are small, the calibration is impossible. | ||
285 | % if one of them is small, only the other focal length is observable | ||
286 | % if none is small, both focals are observable | ||
287 | |||
288 | |||
289 | fc_2 = fc_2 .* f; | ||
290 | |||
291 | |||
292 | % DEBUG PART: fix focal to 500... | ||
293 | %fc_2= [500;500]; disp('Line 293 to be earased in Distor2Calib.m'); | ||
294 | |||
295 | |||
296 | % end of focal compensation | ||
297 | |||
298 | % normalize by the current focal: | ||
299 | |||
300 | x_all = [grid_pts_centered(1,:)/fc_2(1);grid_pts_centered(2,:)/fc_2(2)]; | ||
301 | |||
302 | % Compensate by the distortion factor: | ||
303 | |||
304 | x_all_c = comp_distortion(x_all,k_dist); | ||
305 | |||
306 | end; | ||
307 | |||
308 | % At that point, we hope that the distortion is gone... | ||
309 | |||
310 | x_grid(:) = x_all_c(1,:); | ||
311 | y_grid(:) = x_all_c(2,:); | ||
312 | |||
313 | for k=1:n_sq_x+1, | ||
314 | [U,S,V] = svd([x_grid(k,:);y_grid(k,:);ones(1,n_sq_y+1)]); | ||
315 | vert(:,k) = U(:,3); | ||
316 | end; | ||
317 | |||
318 | for k=1:n_sq_y+1, | ||
319 | [U,S,V] = svd([x_grid(:,k)';y_grid(:,k)';ones(1,n_sq_x+1)]); | ||
320 | hori(:,k) = U(:,3); | ||
321 | end; | ||
322 | |||
323 | % Vanishing points: | ||
324 | [U,S,V] = svd(vert); | ||
325 | V_vert = U(:,3); | ||
326 | [U,S,V] = svd(hori); | ||
327 | V_hori = U(:,3); | ||
328 | |||
329 | % Horizon: | ||
330 | |||
331 | H_2 = cross(V_vert,V_hori); | ||
332 | |||
333 | % H_2 = cross(V_vert,V_hori); | ||
334 | |||
335 | % pick a plane in front of the camera (positive depth) | ||
336 | if H_2(3) < 0, H_2 = -H_2; end; | ||
337 | |||
338 | |||
339 | % Rotation matrix: | ||
340 | |||
341 | if V_hori(1) < 0, V_hori = -V_hori; end; | ||
342 | |||
343 | V_hori = V_hori/norm(V_hori); | ||
344 | H_2 = H_2/norm(H_2); | ||
345 | |||
346 | V_hori = V_hori - dot(V_hori,H_2)*H_2; | ||
347 | |||
348 | Rc_2 = [V_hori cross(H_2,V_hori) H_2]; | ||
349 | |||
350 | Rc_2 = Rc_2 / det(Rc_2); | ||
351 | |||
352 | %omc_2 = rodrigues(Rc_2); | ||
353 | |||
354 | %Rc_2 = rodrigues(omc_2); | ||
355 | |||
356 | % Find the distance of the plane for translation vector: | ||
357 | |||
358 | xc_2 = [x_all_c;ones(1,Np)]; | ||
359 | |||
360 | Zc_2 = 1./sum(xc_2 .* (Rc_2(:,3)*ones(1,Np))); | ||
361 | |||
362 | Xo_2 = [sum(xc_2 .* (Rc_2(:,1)*ones(1,Np))).*Zc_2 ; sum(xc_2 .* (Rc_2(:,2)*ones(1,Np))).*Zc_2]; | ||
363 | |||
364 | XXo_2 = Xo_2 - mean(Xo_2')'*ones(1,Np); | ||
365 | |||
366 | distance_x = norm(Xgrid_2(1,:))/norm(XXo_2(1,:)); | ||
367 | distance_y = norm(Xgrid_2(2,:))/norm(XXo_2(2,:)); | ||
368 | |||
369 | |||
370 | distance = sum(sum(XXo_2(1:2,:).*Xgrid_2(1:2,:)))/sum(sum(XXo_2(1:2,:).^2)); | ||
371 | |||
372 | alpha = abs(distance_x - distance_y)/distance; | ||
373 | |||
374 | if (alpha>0.1)&~two_focal, | ||
375 | disp('Should use two focals in x and y...'); | ||
376 | end; | ||
377 | |||
378 | % Deduce the translation vector: | ||
379 | |||
380 | Tc_2 = distance * H_2; | ||
381 | |||
382 | |||
383 | |||
384 | |||
385 | |||
386 | return; | ||
387 | |||
388 | V_hori_pix/V_hori_pix(3) | ||
389 | V_vert_pix/V_vert_pix(3) | ||
390 | V_diag1_pix/V_diag1_pix(3) | ||
391 | V_diag2_pix/V_diag2_pix(3) | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/Rectangle2Square.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/Rectangle2Square.m new file mode 100755 index 0000000..a6bbbe5 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/Rectangle2Square.m | |||
@@ -0,0 +1,19 @@ | |||
1 | function [square] = Rectangle2Square(rectangle,L,W); | ||
2 | |||
3 | % Generate the square from a rectangle of known segment lengths | ||
4 | % from pt1 to pt2 : L | ||
5 | % from pt2 to pt3 : W | ||
6 | |||
7 | [u_hori,u_vert] = UnWarpPlane(rectangle); | ||
8 | |||
9 | coeff_x = sqrt(W/L); | ||
10 | coeff_y = 1/coeff_x; | ||
11 | |||
12 | x_coord = [ 0 coeff_x coeff_x 0]; | ||
13 | y_coord = [ 0 0 coeff_y coeff_y]; | ||
14 | |||
15 | |||
16 | square = rectangle(:,1) * ones(1,4) + u_hori*x_coord + u_vert*y_coord; | ||
17 | square = square ./ (ones(3,1)*square(3,:)); | ||
18 | |||
19 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/UnWarpPlane.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/UnWarpPlane.m new file mode 100755 index 0000000..8addf52 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/UnWarpPlane.m | |||
@@ -0,0 +1,54 @@ | |||
1 | function [u_hori,u_vert] = UnWarpPlane(x1,x2,x3,x4); | ||
2 | |||
3 | % Recovers the two 3D directions of the rectangular patch x1x2x3x4 | ||
4 | % x1 is the origin point, ie any point of planar coordinate (x,y) on the | ||
5 | % rectangular patch will be projected on the image plane at: | ||
6 | % x1 + x * u_hori + y * u_vert | ||
7 | % | ||
8 | % Note: u_hori and u_vert are also the two vanishing points. | ||
9 | |||
10 | |||
11 | if nargin < 4, | ||
12 | |||
13 | x4 = x1(:,4); | ||
14 | x3 = x1(:,3); | ||
15 | x2 = x1(:,2); | ||
16 | x1 = x1(:,1); | ||
17 | |||
18 | end; | ||
19 | |||
20 | |||
21 | % Image Projection: | ||
22 | L1 = cross(x1,x2); | ||
23 | L2 = cross(x4,x3); | ||
24 | L3 = cross(x2,x3); | ||
25 | L4 = cross(x1,x4); | ||
26 | |||
27 | % Vanishing point: | ||
28 | V1 = cross(L1,L2); | ||
29 | V2 = cross(L3,L4); | ||
30 | |||
31 | % Horizon line: | ||
32 | H = cross(V1,V2); | ||
33 | |||
34 | if H(3) < 0, H = -H; end; | ||
35 | |||
36 | |||
37 | H = H / norm(H); | ||
38 | |||
39 | |||
40 | X1 = x1 / dot(H,x1); | ||
41 | X2 = x2 / dot(H,x2); | ||
42 | X3 = x3 / dot(H,x3); | ||
43 | X4 = x4 / dot(H,x4); | ||
44 | |||
45 | scale = X1(3); | ||
46 | |||
47 | X1 = X1/scale; | ||
48 | X2 = X2/scale; | ||
49 | X3 = X3/scale; | ||
50 | X4 = X4/scale; | ||
51 | |||
52 | |||
53 | u_hori = X2 - X1; | ||
54 | u_vert = X4 - X1; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/add_suppress.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/add_suppress.m new file mode 100755 index 0000000..a8a32c0 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/add_suppress.m | |||
@@ -0,0 +1,98 @@ | |||
1 | |||
2 | if ~exist('n_ima'), | ||
3 | fprintf(1,'No data to process.\n'); | ||
4 | return; | ||
5 | end; | ||
6 | |||
7 | |||
8 | check_active_images; | ||
9 | |||
10 | |||
11 | fprintf(1,'\nThis function is useful to select a subset of images to calibrate\n'); | ||
12 | |||
13 | fprintf(1,'\nThere are currently %d active images selected for calibration (out of %d):\n',length(ind_active),n_ima); | ||
14 | |||
15 | if ~isempty(ind_active), | ||
16 | |||
17 | for ii = 1:length(ind_active)-2, | ||
18 | |||
19 | fprintf(1,'%d, ',ind_active(ii)); | ||
20 | |||
21 | end; | ||
22 | |||
23 | fprintf(1,'%d and %d.',ind_active(end-1),ind_active(end)); | ||
24 | |||
25 | end; | ||
26 | |||
27 | fprintf(1,'\n'); | ||
28 | |||
29 | |||
30 | fprintf(1,'\nDo you want to suppress or add images from that list?\n'); | ||
31 | |||
32 | choice = 2; | ||
33 | |||
34 | while (choice~=0)&(choice~=1), | ||
35 | choice = input('For suppressing images enter 0, for adding images enter 1 ([]=no change): '); | ||
36 | if isempty(choice), | ||
37 | fprintf(1,'No change applied to the list of active images.\n'); | ||
38 | return; | ||
39 | end; | ||
40 | if (choice~=0)&(choice~=1), | ||
41 | disp('Bad entry. Try again.'); | ||
42 | end; | ||
43 | end; | ||
44 | |||
45 | |||
46 | if choice, | ||
47 | |||
48 | ima_numbers = input('Number(s) of image(s) to add ([] = all images) = '); | ||
49 | |||
50 | if isempty(ima_numbers), | ||
51 | fprintf(1,'All %d images are now active\n',n_ima); | ||
52 | ima_proc = 1:n_ima; | ||
53 | else | ||
54 | ima_proc = ima_numbers; | ||
55 | end; | ||
56 | |||
57 | else | ||
58 | |||
59 | |||
60 | ima_numbers = input('Number(s) of image(s) to suppress ([] = no image) = '); | ||
61 | |||
62 | if isempty(ima_numbers), | ||
63 | fprintf(1,'No image has been suppressed. No modication of the list of active images.\n',n_ima); | ||
64 | ima_proc = []; | ||
65 | else | ||
66 | ima_proc = ima_numbers; | ||
67 | end; | ||
68 | |||
69 | end; | ||
70 | |||
71 | if ~isempty(ima_proc), | ||
72 | |||
73 | active_images(ima_proc) = choice * ones(1,length(ima_proc)); | ||
74 | |||
75 | end; | ||
76 | |||
77 | |||
78 | check_active_images; | ||
79 | |||
80 | |||
81 | fprintf(1,'\nThere is now a total of %d active images for calibration:\n',length(ind_active)); | ||
82 | |||
83 | if ~isempty(ind_active), | ||
84 | |||
85 | for ii = 1:length(ind_active)-2, | ||
86 | |||
87 | fprintf(1,'%d, ',ind_active(ii)); | ||
88 | |||
89 | end; | ||
90 | |||
91 | fprintf(1,'%d and %d.',ind_active(end-1),ind_active(end)); | ||
92 | |||
93 | end; | ||
94 | |||
95 | fprintf(1,'\n\nYou may now run ''Calibration'' to recalibrate based on this new set of images.\n'); | ||
96 | |||
97 | |||
98 | \ No newline at end of file | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/analyse_error.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/analyse_error.m new file mode 100755 index 0000000..7a9cf0f --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/analyse_error.m | |||
@@ -0,0 +1,141 @@ | |||
1 | % Color code for each image: | ||
2 | |||
3 | if ~exist('n_ima')|~exist('fc'), | ||
4 | fprintf(1,'No calibration data available.\n'); | ||
5 | return; | ||
6 | end; | ||
7 | |||
8 | check_active_images; | ||
9 | |||
10 | if ~exist(['ex_' num2str(ind_active(1)) ]), | ||
11 | fprintf(1,'Need to calibrate before analysing reprojection error. Maybe need to load Calib_Results.mat file.\n'); | ||
12 | return; | ||
13 | end; | ||
14 | |||
15 | |||
16 | %if ~exist('no_grid'), | ||
17 | no_grid = 0; | ||
18 | %end; | ||
19 | |||
20 | colors = 'brgkcm'; | ||
21 | |||
22 | |||
23 | figure(5); | ||
24 | |||
25 | for kk = 1:n_ima, | ||
26 | if exist(['y_' num2str(kk)]), | ||
27 | if active_images(kk) & eval(['~isnan(y_' num2str(kk) '(1,1))']), | ||
28 | |||
29 | if ~no_grid, | ||
30 | eval(['XX_kk = X_' num2str(kk) ';']); | ||
31 | N_kk = size(XX_kk,2); | ||
32 | |||
33 | if ~exist(['n_sq_x_' num2str(kk)]), | ||
34 | no_grid = 1; | ||
35 | end; | ||
36 | |||
37 | if ~no_grid, | ||
38 | eval(['n_sq_x = n_sq_x_' num2str(kk) ';']); | ||
39 | eval(['n_sq_y = n_sq_y_' num2str(kk) ';']); | ||
40 | if (N_kk ~= ((n_sq_x+1)*(n_sq_y+1))), | ||
41 | no_grid = 1; | ||
42 | end; | ||
43 | end; | ||
44 | end; | ||
45 | |||
46 | eval(['plot(ex_' num2str(kk) '(1,:),ex_' num2str(kk) '(2,:),''' colors(rem(kk-1,6)+1) '+'');']); | ||
47 | |||
48 | hold on; | ||
49 | end; | ||
50 | end; | ||
51 | end; | ||
52 | |||
53 | hold off; | ||
54 | axis('equal'); | ||
55 | if 1, %~no_grid, | ||
56 | title('Reprojection error (in pixel) - To exit: right button'); | ||
57 | else | ||
58 | title('Reprojection error (in pixel)'); | ||
59 | end; | ||
60 | xlabel('x'); | ||
61 | ylabel('y'); | ||
62 | |||
63 | set(5,'Name','error','NumberTitle','off'); | ||
64 | |||
65 | |||
66 | |||
67 | err_std = std(ex')'; | ||
68 | |||
69 | fprintf(1,'Pixel error: err = [ %3.5f %3.5f] (all active images)\n\n',err_std); | ||
70 | |||
71 | |||
72 | b = 1; | ||
73 | |||
74 | while b==1, | ||
75 | |||
76 | [xp,yp,b] = ginput3(1); | ||
77 | |||
78 | if b==1, | ||
79 | ddd = (ex(1,:)-xp).^2 + (ex(2,:)-yp).^2; | ||
80 | |||
81 | [mind,indmin] = min(ddd); | ||
82 | |||
83 | |||
84 | done = 0; | ||
85 | kk_ima = 1; | ||
86 | while (~done)&(kk_ima<=n_ima), | ||
87 | %fprintf(1,'%d...',kk_ima); | ||
88 | eval(['ex_kk = ex_' num2str(kk_ima) ';']); | ||
89 | sol_kk = find((ex_kk(1,:) == ex(1,indmin))&(ex_kk(2,:) == ex(2,indmin))); | ||
90 | if isempty(sol_kk), | ||
91 | kk_ima = kk_ima + 1; | ||
92 | else | ||
93 | done = 1; | ||
94 | end; | ||
95 | end; | ||
96 | |||
97 | if ~no_grid, | ||
98 | |||
99 | eval(['n_sq_x = n_sq_x_' num2str(kk_ima) ';']); | ||
100 | eval(['n_sq_y = n_sq_y_' num2str(kk_ima) ';']); | ||
101 | |||
102 | Nx = n_sq_x+1; | ||
103 | Ny = n_sq_y+1; | ||
104 | |||
105 | y1 = floor((sol_kk-1)./Nx); | ||
106 | x1 = sol_kk - 1 - Nx*y1; %rem(sol_kk-1,Nx); | ||
107 | |||
108 | y1 = (n_sq_y+1) - y1; | ||
109 | x1 = x1 + 1; | ||
110 | |||
111 | fprintf(1,'\nSelected image: %d\nSelected point: (col,row)=(%d,%d)\nNcol=%d, Nrow=%d\n',[kk_ima x1 y1 Nx Ny]); | ||
112 | fprintf(1,'Pixel error = (%3.5f,%3.5f)\n',[ex(1,indmin) ex(2,indmin)]); | ||
113 | |||
114 | else | ||
115 | |||
116 | eval(['x_kk = x_' num2str(kk_ima) ';']); | ||
117 | |||
118 | xpt = x_kk(:,sol_kk); | ||
119 | |||
120 | fprintf(1,'\nSelected image: %d\nImage coordinates (in pixel): (%3.2f,%3.2f)\n',[kk_ima xpt']); | ||
121 | fprintf(1,'Pixel error = (%3.5f,%3.5f)\n',[ex(1,indmin) ex(2,indmin)]); | ||
122 | |||
123 | |||
124 | end; | ||
125 | |||
126 | |||
127 | if exist(['wintx_' num2str(kk_ima)]), | ||
128 | |||
129 | eval(['wintx = wintx_' num2str(kk_ima) ';']); | ||
130 | eval(['winty = winty_' num2str(kk_ima) ';']); | ||
131 | |||
132 | fprintf(1,'Window size: wintx = %d, winty = %d\n',[wintx winty]); | ||
133 | end; | ||
134 | |||
135 | |||
136 | end; | ||
137 | |||
138 | end; | ||
139 | |||
140 | disp('done'); | ||
141 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/apply_distortion.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/apply_distortion.m new file mode 100755 index 0000000..f5c5b48 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/apply_distortion.m | |||
@@ -0,0 +1,137 @@ | |||
1 | function [xd,dxddk] = apply_distortion(x,k) | ||
2 | |||
3 | |||
4 | [m,n] = size(x); | ||
5 | |||
6 | % Add distortion: | ||
7 | |||
8 | r2 = x(1,:).^2 + x(2,:).^2; | ||
9 | |||
10 | r4 = r2.^2; | ||
11 | |||
12 | % Radial distortion: | ||
13 | |||
14 | cdist = 1 + k(1) * r2 + k(2) * r4; | ||
15 | |||
16 | if nargout > 1, | ||
17 | dcdistdk = [ r2' r4' zeros(n,2)]; | ||
18 | end; | ||
19 | |||
20 | |||
21 | xd1 = x .* (ones(2,1)*cdist); | ||
22 | |||
23 | coeff = (reshape([cdist;cdist],2*n,1)*ones(1,3)); | ||
24 | |||
25 | if nargout > 1, | ||
26 | dxd1dk = zeros(2*n,4); | ||
27 | dxd1dk(1:2:end,:) = (x(1,:)'*ones(1,4)) .* dcdistdk; | ||
28 | dxd1dk(2:2:end,:) = (x(2,:)'*ones(1,4)) .* dcdistdk; | ||
29 | end; | ||
30 | |||
31 | |||
32 | % tangential distortion: | ||
33 | |||
34 | a1 = 2.*x(1,:).*x(2,:); | ||
35 | a2 = r2 + 2*x(1,:).^2; | ||
36 | a3 = r2 + 2*x(2,:).^2; | ||
37 | |||
38 | delta_x = [k(3)*a1 + k(4)*a2 ; | ||
39 | k(3) * a3 + k(4)*a1]; | ||
40 | |||
41 | aa = (2*k(3)*x(2,:)+6*k(4)*x(1,:))'*ones(1,3); | ||
42 | bb = (2*k(3)*x(1,:)+2*k(4)*x(2,:))'*ones(1,3); | ||
43 | cc = (6*k(3)*x(2,:)+2*k(4)*x(1,:))'*ones(1,3); | ||
44 | |||
45 | if nargout > 1, | ||
46 | ddelta_xdk = zeros(2*n,4); | ||
47 | ddelta_xdk(1:2:end,3) = a1'; | ||
48 | ddelta_xdk(1:2:end,4) = a2'; | ||
49 | ddelta_xdk(2:2:end,3) = a3'; | ||
50 | ddelta_xdk(2:2:end,4) = a1'; | ||
51 | end; | ||
52 | |||
53 | xd = xd1 + delta_x; | ||
54 | |||
55 | if nargout > 1, | ||
56 | dxddk = dxd1dk + ddelta_xdk ; | ||
57 | end; | ||
58 | |||
59 | |||
60 | return; | ||
61 | |||
62 | % Test of the Jacobians: | ||
63 | |||
64 | n = 10; | ||
65 | |||
66 | X = 10*randn(3,n); | ||
67 | om = randn(3,1); | ||
68 | T = [10*randn(2,1);40]; | ||
69 | f = 1000*rand(2,1); | ||
70 | c = 1000*randn(2,1); | ||
71 | k = 0.5*randn(4,1); | ||
72 | |||
73 | |||
74 | [x,dxdom,dxdT,dxdf,dxdc,dxdk] = project_points(X,om,T,f,c,k); | ||
75 | |||
76 | |||
77 | % Test on om: NOT OK | ||
78 | |||
79 | dom = 0.000000001 * norm(om)*randn(3,1); | ||
80 | om2 = om + dom; | ||
81 | |||
82 | [x2] = project_points(X,om2,T,f,c,k); | ||
83 | |||
84 | x_pred = x + reshape(dxdom * dom,2,n); | ||
85 | |||
86 | |||
87 | norm(x2-x)/norm(x2 - x_pred) | ||
88 | |||
89 | |||
90 | % Test on T: OK!! | ||
91 | |||
92 | dT = 0.0001 * norm(T)*randn(3,1); | ||
93 | T2 = T + dT; | ||
94 | |||
95 | [x2] = project_points(X,om,T2,f,c,k); | ||
96 | |||
97 | x_pred = x + reshape(dxdT * dT,2,n); | ||
98 | |||
99 | |||
100 | norm(x2-x)/norm(x2 - x_pred) | ||
101 | |||
102 | |||
103 | |||
104 | % Test on f: OK!! | ||
105 | |||
106 | df = 0.001 * norm(f)*randn(2,1); | ||
107 | f2 = f + df; | ||
108 | |||
109 | [x2] = project_points(X,om,T,f2,c,k); | ||
110 | |||
111 | x_pred = x + reshape(dxdf * df,2,n); | ||
112 | |||
113 | |||
114 | norm(x2-x)/norm(x2 - x_pred) | ||
115 | |||
116 | |||
117 | % Test on c: OK!! | ||
118 | |||
119 | dc = 0.01 * norm(c)*randn(2,1); | ||
120 | c2 = c + dc; | ||
121 | |||
122 | [x2] = project_points(X,om,T,f,c2,k); | ||
123 | |||
124 | x_pred = x + reshape(dxdc * dc,2,n); | ||
125 | |||
126 | norm(x2-x)/norm(x2 - x_pred) | ||
127 | |||
128 | % Test on k: OK!! | ||
129 | |||
130 | dk = 0.001 * norm(4)*randn(4,1); | ||
131 | k2 = k + dk; | ||
132 | |||
133 | [x2] = project_points(X,om,T,f,c,k2); | ||
134 | |||
135 | x_pred = x + reshape(dxdk * dk,2,n); | ||
136 | |||
137 | norm(x2-x)/norm(x2 - x_pred) | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/calib_gui.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/calib_gui.m new file mode 100755 index 0000000..d591d03 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/calib_gui.m | |||
@@ -0,0 +1,117 @@ | |||
1 | fig_number = 1; | ||
2 | |||
3 | n_row = 4; | ||
4 | n_col = 4; | ||
5 | |||
6 | string_list = cell(n_row,n_col); | ||
7 | callback_list = cell(n_row,n_col); | ||
8 | |||
9 | x_size = 85; | ||
10 | y_size = 14; | ||
11 | gap_x = 0; | ||
12 | font_name = 'clean'; | ||
13 | font_size = 8; | ||
14 | |||
15 | title_figure = 'Camera Calibration Toolbox'; | ||
16 | |||
17 | string_list{1,1} = 'Image names'; | ||
18 | string_list{1,2} = 'Read images'; | ||
19 | string_list{1,3} = 'Extract grid corners'; | ||
20 | string_list{1,4} = 'Calibration'; | ||
21 | string_list{2,1} = 'Show Extrinsic'; | ||
22 | string_list{2,2} = 'Reproject on images'; | ||
23 | string_list{2,3} = 'Analyse error'; | ||
24 | string_list{2,4} = 'Recomp. corners'; | ||
25 | string_list{3,1} = 'Add/Suppress images'; | ||
26 | string_list{3,2} = 'Save'; | ||
27 | string_list{3,3} = 'Load'; | ||
28 | string_list{3,4} = 'Exit'; | ||
29 | |||
30 | string_list{4,1} = 'Comp. Extrinsic'; | ||
31 | string_list{4,2} = 'Undistort image'; | ||
32 | string_list{4,3} = 'Export calib data'; | ||
33 | |||
34 | |||
35 | callback_list{1,1} = 'data_calib;'; | ||
36 | callback_list{1,2} = 'ima_read_calib;'; | ||
37 | callback_list{1,3} = 'click_calib;'; | ||
38 | callback_list{1,4} = 'go_calib_optim;'; | ||
39 | callback_list{2,1} = 'ext_calib;'; | ||
40 | callback_list{2,2} = 'reproject_calib;'; | ||
41 | callback_list{2,3} = 'analyse_error;'; | ||
42 | callback_list{2,4} = 'recomp_corner_calib;'; | ||
43 | callback_list{3,1} = 'add_suppress;'; | ||
44 | callback_list{3,2} = 'saving_calib;'; | ||
45 | callback_list{3,3} = 'loading_calib;'; | ||
46 | callback_list{3,4} = ['disp(''Bye. To run again, type calib_gui.''); close(' num2str(fig_number) ');']; | ||
47 | |||
48 | callback_list{4,1} = 'extrinsic_computation;'; | ||
49 | callback_list{4,2} = 'undistort_image;'; | ||
50 | callback_list{4,3} = 'export_calib_data;'; | ||
51 | |||
52 | |||
53 | %------- BEGIN PROECTED REGION -----------% | ||
54 | %------- DO NOT EDIT IN THIS REGION -----------% | ||
55 | |||
56 | figure(fig_number); clf; | ||
57 | pos = get(fig_number,'Position'); | ||
58 | |||
59 | fig_size_x = x_size*n_col+(n_col+1)*gap_x; | ||
60 | fig_size_y = y_size*n_row+(n_row+1)*gap_x; | ||
61 | |||
62 | set(fig_number,'Units','points', ... | ||
63 | 'BackingStore','off', ... | ||
64 | 'Color',[0.8 0.8 0.8], ... | ||
65 | 'MenuBar','none', ... | ||
66 | 'Resize','off', ... | ||
67 | 'Name',title_figure, ... | ||
68 | 'Position',[pos(1) pos(2) fig_size_x fig_size_y], ... | ||
69 | 'NumberTitle','off'); %,'WindowButtonMotionFcn',['figure(' num2str(fig_number) ');']); | ||
70 | |||
71 | h_mat = zeros(n_row,n_col); | ||
72 | |||
73 | posx = zeros(n_row,n_col); | ||
74 | posy = zeros(n_row,n_col); | ||
75 | |||
76 | for i=n_row:-1:1, | ||
77 | for j = n_col:-1:1, | ||
78 | posx(i,j) = gap_x+(j-1)*(x_size+gap_x); | ||
79 | posy(i,j) = fig_size_y - i*(gap_x+y_size); | ||
80 | end; | ||
81 | end; | ||
82 | |||
83 | for i=n_row:-1:1, | ||
84 | for j = n_col:-1:1, | ||
85 | if ~isempty(string_list{i,j}) & ~isempty(callback_list{i,j}), | ||
86 | h_mat(i,j) = uicontrol('Parent',fig_number, ... | ||
87 | 'Units','points', ... | ||
88 | 'Callback',callback_list{i,j}, ... | ||
89 | 'ListboxTop',0, ... | ||
90 | 'Position',[posx(i,j) posy(i,j) x_size y_size], ... | ||
91 | 'String',string_list{i,j}, ... | ||
92 | 'fontsize',font_size,... | ||
93 | 'fontname',font_name,... | ||
94 | 'Tag','Pushbutton1'); | ||
95 | end; | ||
96 | end; | ||
97 | end; | ||
98 | |||
99 | %------ END PROTECTED REGION ----------------% | ||
100 | |||
101 | if 0, | ||
102 | %-- VERSION: | ||
103 | |||
104 | uicontrol('Parent',fig_number, ... | ||
105 | 'Units','points', ... | ||
106 | 'ListboxTop',0, ... | ||
107 | 'Position',[(fig_size_x-x_size/2)-2 -5 x_size/2 y_size], ... | ||
108 | 'String','ver. 1.0', ... | ||
109 | 'fontsize',8,... | ||
110 | 'BackgroundColor',[0.8 0.8 0.8], ... | ||
111 | 'fontname','clean',... | ||
112 | 'HorizontalAlignment','right', ... | ||
113 | 'Style','text'); | ||
114 | end; | ||
115 | |||
116 | |||
117 | %clear callback_list string_list fig_number fig_size_x fig_size_y i j n_col n_row pos string_list title_figure x_size y_size font_name font_size gap_x h_mat posx posy | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/check_active_images.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/check_active_images.m new file mode 100755 index 0000000..fc365a5 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/check_active_images.m | |||
@@ -0,0 +1,19 @@ | |||
1 | |||
2 | if ~exist('active_images'), | ||
3 | active_images = ones(1,n_ima); | ||
4 | end; | ||
5 | n_act = length(active_images); | ||
6 | if n_act < n_ima, | ||
7 | active_images = [active_images ones(1,n_ima-n_act)]; | ||
8 | else | ||
9 | if n_act > n_ima, | ||
10 | active_images = active_images(1:n_ima); | ||
11 | end; | ||
12 | end; | ||
13 | |||
14 | ind_active = find(active_images); | ||
15 | |||
16 | if prod(active_images == 0), | ||
17 | disp('Error: There is no active image'); | ||
18 | break | ||
19 | end; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/check_convergence.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/check_convergence.m new file mode 100755 index 0000000..c4b13fd --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/check_convergence.m | |||
@@ -0,0 +1,48 @@ | |||
1 | %%% Replay the set of solution vectors: | ||
2 | |||
3 | |||
4 | if ~exist('param_list'), | ||
5 | if ~exist('solution'); | ||
6 | fprintf(1,'Error: Need to calibrate first\n'); | ||
7 | return; | ||
8 | else | ||
9 | param_list = solution; | ||
10 | end; | ||
11 | end; | ||
12 | |||
13 | N_iter = size(param_list,2); | ||
14 | |||
15 | if N_iter == 1, | ||
16 | fprintf(1,'Warning: There is a unique state in the list of parameters.\n'); | ||
17 | end; | ||
18 | |||
19 | |||
20 | |||
21 | %M = moviein(N_iter); | ||
22 | |||
23 | for nn = 1:N_iter, | ||
24 | |||
25 | solution = param_list(:,nn); | ||
26 | |||
27 | extract_parameters; | ||
28 | comp_error_calib; | ||
29 | |||
30 | ext_calib; | ||
31 | |||
32 | drawnow; | ||
33 | |||
34 | % Mnn = getframe(gcf); | ||
35 | |||
36 | % M(:,nn) = Mnn; | ||
37 | |||
38 | end; | ||
39 | |||
40 | %fig = gcf; | ||
41 | |||
42 | |||
43 | %figure(fig+1); | ||
44 | %close; | ||
45 | %figure(fig+1); | ||
46 | |||
47 | %clf; | ||
48 | %movie(M,20); | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/check_directory.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/check_directory.m new file mode 100755 index 0000000..dc23149 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/check_directory.m | |||
@@ -0,0 +1,97 @@ | |||
1 | % This small script looks in the direcory and checks if the images are there. | ||
2 | % | ||
3 | % This works only on Matlab 5.x (otherwise, the dir commands works differently) | ||
4 | |||
5 | % (c) Jean-Yves Bouguet - Dec. 27th, 1999 | ||
6 | |||
7 | l = dir([calib_name '*']); | ||
8 | |||
9 | Nl = size(l,1); | ||
10 | Nima_valid = 0; | ||
11 | ind_valid = []; | ||
12 | loc_extension = []; | ||
13 | length_name = size(calib_name,2); | ||
14 | |||
15 | if Nl > 0, | ||
16 | |||
17 | for pp = 1:Nl, | ||
18 | filenamepp = l(pp).name; | ||
19 | iii = findstr(filenamepp,calib_name); | ||
20 | |||
21 | loc_ext = findstr(filenamepp,format_image); | ||
22 | string_num = filenamepp(length_name+1:loc_ext - 2); | ||
23 | |||
24 | if isempty(str2num(string_num)), | ||
25 | iii = []; | ||
26 | end; | ||
27 | |||
28 | |||
29 | if ~isempty(iii), | ||
30 | if (iii(1) ~= 1), | ||
31 | iii = []; | ||
32 | end; | ||
33 | end; | ||
34 | |||
35 | |||
36 | |||
37 | if ~isempty(iii) & ~isempty(loc_ext), | ||
38 | |||
39 | Nima_valid = Nima_valid + 1; | ||
40 | ind_valid = [ind_valid pp]; | ||
41 | loc_extension = [loc_extension loc_ext(1)]; | ||
42 | |||
43 | end; | ||
44 | |||
45 | end; | ||
46 | |||
47 | if (Nima_valid==0), | ||
48 | |||
49 | fprintf(1,'No image found. File format may be wrong.\n'); | ||
50 | |||
51 | else | ||
52 | |||
53 | % Get all the string numbers: | ||
54 | |||
55 | string_length = zeros(1,Nima_valid); | ||
56 | indices = zeros(1,Nima_valid); | ||
57 | |||
58 | |||
59 | for ppp = 1:Nima_valid, | ||
60 | |||
61 | name = l(ind_valid(ppp)).name; | ||
62 | string_num = name(length_name+1:loc_extension(ppp) - 2); | ||
63 | string_length(ppp) = size(string_num,2); | ||
64 | indices(ppp) = str2num(string_num); | ||
65 | |||
66 | end; | ||
67 | |||
68 | % Number of images... | ||
69 | first_num = min(indices); | ||
70 | n_ima = max(indices) - first_num + 1; | ||
71 | |||
72 | if min(string_length) == max(string_length), | ||
73 | |||
74 | N_slots = min(string_length); | ||
75 | type_numbering = 1; | ||
76 | |||
77 | else | ||
78 | |||
79 | N_slots = 1; | ||
80 | type_numbering = 0; | ||
81 | |||
82 | end; | ||
83 | |||
84 | image_numbers = first_num:n_ima-1+first_num; | ||
85 | |||
86 | %%% By default, all the images are active for calibration: | ||
87 | |||
88 | active_images = ones(1,n_ima); | ||
89 | |||
90 | end; | ||
91 | |||
92 | else | ||
93 | |||
94 | fprintf(1,'No image found. Basename may be wrong.\n'); | ||
95 | |||
96 | end; | ||
97 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/check_extracted_images.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/check_extracted_images.m new file mode 100755 index 0000000..fa7df87 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/check_extracted_images.m | |||
@@ -0,0 +1,37 @@ | |||
1 | check_active_images; | ||
2 | |||
3 | for kk = ind_active, | ||
4 | |||
5 | if ~exist(['x_' num2str(kk)]), | ||
6 | |||
7 | fprintf(1,'WARNING: Need to extract grid corners on image %d\n',kk); | ||
8 | |||
9 | active_images(kk) = 0; | ||
10 | |||
11 | eval(['dX_' num2str(kk) ' = NaN;']); | ||
12 | eval(['dY_' num2str(kk) ' = NaN;']); | ||
13 | |||
14 | eval(['wintx_' num2str(kk) ' = NaN;']); | ||
15 | eval(['winty_' num2str(kk) ' = NaN;']); | ||
16 | |||
17 | eval(['x_' num2str(kk) ' = NaN*ones(2,1);']); | ||
18 | eval(['X_' num2str(kk) ' = NaN*ones(3,1);']); | ||
19 | |||
20 | eval(['n_sq_x_' num2str(kk) ' = NaN;']); | ||
21 | eval(['n_sq_y_' num2str(kk) ' = NaN;']); | ||
22 | |||
23 | else | ||
24 | |||
25 | eval(['xkk = x_' num2str(kk) ';']); | ||
26 | |||
27 | if isnan(xkk(1)), | ||
28 | |||
29 | fprintf(1,'WARNING: Need to extract grid corners on image %d - This image is now set inactive\n',kk); | ||
30 | |||
31 | active_images(kk) = 0; | ||
32 | |||
33 | end; | ||
34 | |||
35 | end; | ||
36 | |||
37 | end; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/clear_windows.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/clear_windows.m new file mode 100755 index 0000000..1eccbd3 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/clear_windows.m | |||
@@ -0,0 +1,4 @@ | |||
1 | for kk = 1:n_ima, | ||
2 | eval(['clear wintx_' num2str(kk)]); | ||
3 | eval(['clear winty_' num2str(kk)]); | ||
4 | end; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/clearwin.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/clearwin.m new file mode 100755 index 0000000..a04be67 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/clearwin.m | |||
@@ -0,0 +1,10 @@ | |||
1 | % Function that clears all the wintx_i and winty_i | ||
2 | % In normal operation of the toolbox, this function should not be | ||
3 | % useful. | ||
4 | % only in cases where you want to re-extract corners using the Extract grid corners another time... not common. You might as well use the Recomp. corners. | ||
5 | |||
6 | for kk = 1:n_ima, | ||
7 | |||
8 | eval(['clear wintx_' num2str(kk) ' winty_' num2str(kk)]); | ||
9 | |||
10 | end; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/click_calib.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/click_calib.m new file mode 100755 index 0000000..1a6d2d7 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/click_calib.m | |||
@@ -0,0 +1,193 @@ | |||
1 | %if exist('images_read'); | ||
2 | % active_images = active_images & images_read; | ||
3 | %end; | ||
4 | |||
5 | var2fix = 'dX_default'; | ||
6 | |||
7 | fixvariable; | ||
8 | |||
9 | var2fix = 'dY_default'; | ||
10 | |||
11 | fixvariable; | ||
12 | |||
13 | var2fix = 'map'; | ||
14 | |||
15 | fixvariable; | ||
16 | |||
17 | |||
18 | if ~exist('n_ima'), | ||
19 | data_calib; | ||
20 | end; | ||
21 | |||
22 | check_active_images; | ||
23 | |||
24 | if ~exist(['I_' num2str(ind_active(1))]), | ||
25 | ima_read_calib; | ||
26 | if isempty(ind_read), | ||
27 | disp('Cannot extract corners without images'); | ||
28 | return; | ||
29 | end; | ||
30 | end; | ||
31 | |||
32 | |||
33 | %wintx = 10; % neigborhood of integration for | ||
34 | %winty = 10; % the corner finder | ||
35 | |||
36 | fprintf(1,'\nExtraction of the grid corners on the images\n'); | ||
37 | |||
38 | |||
39 | if ~exist('map'), map = gray(256); end; | ||
40 | |||
41 | |||
42 | disp('WARNING!!! Do not forget to change dX_default and dY_default in click_calib.m!!!') | ||
43 | |||
44 | if ~exist('dX_default'); | ||
45 | |||
46 | % Default size of the pattern squares; | ||
47 | |||
48 | % Setup of JY (old at Caltech) | ||
49 | %dX_default = 21.9250/11; | ||
50 | %dY_default = 18.1250/9; | ||
51 | |||
52 | % Setup of JY (new at Intel) | ||
53 | %dX_default = 1.9750; | ||
54 | %dY_default = 1.9865; | ||
55 | |||
56 | |||
57 | % Setup of Luis and Enrico | ||
58 | %dX_default = 67.7/16; | ||
59 | %dY_default = 50.65/12; | ||
60 | |||
61 | |||
62 | % Setup of German | ||
63 | %dX_default = 10.16; | ||
64 | %dY_default = 10.16; | ||
65 | |||
66 | % Setup of JY (new at Intel) | ||
67 | %dX_default = 1.9750*2.54; | ||
68 | %dY_default = 1.9865*2.54; | ||
69 | |||
70 | % Setup of JY - 3D calibration rig at Intel (new at Intel) | ||
71 | %dX_default = 3; | ||
72 | %dY_default = 3; | ||
73 | |||
74 | % Setup of JY - 3D calibration rig at Intel (new at Intel) - use units in mm to match Zhang | ||
75 | dX_default = 30; | ||
76 | dY_default = 30; | ||
77 | |||
78 | end; | ||
79 | |||
80 | |||
81 | if ~exist('dont_ask'), | ||
82 | dont_ask = 0; | ||
83 | end; | ||
84 | |||
85 | |||
86 | if ~dont_ask, | ||
87 | ima_numbers = input('Number(s) of image(s) to process ([] = all images) = '); | ||
88 | else | ||
89 | ima_numbers = []; | ||
90 | end; | ||
91 | |||
92 | if isempty(ima_numbers), | ||
93 | ima_proc = 1:n_ima; | ||
94 | else | ||
95 | ima_proc = ima_numbers; | ||
96 | end; | ||
97 | |||
98 | |||
99 | % Useful option to add images: | ||
100 | kk_first = ima_proc(1); %input('Start image number ([]=1=first): '); | ||
101 | |||
102 | %if isempty(kk_first), kk_first = 1; end; | ||
103 | |||
104 | |||
105 | if exist(['wintx_' num2str(kk_first)]), | ||
106 | |||
107 | eval(['wintxkk = wintx_' num2str(kk_first) ';']); | ||
108 | |||
109 | if isempty(wintxkk) | isnan(wintxkk), | ||
110 | |||
111 | disp('Window size for corner finder (wintx and winty):'); | ||
112 | wintx = input('wintx ([] = 5) = '); | ||
113 | if isempty(wintx), wintx = 5; end; | ||
114 | wintx = round(wintx); | ||
115 | winty = input('winty ([] = 5) = '); | ||
116 | if isempty(winty), winty = 5; end; | ||
117 | winty = round(winty); | ||
118 | |||
119 | fprintf(1,'Window size = %dx%d\n',2*wintx+1,2*winty+1); | ||
120 | |||
121 | end; | ||
122 | |||
123 | else | ||
124 | |||
125 | disp('Window size for corner finder (wintx and winty):'); | ||
126 | wintx = input('wintx ([] = 5) = '); | ||
127 | if isempty(wintx), wintx = 5; end; | ||
128 | wintx = round(wintx); | ||
129 | winty = input('winty ([] = 5) = '); | ||
130 | if isempty(winty), winty = 5; end; | ||
131 | winty = round(winty); | ||
132 | |||
133 | fprintf(1,'Window size = %dx%d\n',2*wintx+1,2*winty+1); | ||
134 | |||
135 | end; | ||
136 | |||
137 | |||
138 | for kk = ima_proc, | ||
139 | if exist(['I_' num2str(kk)]), | ||
140 | click_ima_calib; | ||
141 | active_images(kk) = 1; | ||
142 | else | ||
143 | eval(['dX_' num2str(kk) ' = NaN;']); | ||
144 | eval(['dY_' num2str(kk) ' = NaN;']); | ||
145 | |||
146 | eval(['wintx_' num2str(kk) ' = NaN;']); | ||
147 | eval(['winty_' num2str(kk) ' = NaN;']); | ||
148 | |||
149 | eval(['x_' num2str(kk) ' = NaN*ones(2,1);']); | ||
150 | eval(['X_' num2str(kk) ' = NaN*ones(3,1);']); | ||
151 | |||
152 | eval(['n_sq_x_' num2str(kk) ' = NaN;']); | ||
153 | eval(['n_sq_y_' num2str(kk) ' = NaN;']); | ||
154 | end; | ||
155 | end; | ||
156 | |||
157 | |||
158 | check_active_images; | ||
159 | |||
160 | |||
161 | % Fix potential non-existing variables: | ||
162 | |||
163 | for kk = 1:n_ima, | ||
164 | if ~exist(['x_' num2str(kk)]), | ||
165 | eval(['dX_' num2str(kk) ' = NaN;']); | ||
166 | eval(['dY_' num2str(kk) ' = NaN;']); | ||
167 | |||
168 | eval(['wintx_' num2str(kk) ' = NaN;']); | ||
169 | eval(['winty_' num2str(kk) ' = NaN;']); | ||
170 | |||
171 | eval(['x_' num2str(kk) ' = NaN*ones(2,1);']); | ||
172 | eval(['X_' num2str(kk) ' = NaN*ones(3,1);']); | ||
173 | |||
174 | eval(['n_sq_x_' num2str(kk) ' = NaN;']); | ||
175 | eval(['n_sq_y_' num2str(kk) ' = NaN;']); | ||
176 | end; | ||
177 | end; | ||
178 | |||
179 | |||
180 | string_save = 'save calib_data active_images ind_active wintx winty n_ima type_numbering N_slots first_num image_numbers format_image calib_name Hcal Wcal nx ny map dX_default dY_default dX dY'; | ||
181 | |||
182 | for kk = 1:n_ima, | ||
183 | string_save = [string_save ' X_' num2str(kk) ' x_' num2str(kk) ' n_sq_x_' num2str(kk) ' n_sq_y_' num2str(kk) ' wintx_' num2str(kk) ' winty_' num2str(kk) ' dX_' num2str(kk) ' dY_' num2str(kk)]; | ||
184 | end; | ||
185 | |||
186 | eval(string_save); | ||
187 | |||
188 | disp('done'); | ||
189 | |||
190 | return; | ||
191 | |||
192 | go_calib_optim; | ||
193 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/click_ima_calib.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/click_ima_calib.m new file mode 100755 index 0000000..f0fd4ca --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/click_ima_calib.m | |||
@@ -0,0 +1,230 @@ | |||
1 | % Cleaned-up version of init_calib.m | ||
2 | |||
3 | fprintf(1,'\nProcessing image %d...\n',kk); | ||
4 | |||
5 | eval(['I = I_' num2str(kk) ';']); | ||
6 | |||
7 | if exist(['wintx_' num2str(kk)]), | ||
8 | |||
9 | eval(['wintxkk = wintx_' num2str(kk) ';']); | ||
10 | |||
11 | if ~isempty(wintxkk) & ~isnan(wintxkk), | ||
12 | |||
13 | eval(['wintx = wintx_' num2str(kk) ';']); | ||
14 | eval(['winty = winty_' num2str(kk) ';']); | ||
15 | |||
16 | end; | ||
17 | end; | ||
18 | |||
19 | |||
20 | fprintf(1,'Using (wintx,winty)=(%d,%d) - Window size = %dx%d\n',wintx,winty,2*wintx+1,2*winty+1); | ||
21 | |||
22 | |||
23 | figure(2); | ||
24 | image(I); | ||
25 | colormap(map); | ||
26 | |||
27 | title(['Click on the four extreme corners of the rectangular pattern... Image ' num2str(kk)]); | ||
28 | |||
29 | disp('Click on the four extreme corners of the rectangular complete pattern...'); | ||
30 | |||
31 | [x,y] = ginput3(4); | ||
32 | |||
33 | [Xc,good,bad,type] = cornerfinder([x';y'],I,winty,wintx); % the four corners | ||
34 | |||
35 | x = Xc(1,:)'; | ||
36 | y = Xc(2,:)'; | ||
37 | |||
38 | [y,indy] = sort(y); | ||
39 | x = x(indy); | ||
40 | |||
41 | if (x(2) > x(1)), | ||
42 | x4 = x(1);y4 = y(1); x3 = x(2); y3 = y(2); | ||
43 | else | ||
44 | x4 = x(2);y4 = y(2); x3 = x(1); y3 = y(1); | ||
45 | end; | ||
46 | if (x(3) > x(4)), | ||
47 | x2 = x(3);y2 = y(3); x1 = x(4); y1 = y(4); | ||
48 | else | ||
49 | x2 = x(4);y2 = y(4); x1 = x(3); y1 = y(3); | ||
50 | end; | ||
51 | |||
52 | x = [x1;x2;x3;x4]; | ||
53 | y = [y1;y2;y3;y4]; | ||
54 | |||
55 | |||
56 | figure(2); hold on; | ||
57 | plot([x;x(1)],[y;y(1)],'g-'); | ||
58 | plot(x,y,'og'); | ||
59 | hx=text((x(4)+x(3))/2,(y(4)+y(3))/2 - 20,'X'); | ||
60 | set(hx,'color','g','Fontsize',14); | ||
61 | hy=text((x(4)+x(1))/2-20,(y(4)+y(1))/2,'Y'); | ||
62 | set(hy,'color','g','Fontsize',14); | ||
63 | hold off; | ||
64 | |||
65 | |||
66 | % Try to automatically count the number of squares in the grid | ||
67 | |||
68 | n_sq_x1 = count_squares(I,x1,y1,x2,y2,wintx); | ||
69 | n_sq_x2 = count_squares(I,x3,y3,x4,y4,wintx); | ||
70 | n_sq_y1 = count_squares(I,x2,y2,x3,y3,wintx); | ||
71 | n_sq_y2 = count_squares(I,x4,y4,x1,y1,wintx); | ||
72 | |||
73 | |||
74 | |||
75 | % If could not count the number of squares, enter manually | ||
76 | |||
77 | if (n_sq_x1~=n_sq_x2)|(n_sq_y1~=n_sq_y2), | ||
78 | |||
79 | |||
80 | disp('Could not count the number of squares in the grid. Enter manually.'); | ||
81 | n_sq_x = input('Number of squares along the X direction ([]=10) = '); %6 | ||
82 | if isempty(n_sq_x), n_sq_x = 10; end; | ||
83 | n_sq_y = input('Number of squares along the Y direction ([]=10) = '); %6 | ||
84 | if isempty(n_sq_y), n_sq_y = 10; end; | ||
85 | |||
86 | else | ||
87 | |||
88 | n_sq_x = n_sq_x1; | ||
89 | n_sq_y = n_sq_y1; | ||
90 | |||
91 | end; | ||
92 | |||
93 | |||
94 | % Enter the size of each square | ||
95 | |||
96 | dX = input(['Size dX of each square along the X direction ([]=' num2str(dX_default) 'mm) = ']); | ||
97 | dY = input(['Size dY of each square along the Y direction ([]=' num2str(dY_default) 'mm) = ']); | ||
98 | if isempty(dX), dX = dX_default; else dX_default = dX; end; | ||
99 | if isempty(dY), dY = dY_default; else dY_default = dY; end; | ||
100 | |||
101 | % Compute the inside points through computation of the planar homography (collineation) | ||
102 | |||
103 | a00 = [x(1);y(1);1]; | ||
104 | a10 = [x(2);y(2);1]; | ||
105 | a11 = [x(3);y(3);1]; | ||
106 | a01 = [x(4);y(4);1]; | ||
107 | |||
108 | |||
109 | % Compute the planar collineation: (return the normalization matrix as well) | ||
110 | |||
111 | [Homo,Hnorm,inv_Hnorm] = compute_homography ([a00 a10 a11 a01],[0 1 1 0;0 0 1 1;1 1 1 1]); | ||
112 | |||
113 | |||
114 | % Build the grid using the planar collineation: | ||
115 | |||
116 | x_l = ((0:n_sq_x)'*ones(1,n_sq_y+1))/n_sq_x; | ||
117 | y_l = (ones(n_sq_x+1,1)*(0:n_sq_y))/n_sq_y; | ||
118 | pts = [x_l(:) y_l(:) ones((n_sq_x+1)*(n_sq_y+1),1)]'; | ||
119 | |||
120 | XX = Homo*pts; | ||
121 | XX = XX(1:2,:) ./ (ones(2,1)*XX(3,:)); | ||
122 | |||
123 | |||
124 | % Complete size of the rectangle | ||
125 | |||
126 | W = n_sq_x*dX; | ||
127 | L = n_sq_y*dY; | ||
128 | |||
129 | |||
130 | |||
131 | |||
132 | %%%%%%%%%%%%%%%%%%%%%%%% ADDITIONAL STUFF IN THE CASE OF HIGHLY DISTORTED IMAGES %%%%%%%%%%%%% | ||
133 | figure(2); | ||
134 | hold on; | ||
135 | plot(XX(1,:),XX(2,:),'r+'); | ||
136 | title('The red crosses should be close to the image corners'); | ||
137 | hold off; | ||
138 | |||
139 | disp('If the guessed grid corners (red crosses on the image) are not close to the actual corners,'); | ||
140 | disp('it is necessary to enter an initial guess for the radial distortion factor kc (useful for subpixel detection)'); | ||
141 | quest_distort = input('Need of an initial guess for distortion? ([]=no, other=yes) '); | ||
142 | |||
143 | quest_distort = ~isempty(quest_distort); | ||
144 | |||
145 | if quest_distort, | ||
146 | % Estimation of focal length: | ||
147 | c_g = [size(I,2);size(I,1)]/2 + .5; | ||
148 | f_g = Distor2Calib(0,[[x(1) x(2) x(4) x(3)] - c_g(1);[y(1) y(2) y(4) y(3)] - c_g(2)],1,1,4,W,L,[-W/2 W/2 W/2 -W/2;L/2 L/2 -L/2 -L/2; 0 0 0 0],100,1,1); | ||
149 | f_g = mean(f_g); | ||
150 | script_fit_distortion; | ||
151 | end; | ||
152 | %%%%%%%%%%%%%%%%%%%%% END ADDITIONAL STUFF IN THE CASE OF HIGHLY DISTORTED IMAGES %%%%%%%%%%%%% | ||
153 | |||
154 | |||
155 | |||
156 | |||
157 | |||
158 | Np = (n_sq_x+1)*(n_sq_y+1); | ||
159 | |||
160 | disp('Corner extraction...'); | ||
161 | |||
162 | grid_pts = cornerfinder(XX,I,winty,wintx); %%% Finds the exact corners at every points! | ||
163 | |||
164 | |||
165 | |||
166 | %save all_corners x y grid_pts | ||
167 | |||
168 | grid_pts = grid_pts - 1; % subtract 1 to bring the origin to (0,0) instead of (1,1) in matlab (not necessary in C) | ||
169 | |||
170 | |||
171 | |||
172 | ind_corners = [1 n_sq_x+1 (n_sq_x+1)*n_sq_y+1 (n_sq_x+1)*(n_sq_y+1)]; % index of the 4 corners | ||
173 | ind_orig = (n_sq_x+1)*n_sq_y + 1; | ||
174 | xorig = grid_pts(1,ind_orig); | ||
175 | yorig = grid_pts(2,ind_orig); | ||
176 | dxpos = mean([grid_pts(:,ind_orig) grid_pts(:,ind_orig+1)]'); | ||
177 | dypos = mean([grid_pts(:,ind_orig) grid_pts(:,ind_orig-n_sq_x-1)]'); | ||
178 | |||
179 | |||
180 | x_box_kk = [grid_pts(1,:)-(wintx+.5);grid_pts(1,:)+(wintx+.5);grid_pts(1,:)+(wintx+.5);grid_pts(1,:)-(wintx+.5);grid_pts(1,:)-(wintx+.5)]; | ||
181 | y_box_kk = [grid_pts(2,:)-(winty+.5);grid_pts(2,:)-(winty+.5);grid_pts(2,:)+(winty+.5);grid_pts(2,:)+(winty+.5);grid_pts(2,:)-(winty+.5)]; | ||
182 | |||
183 | |||
184 | figure(3); | ||
185 | image(I); colormap(map); hold on; | ||
186 | plot(grid_pts(1,:)+1,grid_pts(2,:)+1,'r+'); | ||
187 | plot(x_box_kk+1,y_box_kk+1,'-b'); | ||
188 | plot(grid_pts(1,ind_corners)+1,grid_pts(2,ind_corners)+1,'mo'); | ||
189 | plot(xorig+1,yorig+1,'*m'); | ||
190 | h = text(xorig-15,yorig-15,'O'); | ||
191 | set(h,'Color','m','FontSize',14); | ||
192 | h2 = text(dxpos(1)-10,dxpos(2)-10,'dX'); | ||
193 | set(h2,'Color','g','FontSize',14); | ||
194 | h3 = text(dypos(1)-25,dypos(2)-3,'dY'); | ||
195 | set(h3,'Color','g','FontSize',14); | ||
196 | xlabel('Xc (in camera frame)'); | ||
197 | ylabel('Yc (in camera frame)'); | ||
198 | title('Extracted corners'); | ||
199 | zoom on; | ||
200 | drawnow; | ||
201 | hold off; | ||
202 | |||
203 | |||
204 | Xi = reshape(([0:n_sq_x]*dX)'*ones(1,n_sq_y+1),Np,1)'; | ||
205 | Yi = reshape(ones(n_sq_x+1,1)*[n_sq_y:-1:0]*dY,Np,1)'; | ||
206 | Zi = zeros(1,Np); | ||
207 | |||
208 | Xgrid = [Xi;Yi;Zi]; | ||
209 | |||
210 | |||
211 | % All the point coordinates (on the image, and in 3D) - for global optimization: | ||
212 | |||
213 | x = grid_pts; | ||
214 | X = Xgrid; | ||
215 | |||
216 | |||
217 | % Saves all the data into variables: | ||
218 | |||
219 | eval(['dX_' num2str(kk) ' = dX;']); | ||
220 | eval(['dY_' num2str(kk) ' = dY;']); | ||
221 | |||
222 | eval(['wintx_' num2str(kk) ' = wintx;']); | ||
223 | eval(['winty_' num2str(kk) ' = winty;']); | ||
224 | |||
225 | eval(['x_' num2str(kk) ' = x;']); | ||
226 | eval(['X_' num2str(kk) ' = X;']); | ||
227 | |||
228 | eval(['n_sq_x_' num2str(kk) ' = n_sq_x;']); | ||
229 | eval(['n_sq_y_' num2str(kk) ' = n_sq_y;']); | ||
230 | \ No newline at end of file | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/click_ima_calib3D.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/click_ima_calib3D.m new file mode 100755 index 0000000..7718268 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/click_ima_calib3D.m | |||
@@ -0,0 +1,482 @@ | |||
1 | % Cleaned-up version of init_calib.m | ||
2 | |||
3 | eval(['I = I_' num2str(kk) ';']); | ||
4 | |||
5 | figure(2); | ||
6 | image(I); | ||
7 | colormap(map); | ||
8 | |||
9 | |||
10 | |||
11 | |||
12 | |||
13 | %%%%%%%%%%%%%%%%%%%%%%%%% LEFT PATTERN ACQUISITION %%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
14 | |||
15 | |||
16 | |||
17 | title(['Click on the four extreme corners of the left rectangular pattern... Image ' num2str(kk)]); | ||
18 | |||
19 | disp('Click on the four extreme corners of the left rectangular pattern...'); | ||
20 | |||
21 | [x,y] = ginput3(4); | ||
22 | |||
23 | [Xc,good,bad,type] = cornerfinder([x';y'],I,winty,wintx); % the four corners | ||
24 | |||
25 | x = Xc(1,:)'; | ||
26 | y = Xc(2,:)'; | ||
27 | |||
28 | [y,indy] = sort(y); | ||
29 | x = x(indy); | ||
30 | |||
31 | if (x(2) > x(1)), | ||
32 | x4 = x(1);y4 = y(1); x3 = x(2); y3 = y(2); | ||
33 | else | ||
34 | x4 = x(2);y4 = y(2); x3 = x(1); y3 = y(1); | ||
35 | end; | ||
36 | if (x(3) > x(4)), | ||
37 | x2 = x(3);y2 = y(3); x1 = x(4); y1 = y(4); | ||
38 | else | ||
39 | x2 = x(4);y2 = y(4); x1 = x(3); y1 = y(3); | ||
40 | end; | ||
41 | |||
42 | x = [x1;x2;x3;x4]; | ||
43 | y = [y1;y2;y3;y4]; | ||
44 | |||
45 | |||
46 | figure(2); hold on; | ||
47 | plot([x;x(1)],[y;y(1)],'g-'); | ||
48 | plot(x,y,'og'); | ||
49 | hx=text((x(4)+x(3))/2,(y(4)+y(3))/2 - 20,'X'); | ||
50 | set(hx,'color','g','Fontsize',14); | ||
51 | hy=text((x(4)+x(1))/2-20,(y(4)+y(1))/2,'Y'); | ||
52 | set(hy,'color','g','Fontsize',14); | ||
53 | hold off; | ||
54 | |||
55 | drawnow; | ||
56 | |||
57 | |||
58 | % Try to automatically count the number of squares in the grid | ||
59 | |||
60 | n_sq_x1 = count_squares(I,x1,y1,x2,y2,wintx); | ||
61 | n_sq_x2 = count_squares(I,x3,y3,x4,y4,wintx); | ||
62 | n_sq_y1 = count_squares(I,x2,y2,x3,y3,wintx); | ||
63 | n_sq_y2 = count_squares(I,x4,y4,x1,y1,wintx); | ||
64 | |||
65 | |||
66 | |||
67 | % If could not count the number of squares, enter manually | ||
68 | |||
69 | if (n_sq_x1~=n_sq_x2)|(n_sq_y1~=n_sq_y2), | ||
70 | |||
71 | |||
72 | disp('Could not count the number of squares in the grid. Enter manually.'); | ||
73 | n_sq_x = input('Number of squares along the X direction ([]=10) = '); %6 | ||
74 | if isempty(n_sq_x), n_sq_x = 10; end; | ||
75 | n_sq_y = input('Number of squares along the Y direction ([]=10) = '); %6 | ||
76 | if isempty(n_sq_y), n_sq_y = 10; end; | ||
77 | |||
78 | else | ||
79 | |||
80 | n_sq_x = n_sq_x1; | ||
81 | n_sq_y = n_sq_y1; | ||
82 | |||
83 | end; | ||
84 | |||
85 | |||
86 | if 1, | ||
87 | % Enter the size of each square | ||
88 | |||
89 | dX = input(['Size dX of each square along the X direction ([]=' num2str(dX_default) 'cm) = ']); | ||
90 | dY = input(['Size dY of each square along the Y direction ([]=' num2str(dY_default) 'cm) = ']); | ||
91 | if isempty(dX), dX = dX_default; else dX_default = dX; end; | ||
92 | if isempty(dY), dY = dY_default; else dY_default = dY; end; | ||
93 | |||
94 | else | ||
95 | |||
96 | dX = 3; | ||
97 | dY = 3; | ||
98 | |||
99 | end; | ||
100 | |||
101 | |||
102 | % Compute the inside points through computation of the planar homography (collineation) | ||
103 | |||
104 | a00 = [x(1);y(1);1]; | ||
105 | a10 = [x(2);y(2);1]; | ||
106 | a11 = [x(3);y(3);1]; | ||
107 | a01 = [x(4);y(4);1]; | ||
108 | |||
109 | |||
110 | % Compute the planart collineation: (return the normalization matrice as well) | ||
111 | |||
112 | [Homo,Hnorm,inv_Hnorm] = compute_collineation (a00, a10, a11, a01); | ||
113 | |||
114 | |||
115 | % Build the grid using the planar collineation: | ||
116 | |||
117 | x_l = ((0:n_sq_x)'*ones(1,n_sq_y+1))/n_sq_x; | ||
118 | y_l = (ones(n_sq_x+1,1)*(0:n_sq_y))/n_sq_y; | ||
119 | pts = [x_l(:) y_l(:) ones((n_sq_x+1)*(n_sq_y+1),1)]'; | ||
120 | |||
121 | XX = Homo*pts; | ||
122 | XX = XX(1:2,:) ./ (ones(2,1)*XX(3,:)); | ||
123 | |||
124 | |||
125 | % Complete size of the rectangle | ||
126 | |||
127 | W = n_sq_x*dX; | ||
128 | L = n_sq_y*dY; | ||
129 | |||
130 | |||
131 | |||
132 | if 1, | ||
133 | %%%%%%%%%%%%%%%%%%%%%%%% ADDITIONAL STUFF IN THE CASE OF HIGHLY DISTORTED IMAGES %%%%%%%%%%%%% | ||
134 | figure(2); | ||
135 | hold on; | ||
136 | plot(XX(1,:),XX(2,:),'r+'); | ||
137 | title('The red crosses should be close to the image corners'); | ||
138 | hold off; | ||
139 | |||
140 | disp('If the guessed grid corners (red crosses on the image) are not close to the actual corners,'); | ||
141 | disp('it is necessary to enter an initial guess for the radial distortion factor kc (useful for subpixel detection)'); | ||
142 | quest_distort = input('Need of an initial guess for distortion? ([]=no, other=yes) '); | ||
143 | |||
144 | quest_distort = ~isempty(quest_distort); | ||
145 | |||
146 | if quest_distort, | ||
147 | % Estimation of focal length: | ||
148 | c_g = [size(I,2);size(I,1)]/2 + .5; | ||
149 | f_g = Distor2Calib(0,[[x(1) x(2) x(4) x(3)] - c_g(1);[y(1) y(2) y(4) y(3)] - c_g(2)],1,1,4,W,L,[-W/2 W/2 W/2 -W/2;L/2 L/2 -L/2 -L/2; 0 0 0 0],100,1,1); | ||
150 | f_g = mean(f_g); | ||
151 | script_fit_distortion; | ||
152 | end; | ||
153 | %%%%%%%%%%%%%%%%%%%%% END ADDITIONAL STUFF IN THE CASE OF HIGHLY DISTORTED IMAGES %%%%%%%%%%%%% | ||
154 | end; | ||
155 | |||
156 | |||
157 | Np = (n_sq_x+1)*(n_sq_y+1); | ||
158 | |||
159 | disp('Corner extraction...'); | ||
160 | |||
161 | grid_pts = cornerfinder(XX,I,winty,wintx); %%% Finds the exact corners at every points! | ||
162 | |||
163 | %save all_corners x y grid_pts | ||
164 | |||
165 | grid_pts = grid_pts - 1; % subtract 1 to bring the origin to (0,0) instead of (1,1) in matlab (not necessary in C) | ||
166 | |||
167 | |||
168 | % Global Homography from plane to pixel coordinates: | ||
169 | |||
170 | H_total = [1 0 -1 ; 0 1 -1 ; 0 0 1]*Homo*[1 0 0;0 -1 1;0 0 1]*[1/W 0 0 ; 0 1/L 0; 0 0 1]; | ||
171 | % WARNING!!! the first matrix (on the left side) takes care of the transformation of the pixel cooredinates by -1 (previous line) | ||
172 | % If it is not done, then this matrix should not appear (in C) | ||
173 | H_total = H_total / H_total(3,3); | ||
174 | |||
175 | |||
176 | ind_corners = [1 n_sq_x+1 (n_sq_x+1)*n_sq_y+1 (n_sq_x+1)*(n_sq_y+1)]; % index of the 4 corners | ||
177 | ind_orig = (n_sq_x+1)*n_sq_y + 1; | ||
178 | xorig = grid_pts(1,ind_orig); | ||
179 | yorig = grid_pts(2,ind_orig); | ||
180 | dxpos = mean([grid_pts(:,ind_orig) grid_pts(:,ind_orig+1)]'); | ||
181 | dypos = mean([grid_pts(:,ind_orig) grid_pts(:,ind_orig-n_sq_x-1)]'); | ||
182 | |||
183 | |||
184 | x_box_kk = [grid_pts(1,:)-(wintx+.5);grid_pts(1,:)+(wintx+.5);grid_pts(1,:)+(wintx+.5);grid_pts(1,:)-(wintx+.5);grid_pts(1,:)-(wintx+.5)]; | ||
185 | y_box_kk = [grid_pts(2,:)-(winty+.5);grid_pts(2,:)-(winty+.5);grid_pts(2,:)+(winty+.5);grid_pts(2,:)+(winty+.5);grid_pts(2,:)-(winty+.5)]; | ||
186 | |||
187 | |||
188 | figure(3); | ||
189 | image(I); colormap(map); hold on; | ||
190 | plot(grid_pts(1,:)+1,grid_pts(2,:)+1,'r+'); | ||
191 | plot(x_box_kk+1,y_box_kk+1,'-b'); | ||
192 | plot(grid_pts(1,ind_corners)+1,grid_pts(2,ind_corners)+1,'mo'); | ||
193 | plot(xorig+1,yorig+1,'*m'); | ||
194 | h = text(xorig-15,yorig-15,'O'); | ||
195 | set(h,'Color','m','FontSize',14); | ||
196 | h2 = text(dxpos(1)-10,dxpos(2)-10,'dX'); | ||
197 | set(h2,'Color','g','FontSize',14); | ||
198 | h3 = text(dypos(1)-25,dypos(2)-3,'dY'); | ||
199 | set(h3,'Color','g','FontSize',14); | ||
200 | xlabel('Xc (in camera frame)'); | ||
201 | ylabel('Yc (in camera frame)'); | ||
202 | title('Extracted corners'); | ||
203 | zoom on; | ||
204 | drawnow; | ||
205 | hold off; | ||
206 | |||
207 | |||
208 | Xi = reshape(([0:n_sq_x]*dX)'*ones(1,n_sq_y+1),Np,1)'; | ||
209 | Yi = reshape(ones(n_sq_x+1,1)*[n_sq_y:-1:0]*dY,Np,1)'; | ||
210 | Zi = zeros(1,Np); | ||
211 | |||
212 | Xgrid = [Xi;Yi;Zi]; | ||
213 | |||
214 | |||
215 | % All the point coordinates (on the image, and in 3D) - for global optimization: | ||
216 | |||
217 | x = grid_pts; | ||
218 | X = Xgrid; | ||
219 | |||
220 | |||
221 | % The left pannel info: | ||
222 | |||
223 | xl = x; | ||
224 | Xl = X; | ||
225 | nl_sq_x = n_sq_x; | ||
226 | nl_sq_y = n_sq_y; | ||
227 | Hl = H_total; | ||
228 | |||
229 | |||
230 | |||
231 | |||
232 | |||
233 | |||
234 | %%%%%%%%%%%%%%%%%%%%%%%%% RIGHT PATTERN ACQUISITION %%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
235 | |||
236 | |||
237 | x1 = a10(1)/a10(3); | ||
238 | x4 = a11(1)/a11(3); | ||
239 | |||
240 | y1 = a10(2)/a10(3); | ||
241 | y4 = a11(2)/a11(3); | ||
242 | |||
243 | |||
244 | figure(2); | ||
245 | hold on; | ||
246 | plot([x1 x4],[y1 y4],'c-'); | ||
247 | plot([x1 x4],[y1 y4],'co'); | ||
248 | hold off; | ||
249 | |||
250 | title(['Click on the two remaining extreme corners of the right rectangular pattern... Image ' num2str(kk)]); | ||
251 | |||
252 | disp('Click on the two remaining extreme corners of the right rectangular pattern...'); | ||
253 | |||
254 | [x,y] = ginput3(2); | ||
255 | |||
256 | [Xc,good,bad,type] = cornerfinder([x';y'],I,winty,wintx); % the four corners | ||
257 | |||
258 | x = Xc(1,:)'; | ||
259 | y = Xc(2,:)'; | ||
260 | |||
261 | [y,indy] = sort(y); | ||
262 | x = x(indy); | ||
263 | |||
264 | x2 = x(2); | ||
265 | x3 = x(1); | ||
266 | |||
267 | y2 = y(2); | ||
268 | y3 = y(1); | ||
269 | |||
270 | |||
271 | x = [x1;x2;x3;x4]; | ||
272 | y = [y1;y2;y3;y4]; | ||
273 | |||
274 | figure(2); hold on; | ||
275 | plot([x;x(1)],[y;y(1)],'c-'); | ||
276 | plot(x,y,'oc'); | ||
277 | hx=text((x(4)+x(3))/2,(y(4)+y(3))/2 - 20,'X'); | ||
278 | set(hx,'color','c','Fontsize',14); | ||
279 | hy=text((x(4)+x(1))/2-20,(y(4)+y(1))/2,'Y'); | ||
280 | set(hy,'color','c','Fontsize',14); | ||
281 | hold off; | ||
282 | drawnow; | ||
283 | |||
284 | |||
285 | % Try to automatically count the number of squares in the grid | ||
286 | |||
287 | n_sq_x1 = count_squares(I,x1,y1,x2,y2,wintx); | ||
288 | n_sq_x2 = count_squares(I,x3,y3,x4,y4,wintx); | ||
289 | n_sq_y1 = count_squares(I,x2,y2,x3,y3,wintx); | ||
290 | n_sq_y2 = count_squares(I,x4,y4,x1,y1,wintx); | ||
291 | |||
292 | |||
293 | |||
294 | % If could not count the number of squares, enter manually | ||
295 | |||
296 | if (n_sq_x1~=n_sq_x2)|(n_sq_y1~=n_sq_y2), | ||
297 | |||
298 | |||
299 | disp('Could not count the number of squares in the grid. Enter manually.'); | ||
300 | n_sq_x = input('Number of squares along the X direction ([]=10) = '); %6 | ||
301 | if isempty(n_sq_x), n_sq_x = 10; end; | ||
302 | n_sq_y = input('Number of squares along the Y direction ([]=10) = '); %6 | ||
303 | if isempty(n_sq_y), n_sq_y = 10; end; | ||
304 | |||
305 | else | ||
306 | |||
307 | n_sq_x = n_sq_x1; | ||
308 | n_sq_y = n_sq_y1; | ||
309 | |||
310 | end; | ||
311 | |||
312 | |||
313 | if 1, | ||
314 | % Enter the size of each square | ||
315 | |||
316 | dX = input(['Size dX of each square along the X direction ([]=' num2str(dX_default) 'cm) = ']); | ||
317 | dY = input(['Size dY of each square along the Y direction ([]=' num2str(dY_default) 'cm) = ']); | ||
318 | if isempty(dX), dX = dX_default; else dX_default = dX; end; | ||
319 | if isempty(dY), dY = dY_default; else dY_default = dY; end; | ||
320 | |||
321 | else | ||
322 | |||
323 | dX = 3; | ||
324 | dY = 3; | ||
325 | |||
326 | end; | ||
327 | |||
328 | |||
329 | % Compute the inside points through computation of the planar homography (collineation) | ||
330 | |||
331 | a00 = [x(1);y(1);1]; | ||
332 | a10 = [x(2);y(2);1]; | ||
333 | a11 = [x(3);y(3);1]; | ||
334 | a01 = [x(4);y(4);1]; | ||
335 | |||
336 | |||
337 | % Compute the planart collineation: (return the normalization matrice as well) | ||
338 | |||
339 | [Homo,Hnorm,inv_Hnorm] = compute_collineation (a00, a10, a11, a01); | ||
340 | |||
341 | |||
342 | % Build the grid using the planar collineation: | ||
343 | |||
344 | x_l = ((0:n_sq_x)'*ones(1,n_sq_y+1))/n_sq_x; | ||
345 | y_l = (ones(n_sq_x+1,1)*(0:n_sq_y))/n_sq_y; | ||
346 | pts = [x_l(:) y_l(:) ones((n_sq_x+1)*(n_sq_y+1),1)]'; | ||
347 | |||
348 | XX = Homo*pts; | ||
349 | XX = XX(1:2,:) ./ (ones(2,1)*XX(3,:)); | ||
350 | |||
351 | |||
352 | % Complete size of the rectangle | ||
353 | |||
354 | W = n_sq_x*dX; | ||
355 | L = n_sq_y*dY; | ||
356 | |||
357 | |||
358 | |||
359 | if 1, | ||
360 | %%%%%%%%%%%%%%%%%%%%%%%% ADDITIONAL STUFF IN THE CASE OF HIGHLY DISTORTED IMAGES %%%%%%%%%%%%% | ||
361 | figure(2); | ||
362 | hold on; | ||
363 | plot(XX(1,:),XX(2,:),'r+'); | ||
364 | title('The red crosses should be close to the image corners'); | ||
365 | hold off; | ||
366 | |||
367 | disp('If the guessed grid corners (red crosses on the image) are not close to the actual corners,'); | ||
368 | disp('it is necessary to enter an initial guess for the radial distortion factor kc (useful for subpixel detection)'); | ||
369 | quest_distort = input('Need of an initial guess for distortion? ([]=no, other=yes) '); | ||
370 | |||
371 | quest_distort = ~isempty(quest_distort); | ||
372 | |||
373 | if quest_distort, | ||
374 | % Estimation of focal length: | ||
375 | c_g = [size(I,2);size(I,1)]/2 + .5; | ||
376 | f_g = Distor2Calib(0,[[x(1) x(2) x(4) x(3)] - c_g(1);[y(1) y(2) y(4) y(3)] - c_g(2)],1,1,4,W,L,[-W/2 W/2 W/2 -W/2;L/2 L/2 -L/2 -L/2; 0 0 0 0],100,1,1); | ||
377 | f_g = mean(f_g); | ||
378 | script_fit_distortion; | ||
379 | end; | ||
380 | %%%%%%%%%%%%%%%%%%%%% END ADDITIONAL STUFF IN THE CASE OF HIGHLY DISTORTED IMAGES %%%%%%%%%%%%% | ||
381 | end; | ||
382 | |||
383 | |||
384 | Np = (n_sq_x+1)*(n_sq_y+1); | ||
385 | |||
386 | disp('Corner extraction...'); | ||
387 | |||
388 | grid_pts = cornerfinder(XX,I,winty,wintx); %%% Finds the exact corners at every points! | ||
389 | |||
390 | %save all_corners x y grid_pts | ||
391 | |||
392 | grid_pts = grid_pts - 1; % subtract 1 to bring the origin to (0,0) instead of (1,1) in matlab (not necessary in C) | ||
393 | |||
394 | |||
395 | % Global Homography from plane to pixel coordinates: | ||
396 | |||
397 | H_total = [1 0 -1 ; 0 1 -1 ; 0 0 1]*Homo*[1 0 0;0 -1 1;0 0 1]*[1/W 0 0 ; 0 1/L 0; 0 0 1]; | ||
398 | % WARNING!!! the first matrix (on the left side) takes care of the transformation of the pixel cooredinates by -1 (previous line) | ||
399 | % If it is not done, then this matrix should not appear (in C) | ||
400 | H_total = H_total / H_total(3,3); | ||
401 | |||
402 | |||
403 | ind_corners = [1 n_sq_x+1 (n_sq_x+1)*n_sq_y+1 (n_sq_x+1)*(n_sq_y+1)]; % index of the 4 corners | ||
404 | ind_orig = (n_sq_x+1)*n_sq_y + 1; | ||
405 | xorig = grid_pts(1,ind_orig); | ||
406 | yorig = grid_pts(2,ind_orig); | ||
407 | dxpos = mean([grid_pts(:,ind_orig) grid_pts(:,ind_orig+1)]'); | ||
408 | dypos = mean([grid_pts(:,ind_orig) grid_pts(:,ind_orig-n_sq_x-1)]'); | ||
409 | |||
410 | |||
411 | x_box_kk = [grid_pts(1,:)-(wintx+.5);grid_pts(1,:)+(wintx+.5);grid_pts(1,:)+(wintx+.5);grid_pts(1,:)-(wintx+.5);grid_pts(1,:)-(wintx+.5)]; | ||
412 | y_box_kk = [grid_pts(2,:)-(winty+.5);grid_pts(2,:)-(winty+.5);grid_pts(2,:)+(winty+.5);grid_pts(2,:)+(winty+.5);grid_pts(2,:)-(winty+.5)]; | ||
413 | |||
414 | |||
415 | figure(3); | ||
416 | hold on; | ||
417 | plot(grid_pts(1,:)+1,grid_pts(2,:)+1,'r+'); | ||
418 | plot(x_box_kk+1,y_box_kk+1,'-b'); | ||
419 | plot(grid_pts(1,ind_corners)+1,grid_pts(2,ind_corners)+1,'mo'); | ||
420 | plot(xorig+1,yorig+1,'*m'); | ||
421 | h = text(xorig-15,yorig-15,'O'); | ||
422 | set(h,'Color','m','FontSize',14); | ||
423 | h2 = text(dxpos(1)-10,dxpos(2)-10,'dX'); | ||
424 | set(h2,'Color','g','FontSize',14); | ||
425 | h3 = text(dypos(1)-25,dypos(2)-3,'dY'); | ||
426 | set(h3,'Color','g','FontSize',14); | ||
427 | xlabel('Xc (in camera frame)'); | ||
428 | ylabel('Yc (in camera frame)'); | ||
429 | title('Extracted corners'); | ||
430 | zoom on; | ||
431 | drawnow; | ||
432 | hold off; | ||
433 | |||
434 | |||
435 | Xi = reshape(([0:n_sq_x]*dX)'*ones(1,n_sq_y+1),Np,1)'; | ||
436 | Yi = reshape(ones(n_sq_x+1,1)*[n_sq_y:-1:0]*dY,Np,1)'; | ||
437 | Zi = zeros(1,Np); | ||
438 | |||
439 | Xgrid = [Xi;Yi;Zi]; | ||
440 | |||
441 | |||
442 | % All the point coordinates (on the image, and in 3D) - for global optimization: | ||
443 | |||
444 | x = grid_pts; | ||
445 | X = Xgrid; | ||
446 | |||
447 | |||
448 | % The right pannel info: | ||
449 | |||
450 | xr = x; | ||
451 | Xr = X; | ||
452 | nr_sq_x = n_sq_x; | ||
453 | nr_sq_y = n_sq_y; | ||
454 | Hr = H_total; | ||
455 | |||
456 | |||
457 | |||
458 | %%%%%%%% REGROUP THE LEFT AND RIHT PATTERNS %%%%%%%%%%%%% | ||
459 | |||
460 | |||
461 | Xr2 = [0 0 1;0 1 0;-1 0 0]*Xr + [dX*nl_sq_x;0;0]*ones(1,length(Xr)); | ||
462 | |||
463 | |||
464 | x = [xl xr]; | ||
465 | |||
466 | X = [Xl Xr2]; | ||
467 | |||
468 | |||
469 | |||
470 | eval(['x_' num2str(kk) ' = x;']); | ||
471 | eval(['X_' num2str(kk) ' = X;']); | ||
472 | |||
473 | eval(['nl_sq_x_' num2str(kk) ' = nl_sq_x;']); | ||
474 | eval(['nl_sq_y_' num2str(kk) ' = nl_sq_y;']); | ||
475 | |||
476 | eval(['nr_sq_x_' num2str(kk) ' = nr_sq_x;']); | ||
477 | eval(['nr_sq_y_' num2str(kk) ' = nr_sq_y;']); | ||
478 | |||
479 | % Save the global planar homography: | ||
480 | |||
481 | eval(['Hl_' num2str(kk) ' = Hl;']); | ||
482 | eval(['Hr_' num2str(kk) ' = Hr;']); \ No newline at end of file | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/comp_distortion.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/comp_distortion.m new file mode 100755 index 0000000..a0f03de --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/comp_distortion.m | |||
@@ -0,0 +1,38 @@ | |||
1 | function [x_comp] = comp_distortion(x_dist,k2); | ||
2 | |||
3 | % [x_comp] = comp_distortion(x_dist,k2); | ||
4 | % | ||
5 | % compensates the radial distortion of the camera | ||
6 | % on the image plane. | ||
7 | % | ||
8 | % x_dist : the image points got without considering the | ||
9 | % radial distortion. | ||
10 | % x : The image plane points after correction for the distortion | ||
11 | % | ||
12 | % x and x_dist are 2xN arrays | ||
13 | % | ||
14 | % NOTE : This compensation has to be done after the substraction | ||
15 | % of the center of projection, and division by the focal | ||
16 | % length. | ||
17 | % | ||
18 | % (do it up to a second order approximation) | ||
19 | |||
20 | [two,N] = size(x_dist); | ||
21 | |||
22 | if (two ~= 2 ), | ||
23 | error('ERROR : The dimension of the points should be 2xN'); | ||
24 | end; | ||
25 | |||
26 | if length(k2) > 2, | ||
27 | [x_comp] = comp_distortion_oulu(x_dist,k2); | ||
28 | else | ||
29 | |||
30 | radius_2= x_dist(1,:).^2 + x_dist(2,:).^2; | ||
31 | radial_distortion = 1 + ones(2,1)*(k2 * radius_2); | ||
32 | radius_2_comp = (x_dist(1,:).^2 + x_dist(2,:).^2) ./ radial_distortion(1,:); | ||
33 | radial_distortion = 1 + ones(2,1)*(k2 * radius_2_comp); | ||
34 | x_comp = x_dist ./ radial_distortion; | ||
35 | |||
36 | end; | ||
37 | |||
38 | %% Function completely checked : It works fine !!! \ No newline at end of file | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/comp_distortion2.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/comp_distortion2.m new file mode 100755 index 0000000..532ee9a --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/comp_distortion2.m | |||
@@ -0,0 +1,71 @@ | |||
1 | function [x_comp] = comp_distortion(x_dist,k2); | ||
2 | |||
3 | % [x_comp] = comp_distortion(x_dist,k2); | ||
4 | % | ||
5 | % compensates the radial distortion of the camera | ||
6 | % on the image plane. | ||
7 | % | ||
8 | % x_dist : the image points got without considering the | ||
9 | % radial distortion. | ||
10 | % k2: Radial distortion factor | ||
11 | % | ||
12 | % x : The image plane points after correction for the distortion | ||
13 | % | ||
14 | % x and x_dist are 2xN arrays | ||
15 | % | ||
16 | % NOTE : This compensation has to be done after the substraction | ||
17 | % of the center of projection, and division by the focal | ||
18 | % length. | ||
19 | % | ||
20 | % Solve for cubic roots using method from Numerical Recipes in C 2nd Ed. | ||
21 | % pages 184-185. | ||
22 | |||
23 | |||
24 | % California Institute of Technology | ||
25 | % (c) Jean-Yves Bouguet - April 27th, 1998 | ||
26 | |||
27 | % fully checked! JYB, april 27th, 1998 - 2am | ||
28 | |||
29 | if k2 ~= 0, | ||
30 | |||
31 | [two,N] = size(x_dist); | ||
32 | |||
33 | if (two ~= 2 ), | ||
34 | error('ERROR : The dimension of the points should be 2xN'); | ||
35 | end; | ||
36 | |||
37 | |||
38 | ph = atan2(x_dist(2,:),x_dist(1,:)); | ||
39 | |||
40 | Q = -1/(3*k2); | ||
41 | R = -x_dist(1,:)./(2*k2*cos(ph)); | ||
42 | |||
43 | R2 = R.^2; | ||
44 | Q3 = Q^3; | ||
45 | |||
46 | |||
47 | if k2 < 0, | ||
48 | |||
49 | % this works in all practical situations (it starts failing for very large | ||
50 | % values of k2) | ||
51 | |||
52 | th = acos(R./sqrt(Q3)); | ||
53 | r = -2*sqrt(Q)*cos((th-2*pi)/3); | ||
54 | |||
55 | else | ||
56 | |||
57 | % note: this always works, even for ridiculous values of k2 | ||
58 | |||
59 | A = (sqrt(R2-Q3)-R).^(1/3); | ||
60 | B = Q*(1./A); | ||
61 | r = (A+B); | ||
62 | |||
63 | end; | ||
64 | |||
65 | x_comp = [r.*cos(ph); r.*sin(ph)]; | ||
66 | |||
67 | else | ||
68 | |||
69 | x_comp = x_dist; | ||
70 | |||
71 | end; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/comp_distortion_oulu.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/comp_distortion_oulu.m new file mode 100755 index 0000000..67d02d5 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/comp_distortion_oulu.m | |||
@@ -0,0 +1,47 @@ | |||
1 | function [x] = comp_distortion_oulu(xd,k); | ||
2 | |||
3 | %comp_distortion_oulu.m | ||
4 | % | ||
5 | %[x] = comp_distortion_oulu(xd,k) | ||
6 | % | ||
7 | %Compensates for radial and tangential distortion. Model From Oulu university. | ||
8 | %For more informatino about the distortion model, check the forward projection mapping function: | ||
9 | %project_points.m | ||
10 | % | ||
11 | %INPUT: xd: distorted (normalized) point coordinates in the image plane (2xN matrix) | ||
12 | % k: Distortion coefficients (radial and tangential) (4x1 vector) | ||
13 | % | ||
14 | %OUTPUT: x: undistorted (normalized) point coordinates in the image plane (2xN matrix) | ||
15 | % | ||
16 | %Method: Iterative method for compensation. | ||
17 | % | ||
18 | %NOTE: This compensation has to be done after the subtraction | ||
19 | % of the principal point, and division by the focal length. | ||
20 | |||
21 | |||
22 | if length(k) < 4, | ||
23 | |||
24 | [x] = comp_distortion(xd,k); | ||
25 | |||
26 | else | ||
27 | |||
28 | |||
29 | k1 = k(1); | ||
30 | k2 = k(2); | ||
31 | p1 = k(3); | ||
32 | p2 = k(4); | ||
33 | |||
34 | x = xd; % initial guess | ||
35 | |||
36 | for kk=1:5; | ||
37 | |||
38 | r_2 = sum(x.^2); | ||
39 | k_radial = 1 + k1 * r_2 + k2 * r_2.^2; | ||
40 | delta_x = [2*p1*x(1,:).*x(2,:) + p2*(r_2 + 2*x(1,:).^2) ; | ||
41 | p1 * (r_2 + 2*x(2,:).^2)+2*p2*x(1,:).*x(2,:)]; | ||
42 | x = (xd - delta_x)./(ones(2,1)*k_radial); | ||
43 | |||
44 | end; | ||
45 | |||
46 | end; | ||
47 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/comp_error_calib.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/comp_error_calib.m new file mode 100755 index 0000000..c7bf662 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/comp_error_calib.m | |||
@@ -0,0 +1,46 @@ | |||
1 | %%%%%%%%%%%%%%%%%%%% RECOMPUTES THE REPROJECTION ERROR %%%%%%%%%%%%%%%%%%%%%%%% | ||
2 | |||
3 | check_active_images; | ||
4 | |||
5 | % Reproject the patterns on the images, and compute the pixel errors: | ||
6 | |||
7 | ex = []; % Global error vector | ||
8 | x = []; % Detected corners on the image plane | ||
9 | y = []; % Reprojected points | ||
10 | |||
11 | if ~exist('alpha_c'), | ||
12 | alpha_c = 0; | ||
13 | end; | ||
14 | |||
15 | for kk = 1:n_ima, | ||
16 | |||
17 | eval(['omckk = omc_' num2str(kk) ';']); | ||
18 | eval(['Tckk = Tc_' num2str(kk) ';']); | ||
19 | |||
20 | if active_images(kk) & (~isnan(omckk(1,1))), | ||
21 | |||
22 | %Rkk = rodrigues(omckk); | ||
23 | |||
24 | eval(['y_' num2str(kk) ' = project_points2(X_' num2str(kk) ',omckk,Tckk,fc,cc,kc,alpha_c);']); | ||
25 | |||
26 | eval(['ex_' num2str(kk) ' = x_' num2str(kk) ' -y_' num2str(kk) ';']); | ||
27 | |||
28 | eval(['x_kk = x_' num2str(kk) ';']); | ||
29 | |||
30 | eval(['ex = [ex ex_' num2str(kk) '];']); | ||
31 | eval(['x = [x x_' num2str(kk) '];']); | ||
32 | eval(['y = [y y_' num2str(kk) '];']); | ||
33 | |||
34 | else | ||
35 | |||
36 | % eval(['y_' num2str(kk) ' = NaN*ones(2,1);']); | ||
37 | |||
38 | |||
39 | % If inactivated image, the error does not make sense: | ||
40 | eval(['ex_' num2str(kk) ' = NaN*ones(2,1);']); | ||
41 | |||
42 | end; | ||
43 | |||
44 | end; | ||
45 | |||
46 | err_std = std(ex')'; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/compute_collineation.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/compute_collineation.m new file mode 100755 index 0000000..809c309 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/compute_collineation.m | |||
@@ -0,0 +1,66 @@ | |||
1 | function [H,Hnorm,inv_Hnorm] = compute_collineation (a00, a10, a11, a01); | ||
2 | |||
3 | % new formalism using homographies | ||
4 | |||
5 | a00 = a00 / a00(3); | ||
6 | a10 = a10 / a10(3); | ||
7 | a11 = a11 / a11(3); | ||
8 | a01 = a01 / a01(3); | ||
9 | |||
10 | |||
11 | % Prenormalization of point coordinates (very important): | ||
12 | % (Affine normalization) | ||
13 | |||
14 | ax = [a00(1);a10(1);a11(1);a01(1)]; | ||
15 | ay = [a00(2);a10(2);a11(2);a01(2)]; | ||
16 | |||
17 | mxx = mean(ax); | ||
18 | myy = mean(ay); | ||
19 | ax = ax - mxx; | ||
20 | ay = ay - myy; | ||
21 | |||
22 | scxx = mean(abs(ax)); | ||
23 | scyy = mean(abs(ay)); | ||
24 | |||
25 | |||
26 | Hnorm = [1/scxx 0 -mxx/scxx;0 1/scyy -myy/scyy;0 0 1]; | ||
27 | inv_Hnorm = [scxx 0 mxx ; 0 scyy myy; 0 0 1]; | ||
28 | |||
29 | |||
30 | a00n = Hnorm*a00; | ||
31 | a10n = Hnorm*a10; | ||
32 | a11n = Hnorm*a11; | ||
33 | a01n = Hnorm*a01; | ||
34 | |||
35 | |||
36 | % Computation of the vanishing points: | ||
37 | |||
38 | V1n = cross(cross(a00n,a10n),cross(a01n,a11n)); | ||
39 | V2n = cross(cross(a00n,a01n),cross(a10n,a11n)); | ||
40 | |||
41 | V1 = inv_Hnorm*V1n; | ||
42 | V2 = inv_Hnorm*V2n; | ||
43 | |||
44 | |||
45 | % Normalizaion of the vanishing points: | ||
46 | |||
47 | V1n = V1n/norm(V1n); | ||
48 | V2n = V2n/norm(V2n); | ||
49 | |||
50 | |||
51 | % Closed-form solution of the coefficients: | ||
52 | |||
53 | alpha_x = (a10n(2)*a00n(1) - a10n(1)*a00n(2))/(V1n(2)*a10n(1)-V1n(1)*a10n(2)); | ||
54 | |||
55 | alpha_y = (a01n(2)*a00n(1) - a01n(1)*a00n(2))/(V2n(2)*a01n(1)-V2n(1)*a01n(2)); | ||
56 | |||
57 | |||
58 | % Remaining Homography | ||
59 | |||
60 | Hrem = [alpha_x*V1n alpha_y*V2n a00n]; | ||
61 | |||
62 | |||
63 | % Final homography: | ||
64 | |||
65 | H = inv_Hnorm*Hrem; | ||
66 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/compute_extrinsic.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/compute_extrinsic.m new file mode 100755 index 0000000..5217351 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/compute_extrinsic.m | |||
@@ -0,0 +1,123 @@ | |||
1 | function [omckk,Tckk,Rckk,H,x,ex,JJ] = compute_extrinsic(x_kk,X_kk,fc,cc,kc,alpha_c,MaxIter,thresh_cond), | ||
2 | |||
3 | %compute_extrinsic | ||
4 | % | ||
5 | %[omckk,Tckk,Rckk,H,x,ex] = compute_extrinsic(x_kk,X_kk,fc,cc,kc,alpha_c) | ||
6 | % | ||
7 | %Computes the extrinsic parameters attached to a 3D structure X_kk given its projection | ||
8 | %on the image plane x_kk and the intrinsic camera parameters fc, cc and kc. | ||
9 | %Works with planar and non-planar structures. | ||
10 | % | ||
11 | %INPUT: x_kk: Feature locations on the images | ||
12 | % X_kk: Corresponding grid coordinates | ||
13 | % fc: Camera focal length | ||
14 | % cc: Principal point coordinates | ||
15 | % kc: Distortion coefficients | ||
16 | % alpha_c: Skew coefficient | ||
17 | % | ||
18 | %OUTPUT: omckk: 3D rotation vector attached to the grid positions in space | ||
19 | % Tckk: 3D translation vector attached to the grid positions in space | ||
20 | % Rckk: 3D rotation matrices corresponding to the omc vectors | ||
21 | % H: Homography between points on the grid and points on the image plane (in pixel) | ||
22 | % This makes sense only if the planar that is used in planar. | ||
23 | % x: Reprojections of the points on the image plane | ||
24 | % ex: Reprojection error: ex = x_kk - x; | ||
25 | % | ||
26 | %Method: Computes the normalized point coordinates, then computes the 3D pose | ||
27 | % | ||
28 | %Important functions called within that program: | ||
29 | % | ||
30 | %normalize: Computes the normalize image point coordinates. | ||
31 | % | ||
32 | %pose3D: Computes the 3D pose of the structure given the normalized image projection. | ||
33 | % | ||
34 | %project_points.m: Computes the 2D image projections of a set of 3D points | ||
35 | |||
36 | |||
37 | |||
38 | if nargin < 8, | ||
39 | thresh_cond = inf; | ||
40 | end; | ||
41 | |||
42 | |||
43 | if nargin < 7, | ||
44 | MaxIter = 20; | ||
45 | end; | ||
46 | |||
47 | |||
48 | if nargin < 6, | ||
49 | alpha_c = 0; | ||
50 | if nargin < 5, | ||
51 | kc = zeros(4,1); | ||
52 | if nargin < 4, | ||
53 | cc = zeros(2,1); | ||
54 | if nargin < 3, | ||
55 | fc = ones(2,1); | ||
56 | if nargin < 2, | ||
57 | error('Need 2D projections and 3D points (in compute_extrinsic.m)'); | ||
58 | return; | ||
59 | end; | ||
60 | end; | ||
61 | end; | ||
62 | end; | ||
63 | end; | ||
64 | |||
65 | % Initialization: | ||
66 | |||
67 | [omckk,Tckk,Rckk] = compute_extrinsic_init(x_kk,X_kk,fc,cc,kc,alpha_c); | ||
68 | |||
69 | % Refinement: | ||
70 | |||
71 | [omckk,Tckk,Rckk,JJ] = compute_extrinsic_refine(omckk,Tckk,x_kk,X_kk,fc,cc,kc,alpha_c,MaxIter,thresh_cond); | ||
72 | |||
73 | |||
74 | % computation of the homography (not useful in the end) | ||
75 | |||
76 | H = [Rckk(:,1:2) Tckk]; | ||
77 | |||
78 | % Computes the reprojection error in pixels: | ||
79 | |||
80 | x = project_points2(X_kk,omckk,Tckk,fc,cc,kc,alpha_c); | ||
81 | |||
82 | ex = x_kk - x; | ||
83 | |||
84 | |||
85 | % Converts the homography in pixel units: | ||
86 | |||
87 | KK = [fc(1) alpha_c*fc(1) cc(1);0 fc(2) cc(2); 0 0 1]; | ||
88 | |||
89 | H = KK*H; | ||
90 | |||
91 | |||
92 | |||
93 | |||
94 | return; | ||
95 | |||
96 | |||
97 | % Test of compte extrinsic: | ||
98 | |||
99 | Np = 4; | ||
100 | sx = 10; | ||
101 | sy = 10; | ||
102 | sz = 5; | ||
103 | |||
104 | om = randn(3,1); | ||
105 | T = [0;0;100]; | ||
106 | |||
107 | noise = 2/1000; | ||
108 | |||
109 | XX = [sx*randn(1,Np);sy*randn(1,Np);sz*randn(1,Np)]; | ||
110 | xx = project_points(XX,om,T); | ||
111 | |||
112 | xxn = xx + noise * randn(2,Np); | ||
113 | |||
114 | [omckk,Tckk] = compute_extrinsic(xxn,XX); | ||
115 | |||
116 | [om omckk om-omckk] | ||
117 | [T Tckk T-Tckk] | ||
118 | |||
119 | figure(3); | ||
120 | plot(xx(1,:),xx(2,:),'r+'); | ||
121 | hold on; | ||
122 | plot(xxn(1,:),xxn(2,:),'g+'); | ||
123 | hold off; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/compute_extrinsic_init.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/compute_extrinsic_init.m new file mode 100755 index 0000000..2e6d821 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/compute_extrinsic_init.m | |||
@@ -0,0 +1,151 @@ | |||
1 | function [omckk,Tckk,Rckk] = compute_extrinsic_init(x_kk,X_kk,fc,cc,kc,alpha_c), | ||
2 | |||
3 | %compute_extrinsic | ||
4 | % | ||
5 | %[omckk,Tckk,Rckk] = compute_extrinsic_init(x_kk,X_kk,fc,cc,kc,alpha_c) | ||
6 | % | ||
7 | %Computes the extrinsic parameters attached to a 3D structure X_kk given its projection | ||
8 | %on the image plane x_kk and the intrinsic camera parameters fc, cc and kc. | ||
9 | %Works with planar and non-planar structures. | ||
10 | % | ||
11 | %INPUT: x_kk: Feature locations on the images | ||
12 | % X_kk: Corresponding grid coordinates | ||
13 | % fc: Camera focal length | ||
14 | % cc: Principal point coordinates | ||
15 | % kc: Distortion coefficients | ||
16 | % alpha_c: Skew coefficient | ||
17 | % | ||
18 | %OUTPUT: omckk: 3D rotation vector attached to the grid positions in space | ||
19 | % Tckk: 3D translation vector attached to the grid positions in space | ||
20 | % Rckk: 3D rotation matrices corresponding to the omc vectors | ||
21 | % | ||
22 | %Method: Computes the normalized point coordinates, then computes the 3D pose | ||
23 | % | ||
24 | %Important functions called within that program: | ||
25 | % | ||
26 | %normalize: Computes the normalize image point coordinates. | ||
27 | % | ||
28 | %pose3D: Computes the 3D pose of the structure given the normalized image projection. | ||
29 | % | ||
30 | %project_points.m: Computes the 2D image projections of a set of 3D points | ||
31 | |||
32 | |||
33 | |||
34 | if nargin < 6, | ||
35 | alpha_c = 0; | ||
36 | if nargin < 5, | ||
37 | kc = zeros(4,1); | ||
38 | if nargin < 4, | ||
39 | cc = zeros(2,1); | ||
40 | if nargin < 3, | ||
41 | fc = ones(2,1); | ||
42 | if nargin < 2, | ||
43 | error('Need 2D projections and 3D points (in compute_extrinsic.m)'); | ||
44 | return; | ||
45 | end; | ||
46 | end; | ||
47 | end; | ||
48 | end; | ||
49 | end; | ||
50 | |||
51 | |||
52 | % Compute the normalized coordinates: | ||
53 | |||
54 | xn = normalize(x_kk,fc,cc,kc,alpha_c); | ||
55 | |||
56 | |||
57 | |||
58 | Np = size(xn,2); | ||
59 | |||
60 | %% Check for planarity of the structure: | ||
61 | |||
62 | X_mean = mean(X_kk')'; | ||
63 | |||
64 | Y = X_kk - (X_mean*ones(1,Np)); | ||
65 | |||
66 | YY = Y*Y'; | ||
67 | |||
68 | [U,S,V] = svd(YY); | ||
69 | |||
70 | r = S(3,3)/S(2,2); | ||
71 | |||
72 | if (r < 1e-3)|(Np < 6), %1e-3, %1e-4, %norm(X_kk(3,:)) < eps, % Test of planarity | ||
73 | |||
74 | %fprintf(1,'Planar structure detected: r=%f\n',r); | ||
75 | |||
76 | % Transform the plane to bring it in the Z=0 plane: | ||
77 | |||
78 | R_transform = V'; | ||
79 | |||
80 | if det(R_transform) < 0, R_transform = -R_transform; end; | ||
81 | |||
82 | T_transform = -(R_transform)*X_mean; | ||
83 | |||
84 | X_new = R_transform*X_kk + T_transform*ones(1,Np); | ||
85 | |||
86 | |||
87 | % Compute the planar homography: | ||
88 | |||
89 | H = compute_homography (xn,X_new(1:2,:)); | ||
90 | |||
91 | % De-embed the motion parameters from the homography: | ||
92 | |||
93 | sc = mean([norm(H(:,1));norm(H(:,2))]); | ||
94 | |||
95 | H = H/sc; | ||
96 | |||
97 | omckk = rodrigues([H(:,1:2) cross(H(:,1),H(:,2))]); | ||
98 | Rckk = rodrigues(omckk); | ||
99 | Tckk = H(:,3); | ||
100 | |||
101 | %If Xc = Rckk * X_new + Tckk, then Xc = Rckk * R_transform * X_kk + Tckk + T_transform | ||
102 | |||
103 | Tckk = Tckk + Rckk* T_transform; | ||
104 | Rckk = Rckk * R_transform; | ||
105 | |||
106 | omckk = rodrigues(Rckk); | ||
107 | Rckk = rodrigues(omckk); | ||
108 | |||
109 | |||
110 | else | ||
111 | |||
112 | %fprintf(1,'Non planar structure detected: r=%f\n',r); | ||
113 | |||
114 | % Computes an initial guess for extrinsic parameters (works for general 3d structure, not planar!!!): | ||
115 | % The DLT method is applied here!! | ||
116 | |||
117 | J = zeros(2*Np,12); | ||
118 | |||
119 | xX = (ones(3,1)*xn(1,:)).*X_kk; | ||
120 | yX = (ones(3,1)*xn(2,:)).*X_kk; | ||
121 | |||
122 | J(1:2:end,[1 4 7]) = -X_kk'; | ||
123 | J(2:2:end,[2 5 8]) = X_kk'; | ||
124 | J(1:2:end,[3 6 9]) = xX'; | ||
125 | J(2:2:end,[3 6 9]) = -yX'; | ||
126 | J(1:2:end,12) = xn(1,:)'; | ||
127 | J(2:2:end,12) = -xn(2,:)'; | ||
128 | J(1:2:end,10) = -ones(Np,1); | ||
129 | J(2:2:end,11) = ones(Np,1); | ||
130 | |||
131 | JJ = J'*J; | ||
132 | [U,S,V] = svd(JJ); | ||
133 | |||
134 | RR = reshape(V(1:9,12),3,3); | ||
135 | |||
136 | if det(RR) < 0, | ||
137 | V(:,12) = -V(:,12); | ||
138 | RR = -RR; | ||
139 | end; | ||
140 | |||
141 | [Ur,Sr,Vr] = svd(RR); | ||
142 | |||
143 | Rckk = Ur*Vr'; | ||
144 | |||
145 | sc = norm(V(1:9,12)) / norm(Rckk(:)); | ||
146 | Tckk = V(10:12,12)/sc; | ||
147 | |||
148 | omckk = rodrigues(Rckk); | ||
149 | Rckk = rodrigues(omckk); | ||
150 | |||
151 | end; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/compute_extrinsic_refine.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/compute_extrinsic_refine.m new file mode 100755 index 0000000..a4d066c --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/compute_extrinsic_refine.m | |||
@@ -0,0 +1,113 @@ | |||
1 | function [omckk,Tckk,Rckk,JJ] = compute_extrinsic_refine(omc_init,Tc_init,x_kk,X_kk,fc,cc,kc,alpha_c,MaxIter,thresh_cond), | ||
2 | |||
3 | %compute_extrinsic | ||
4 | % | ||
5 | %[omckk,Tckk,Rckk] = compute_extrinsic_refine(x_kk,X_kk,fc,cc,kc,alpha_c,MaxIter) | ||
6 | % | ||
7 | %Computes the extrinsic parameters attached to a 3D structure X_kk given its projection | ||
8 | %on the image plane x_kk and the intrinsic camera parameters fc, cc and kc. | ||
9 | %Works with planar and non-planar structures. | ||
10 | % | ||
11 | %INPUT: x_kk: Feature locations on the images | ||
12 | % X_kk: Corresponding grid coordinates | ||
13 | % fc: Camera focal length | ||
14 | % cc: Principal point coordinates | ||
15 | % kc: Distortion coefficients | ||
16 | % alpha_c: Skew coefficient | ||
17 | % MaxIter: Maximum number of iterations | ||
18 | % | ||
19 | %OUTPUT: omckk: 3D rotation vector attached to the grid positions in space | ||
20 | % Tckk: 3D translation vector attached to the grid positions in space | ||
21 | % Rckk: 3D rotation matrices corresponding to the omc vectors | ||
22 | |||
23 | % | ||
24 | %Method: Computes the normalized point coordinates, then computes the 3D pose | ||
25 | % | ||
26 | %Important functions called within that program: | ||
27 | % | ||
28 | %normalize: Computes the normalize image point coordinates. | ||
29 | % | ||
30 | %pose3D: Computes the 3D pose of the structure given the normalized image projection. | ||
31 | % | ||
32 | %project_points.m: Computes the 2D image projections of a set of 3D points | ||
33 | |||
34 | |||
35 | if nargin < 10, | ||
36 | thresh_cond = inf; | ||
37 | end; | ||
38 | |||
39 | |||
40 | if nargin < 9, | ||
41 | MaxIter = 20; | ||
42 | end; | ||
43 | |||
44 | if nargin < 8, | ||
45 | alpha_c = 0; | ||
46 | if nargin < 7, | ||
47 | kc = zeros(4,1); | ||
48 | if nargin < 6, | ||
49 | cc = zeros(2,1); | ||
50 | if nargin < 5, | ||
51 | fc = ones(2,1); | ||
52 | if nargin < 4, | ||
53 | error('Need 2D projections and 3D points (in compute_extrinsic_refine.m)'); | ||
54 | return; | ||
55 | end; | ||
56 | end; | ||
57 | end; | ||
58 | end; | ||
59 | end; | ||
60 | |||
61 | |||
62 | % Initialization: | ||
63 | |||
64 | omckk = omc_init; | ||
65 | Tckk = Tc_init; | ||
66 | |||
67 | |||
68 | % Final optimization (minimize the reprojection error in pixel): | ||
69 | % through Gradient Descent: | ||
70 | |||
71 | param = [omckk;Tckk]; | ||
72 | |||
73 | change = 1; | ||
74 | |||
75 | iter = 0; | ||
76 | |||
77 | %keyboard; | ||
78 | |||
79 | %fprintf(1,'Gradient descent iterations: '); | ||
80 | |||
81 | while (change > 1e-10)&(iter < MaxIter), | ||
82 | |||
83 | %fprintf(1,'%d...',iter+1); | ||
84 | |||
85 | [x,dxdom,dxdT] = project_points2(X_kk,omckk,Tckk,fc,cc,kc,alpha_c); | ||
86 | |||
87 | ex = x_kk - x; | ||
88 | |||
89 | %keyboard; | ||
90 | |||
91 | JJ = [dxdom dxdT]; | ||
92 | |||
93 | if cond(JJ) > thresh_cond, | ||
94 | change = 0; | ||
95 | else | ||
96 | |||
97 | JJ2 = JJ'*JJ; | ||
98 | |||
99 | param_innov = inv(JJ2)*(JJ')*ex(:); | ||
100 | param_up = param + param_innov; | ||
101 | change = norm(param_innov)/norm(param_up); | ||
102 | param = param_up; | ||
103 | iter = iter + 1; | ||
104 | |||
105 | omckk = param(1:3); | ||
106 | Tckk = param(4:6); | ||
107 | end; | ||
108 | |||
109 | end; | ||
110 | |||
111 | %fprintf(1,'\n'); | ||
112 | |||
113 | Rckk = rodrigues(omckk); | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/compute_homography.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/compute_homography.m new file mode 100755 index 0000000..fcc9003 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/compute_homography.m | |||
@@ -0,0 +1,163 @@ | |||
1 | function [H,Hnorm,inv_Hnorm] = compute_homography (m,M); | ||
2 | |||
3 | %compute_homography | ||
4 | % | ||
5 | %[H,Hnorm,inv_Hnorm] = compute_homography (m,M) | ||
6 | % | ||
7 | %Computes the planar homography between the point coordinates on the plane (M) and the image | ||
8 | %point coordinates (m). | ||
9 | % | ||
10 | %INPUT: m: homogeneous coordinates in the image plane (3xN matrix) | ||
11 | % M: homogeneous coordinates in the plane in 3D (3xN matrix) | ||
12 | % | ||
13 | %OUTPUT: H: Homography matrix (3x3 homogeneous matrix) | ||
14 | % Hnorm: Normlization matrix used on the points before homography computation | ||
15 | % (useful for numerical stability is points in pixel coordinates) | ||
16 | % inv_Hnorm: The inverse of Hnorm | ||
17 | % | ||
18 | %Definition: m ~ H*M where "~" means equal up to a non zero scalar factor. | ||
19 | % | ||
20 | %Method: First computes an initial guess for the homography through quasi-linear method. | ||
21 | % Then, if the total number of points is larger than 4, optimize the solution by minimizing | ||
22 | % the reprojection error (in the least squares sense). | ||
23 | % | ||
24 | % | ||
25 | %Important functions called within that program: | ||
26 | % | ||
27 | %comp_distortion_oulu: Undistorts pixel coordinates. | ||
28 | % | ||
29 | %compute_homography.m: Computes the planar homography between points on the grid in 3D, and the image plane. | ||
30 | % | ||
31 | %project_points.m: Computes the 2D image projections of a set of 3D points, and also returns te Jacobian | ||
32 | % matrix (derivative with respect to the intrinsic and extrinsic parameters). | ||
33 | % This function is called within the minimization loop. | ||
34 | |||
35 | |||
36 | |||
37 | |||
38 | Np = size(m,2); | ||
39 | |||
40 | if size(m,1)<3, | ||
41 | m = [m;ones(1,Np)]; | ||
42 | end; | ||
43 | |||
44 | if size(M,1)<3, | ||
45 | M = [M;ones(1,Np)]; | ||
46 | end; | ||
47 | |||
48 | |||
49 | m = m ./ (ones(3,1)*m(3,:)); | ||
50 | M = M ./ (ones(3,1)*M(3,:)); | ||
51 | |||
52 | % Prenormalization of point coordinates (very important): | ||
53 | % (Affine normalization) | ||
54 | |||
55 | ax = m(1,:); | ||
56 | ay = m(2,:); | ||
57 | |||
58 | mxx = mean(ax); | ||
59 | myy = mean(ay); | ||
60 | ax = ax - mxx; | ||
61 | ay = ay - myy; | ||
62 | |||
63 | scxx = mean(abs(ax)); | ||
64 | scyy = mean(abs(ay)); | ||
65 | |||
66 | |||
67 | Hnorm = [1/scxx 0 -mxx/scxx;0 1/scyy -myy/scyy;0 0 1]; | ||
68 | inv_Hnorm = [scxx 0 mxx ; 0 scyy myy; 0 0 1]; | ||
69 | |||
70 | mn = Hnorm*m; | ||
71 | |||
72 | % Compute the homography between m and mn: | ||
73 | |||
74 | % Build the matrix: | ||
75 | |||
76 | L = zeros(2*Np,9); | ||
77 | |||
78 | L(1:2:2*Np,1:3) = M'; | ||
79 | L(2:2:2*Np,4:6) = M'; | ||
80 | L(1:2:2*Np,7:9) = -((ones(3,1)*mn(1,:)).* M)'; | ||
81 | L(2:2:2*Np,7:9) = -((ones(3,1)*mn(2,:)).* M)'; | ||
82 | |||
83 | if Np > 4, | ||
84 | L = L'*L; | ||
85 | end; | ||
86 | |||
87 | [U,S,V] = svd(L); | ||
88 | |||
89 | hh = V(:,9); | ||
90 | hh = hh/hh(9); | ||
91 | |||
92 | Hrem = reshape(hh,3,3)'; | ||
93 | %Hrem = Hrem / Hrem(3,3); | ||
94 | |||
95 | % Final homography: | ||
96 | |||
97 | H = inv_Hnorm*Hrem; | ||
98 | |||
99 | |||
100 | %%% Homography refinement if there are more than 4 points: | ||
101 | |||
102 | if Np > 4, | ||
103 | |||
104 | % Final refinement: | ||
105 | |||
106 | hhv = reshape(H',9,1); | ||
107 | hhv = hhv(1:8); | ||
108 | |||
109 | for iter=1:10, | ||
110 | |||
111 | mrep = H * M; | ||
112 | |||
113 | J = zeros(2*Np,8); | ||
114 | |||
115 | MMM = (M ./ (ones(3,1)*mrep(3,:))); | ||
116 | |||
117 | J(1:2:2*Np,1:3) = -MMM'; | ||
118 | J(2:2:2*Np,4:6) = -MMM'; | ||
119 | |||
120 | mrep = mrep ./ (ones(3,1)*mrep(3,:)); | ||
121 | |||
122 | m_err = m(1:2,:) - mrep(1:2,:); | ||
123 | m_err = m_err(:); | ||
124 | |||
125 | MMM2 = (ones(3,1)*mrep(1,:)) .* MMM; | ||
126 | MMM3 = (ones(3,1)*mrep(2,:)) .* MMM; | ||
127 | |||
128 | J(1:2:2*Np,7:8) = MMM2(1:2,:)'; | ||
129 | J(2:2:2*Np,7:8) = MMM3(1:2,:)'; | ||
130 | |||
131 | MMM = (M ./ (ones(3,1)*mrep(3,:)))'; | ||
132 | |||
133 | hh_innov = inv(J'*J)*J'*m_err; | ||
134 | |||
135 | hhv_up = hhv - hh_innov; | ||
136 | |||
137 | H_up = reshape([hhv_up;1],3,3)'; | ||
138 | |||
139 | %norm(m_err) | ||
140 | %norm(hh_innov) | ||
141 | |||
142 | hhv = hhv_up; | ||
143 | H = H_up; | ||
144 | |||
145 | end; | ||
146 | |||
147 | end; | ||
148 | |||
149 | |||
150 | |||
151 | |||
152 | |||
153 | return; | ||
154 | |||
155 | %test of Jacobian | ||
156 | |||
157 | mrep = H*M; | ||
158 | mrep = mrep ./ (ones(3,1)*mrep(3,:)); | ||
159 | |||
160 | m_err = mrep(1:2,:) - m(1:2,:); | ||
161 | figure(8); | ||
162 | plot(m_err(1,:),m_err(2,:),'r+'); | ||
163 | std(m_err') | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/cornerfinder.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/cornerfinder.m new file mode 100755 index 0000000..9bfa51f --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/cornerfinder.m | |||
@@ -0,0 +1,215 @@ | |||
1 | function [xc,good,bad,type] = cornerfinder(xt,I,wintx,winty,wx2,wy2); | ||
2 | |||
3 | %[xc] = cornerfinder(xt,I); | ||
4 | % | ||
5 | %Finds the sub-pixel corners on the image I with initial guess xt | ||
6 | %xt and xc are 2xN matrices. The first component is the x coordinate | ||
7 | %(horizontal) and the second component is the y coordinate (vertical) | ||
8 | % | ||
9 | %Based on Harris corner finder method | ||
10 | % | ||
11 | %Finds corners to a precision below .1 pixel! | ||
12 | %Oct. 14th, 1997 - UPDATED to work with vertical and horizontal edges as well!!! | ||
13 | %Sept 1998 - UPDATED to handle diverged points: we keep the original points | ||
14 | %good is a binary vector indicating wether a feature point has been properly | ||
15 | %found. | ||
16 | % | ||
17 | %Add a zero zone of size wx2,wy2 | ||
18 | %July 15th, 1999 - Bug on the mask building... fixed + change to Gaussian mask with higher | ||
19 | %resolution and larger number of iterations. | ||
20 | |||
21 | |||
22 | % California Institute of Technology | ||
23 | % (c) Jean-Yves Bouguet -- Oct. 14th, 1997 | ||
24 | |||
25 | |||
26 | |||
27 | line_feat = 1; % set to 1 to allow for extraction of line features. | ||
28 | |||
29 | xt = xt'; | ||
30 | xt = fliplr(xt); | ||
31 | |||
32 | |||
33 | if nargin < 4, | ||
34 | winty = 5; | ||
35 | if nargin < 3, | ||
36 | wintx = 5; | ||
37 | end; | ||
38 | end; | ||
39 | |||
40 | |||
41 | if nargin < 6, | ||
42 | wx2 = -1; | ||
43 | wy2 = -1; | ||
44 | end; | ||
45 | |||
46 | |||
47 | %mask = ones(2*wintx+1,2*winty+1); | ||
48 | mask = exp(-((-wintx:wintx)'/(wintx)).^2) * exp(-((-winty:winty)/(winty)).^2); | ||
49 | |||
50 | |||
51 | if (wx2>0) & (wy2>0), | ||
52 | if ((wintx - wx2)>=2)&((winty - wy2)>=2), | ||
53 | mask(wintx+1-wx2:wintx+1+wx2,winty+1-wy2:winty+1+wy2)= zeros(2*wx2+1,2*wy2+1); | ||
54 | end; | ||
55 | end; | ||
56 | |||
57 | offx = [-wintx:wintx]'*ones(1,2*winty+1); | ||
58 | offy = ones(2*wintx+1,1)*[-winty:winty]; | ||
59 | |||
60 | resolution = 0.005; | ||
61 | |||
62 | MaxIter = 10; | ||
63 | |||
64 | [nx,ny] = size(I); | ||
65 | N = size(xt,1); | ||
66 | |||
67 | xc = xt; % first guess... they don't move !!! | ||
68 | |||
69 | type = zeros(1,N); | ||
70 | |||
71 | |||
72 | for i=1:N, | ||
73 | |||
74 | v_extra = resolution + 1; % just larger than resolution | ||
75 | |||
76 | compt = 0; % no iteration yet | ||
77 | |||
78 | while (norm(v_extra) > resolution) & (compt<MaxIter), | ||
79 | |||
80 | cIx = xc(i,1); % | ||
81 | cIy = xc(i,2); % Coords. of the point | ||
82 | crIx = round(cIx); % on the initial image | ||
83 | crIy = round(cIy); % | ||
84 | itIx = cIx - crIx; % Coefficients | ||
85 | itIy = cIy - crIy; % to compute | ||
86 | if itIx > 0, % the sub pixel | ||
87 | vIx = [itIx 1-itIx 0]'; % accuracy. | ||
88 | else | ||
89 | vIx = [0 1+itIx -itIx]'; | ||
90 | end; | ||
91 | if itIy > 0, | ||
92 | vIy = [itIy 1-itIy 0]; | ||
93 | else | ||
94 | vIy = [0 1+itIy -itIy]; | ||
95 | end; | ||
96 | |||
97 | |||
98 | % What if the sub image is not in? | ||
99 | |||
100 | if (crIx-wintx-2 < 1), xmin=1; xmax = 2*wintx+5; | ||
101 | elseif (crIx+wintx+2 > nx), xmax = nx; xmin = nx-2*wintx-4; | ||
102 | else | ||
103 | xmin = crIx-wintx-2; xmax = crIx+wintx+2; | ||
104 | end; | ||
105 | |||
106 | if (crIy-winty-2 < 1), ymin=1; ymax = 2*winty+5; | ||
107 | elseif (crIy+winty+2 > ny), ymax = ny; ymin = ny-2*winty-4; | ||
108 | else | ||
109 | ymin = crIy-winty-2; ymax = crIy+winty+2; | ||
110 | end; | ||
111 | |||
112 | |||
113 | SI = I(xmin:xmax,ymin:ymax); % The necessary neighborhood | ||
114 | SI = conv2(conv2(SI,vIx,'same'),vIy,'same'); | ||
115 | SI = SI(2:2*wintx+4,2:2*winty+4); % The subpixel interpolated neighborhood | ||
116 | [gy,gx] = gradient(SI); % The gradient image | ||
117 | gx = gx(2:2*wintx+2,2:2*winty+2); % extraction of the useful parts only | ||
118 | gy = gy(2:2*wintx+2,2:2*winty+2); % of the gradients | ||
119 | |||
120 | px = cIx + offx; | ||
121 | py = cIy + offy; | ||
122 | |||
123 | gxx = gx .* gx .* mask; | ||
124 | gyy = gy .* gy .* mask; | ||
125 | gxy = gx .* gy .* mask; | ||
126 | |||
127 | |||
128 | bb = [sum(sum(gxx .* px + gxy .* py)); sum(sum(gxy .* px + gyy .* py))]; | ||
129 | |||
130 | a = sum(sum(gxx)); | ||
131 | b = sum(sum(gxy)); | ||
132 | c = sum(sum(gyy)); | ||
133 | |||
134 | dt = a*c - b^2; | ||
135 | |||
136 | xc2 = [c*bb(1)-b*bb(2) a*bb(2)-b*bb(1)]/dt; | ||
137 | |||
138 | |||
139 | %keyboard; | ||
140 | |||
141 | if line_feat, | ||
142 | |||
143 | G = [a b;b c]; | ||
144 | [U,S,V] = svd(G); | ||
145 | |||
146 | %keyboard; | ||
147 | |||
148 | % If non-invertible, then project the point onto the edge orthogonal: | ||
149 | |||
150 | if (S(1,1)/S(2,2) > 50), | ||
151 | % projection operation: | ||
152 | xc2 = xc2 + sum((xc(i,:)-xc2).*(V(:,2)'))*V(:,2)'; | ||
153 | type(i) = 1; | ||
154 | end; | ||
155 | |||
156 | end; | ||
157 | |||
158 | |||
159 | %keyboard; | ||
160 | |||
161 | % G = [a b;b c]; | ||
162 | % [U,S,V] = svd(G); | ||
163 | |||
164 | |||
165 | % if S(1,1)/S(2,2) > 150, | ||
166 | % bb2 = U'*bb; | ||
167 | % xc2 = (V*[bb2(1)/S(1,1) ;0])'; | ||
168 | % else | ||
169 | % xc2 = [c*bb(1)-b*bb(2) a*bb(2)-b*bb(1)]/dt; | ||
170 | % end; | ||
171 | |||
172 | |||
173 | %if (abs(a)> 50*abs(c)), | ||
174 | % xc2 = [(c*bb(1)-b*bb(2))/dt xc(i,2)]; | ||
175 | % elseif (abs(c)> 50*abs(a)) | ||
176 | % xc2 = [xc(i,1) (a*bb(2)-b*bb(1))/dt]; | ||
177 | % else | ||
178 | % xc2 = [c*bb(1)-b*bb(2) a*bb(2)-b*bb(1)]/dt; | ||
179 | % end; | ||
180 | |||
181 | %keyboard; | ||
182 | |||
183 | v_extra = xc(i,:) - xc2; | ||
184 | |||
185 | xc(i,:) = xc2; | ||
186 | |||
187 | % keyboard; | ||
188 | |||
189 | compt = compt + 1; | ||
190 | |||
191 | end | ||
192 | end; | ||
193 | |||
194 | |||
195 | % check for points that diverge: | ||
196 | |||
197 | delta_x = xc(:,1) - xt(:,1); | ||
198 | delta_y = xc(:,2) - xt(:,2); | ||
199 | |||
200 | %keyboard; | ||
201 | |||
202 | |||
203 | bad = (abs(delta_x) > wintx) | (abs(delta_y) > winty); | ||
204 | good = ~bad; | ||
205 | in_bad = find(bad); | ||
206 | |||
207 | % For the diverged points, keep the original guesses: | ||
208 | |||
209 | xc(in_bad,:) = xt(in_bad,:); | ||
210 | |||
211 | xc = fliplr(xc); | ||
212 | xc = xc'; | ||
213 | |||
214 | bad = bad'; | ||
215 | good = good'; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/count_squares.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/count_squares.m new file mode 100755 index 0000000..0e226c0 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/count_squares.m | |||
@@ -0,0 +1,74 @@ | |||
1 | function ns = count_squares(I,x1,y1,x2,y2,win); | ||
2 | |||
3 | %keyboard; | ||
4 | |||
5 | [ny,nx] = size(I); | ||
6 | |||
7 | lambda = [y1 - y2;x2 - x1;x1*y2 - x2*y1]; | ||
8 | |||
9 | lambda = 1/sqrt(lambda(1)^2 + lambda(2)^2) * lambda; | ||
10 | |||
11 | l1 = lambda + [0;0;win]; | ||
12 | l2 = lambda - [0;0;win]; | ||
13 | |||
14 | |||
15 | dx = x2-x1; | ||
16 | dy = y2 - y1; | ||
17 | |||
18 | |||
19 | if abs(dx) > abs(dy), | ||
20 | |||
21 | if x2 > x1, | ||
22 | xs = x1:x2; | ||
23 | else | ||
24 | xs = x1:-1:x2; | ||
25 | end; | ||
26 | |||
27 | ys = -(lambda(3) + lambda(1)*xs)/lambda(2); | ||
28 | |||
29 | else | ||
30 | |||
31 | if y2 > y1, | ||
32 | ys = y1:y2; | ||
33 | else | ||
34 | ys = y1:-1:y2; | ||
35 | end; | ||
36 | xs = -(lambda(3) + lambda(2)*ys)/lambda(1); | ||
37 | |||
38 | end; | ||
39 | |||
40 | |||
41 | |||
42 | Np = length(xs); | ||
43 | |||
44 | xs_mat = ones(2*win + 1,1)*xs; | ||
45 | ys_mat = ones(2*win + 1,1)*ys; | ||
46 | |||
47 | win_mat = (-win:win)'*ones(1,Np); | ||
48 | |||
49 | |||
50 | xs_mat2 = round(xs_mat - win_mat * lambda(1)); | ||
51 | ys_mat2 = round(ys_mat - win_mat * lambda(2)); | ||
52 | |||
53 | ind_mat = (xs_mat2 - 1) * ny + ys_mat2; | ||
54 | |||
55 | ima_patch = zeros(2*win + 1,Np); | ||
56 | |||
57 | ima_patch(:) = I(ind_mat(:)); | ||
58 | |||
59 | %ima2 = ima_patch(:,win+1:end-win); | ||
60 | |||
61 | filtk = [ones(win,Np);zeros(1,Np);-ones(win,Np)]; | ||
62 | |||
63 | out_f = sum(filtk.*ima_patch); | ||
64 | |||
65 | out_f_f = conv2(out_f,[1/4 1/2 1/4],'same'); | ||
66 | |||
67 | out_f_f = out_f_f(win+1:end-win); | ||
68 | |||
69 | ns = length(find(((out_f_f(2:end)>=0)&(out_f_f(1:end-1)<0)) | ((out_f_f(2:end)<=0)&(out_f_f(1:end-1)>0))))+1; | ||
70 | |||
71 | |||
72 | |||
73 | |||
74 | return; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/data_calib.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/data_calib.m new file mode 100755 index 0000000..422769b --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/data_calib.m | |||
@@ -0,0 +1,92 @@ | |||
1 | %%% This script alets the user enter the name of the images (base name, numbering scheme,... | ||
2 | |||
3 | |||
4 | % Checks that there are some images in the directory: | ||
5 | |||
6 | l_ras = dir('*ras'); | ||
7 | s_ras = size(l_ras,1); | ||
8 | l_bmp = dir('*bmp'); | ||
9 | s_bmp = size(l_bmp,1); | ||
10 | l_tif = dir('*tif'); | ||
11 | s_tif = size(l_tif,1); | ||
12 | l_pgm = dir('*pgm'); | ||
13 | s_pgm = size(l_pgm,1); | ||
14 | l_jpg = dir('*jpg'); | ||
15 | s_jpg = size(l_jpg,1); | ||
16 | |||
17 | s_tot = s_ras + s_bmp + s_tif + s_pgm + s_jpg; | ||
18 | |||
19 | if s_tot < 1, | ||
20 | fprintf(1,'No image in this directory in either ras, bmp, tif, pgm or jpg format. Change directory and try again.\n'); | ||
21 | break; | ||
22 | end; | ||
23 | |||
24 | |||
25 | % IF yes, display the directory content: | ||
26 | |||
27 | dir; | ||
28 | |||
29 | Nima_valid = 0; | ||
30 | |||
31 | while (Nima_valid==0), | ||
32 | |||
33 | fprintf(1,'\n'); | ||
34 | calib_name = input('Basename camera calibration images (without number nor suffix): ','s'); | ||
35 | |||
36 | format_image = '0'; | ||
37 | |||
38 | while format_image == '0', | ||
39 | |||
40 | format_image = input('Image format: ([]=''r''=''ras'', ''b''=''bmp'', ''t''=''tif'', ''p''=''pgm'', ''j''=''jpg'', ''m''=''ppm'') ','s'); | ||
41 | |||
42 | if isempty(format_image), | ||
43 | format_image = 'ras'; | ||
44 | end; | ||
45 | |||
46 | if lower(format_image(1)) == 'm', | ||
47 | format_image = 'ppm'; | ||
48 | else | ||
49 | if lower(format_image(1)) == 'b', | ||
50 | format_image = 'bmp'; | ||
51 | else | ||
52 | if lower(format_image(1)) == 't', | ||
53 | format_image = 'tif'; | ||
54 | else | ||
55 | if lower(format_image(1)) == 'p', | ||
56 | format_image = 'pgm'; | ||
57 | else | ||
58 | if lower(format_image(1)) == 'j', | ||
59 | format_image = 'jpg'; | ||
60 | else | ||
61 | if lower(format_image(1)) == 'r', | ||
62 | format_image = 'ras'; | ||
63 | else | ||
64 | disp('Invalid image format'); | ||
65 | format_image = '0'; % Ask for format once again | ||
66 | end; | ||
67 | end; | ||
68 | end; | ||
69 | end; | ||
70 | end; | ||
71 | end; | ||
72 | end; | ||
73 | |||
74 | |||
75 | check_directory; | ||
76 | |||
77 | end; | ||
78 | |||
79 | |||
80 | |||
81 | %string_save = 'save calib_data n_ima type_numbering N_slots image_numbers format_image calib_name first_num'; | ||
82 | |||
83 | %eval(string_save); | ||
84 | |||
85 | |||
86 | |||
87 | if (Nima_valid~=0), | ||
88 | % Reading images: | ||
89 | |||
90 | ima_read_calib; % may be launched from the toolbox itself | ||
91 | end; | ||
92 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/error_analysis.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/error_analysis.m new file mode 100755 index 0000000..85feac5 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/error_analysis.m | |||
@@ -0,0 +1,182 @@ | |||
1 | %%% ERROR_ANALYSIS | ||
2 | %%% This simulation helps coputing the acturacies of calibration | ||
3 | %%% Run it after the main calibration | ||
4 | |||
5 | |||
6 | |||
7 | N_runs = 200; | ||
8 | |||
9 | %N_ima_active = 4; | ||
10 | |||
11 | saving = 1; | ||
12 | |||
13 | if 1, %~exist('fc_list'), % initialization | ||
14 | |||
15 | % Initialization: | ||
16 | |||
17 | load Calib_Results; | ||
18 | check_active_images; | ||
19 | |||
20 | fc_list = []; | ||
21 | cc_list = []; | ||
22 | kc_list = []; | ||
23 | active_images_list = []; | ||
24 | |||
25 | |||
26 | for kk=1:n_ima, | ||
27 | |||
28 | eval(['omc_list_' num2str(kk) ' = [];']); | ||
29 | eval(['Tc_list_' num2str(kk) ' = [];']); | ||
30 | |||
31 | end; | ||
32 | |||
33 | %sx = median(abs(ex(1,:)))*1.4836; | ||
34 | %sy = median(abs(ex(2,:)))*1.4836; | ||
35 | |||
36 | sx = std(ex(1,:)); | ||
37 | sy = std(ex(2,:)); | ||
38 | |||
39 | % Saving the feature locations: | ||
40 | |||
41 | for kk = 1:n_ima, | ||
42 | |||
43 | eval(['x_save_' num2str(kk) ' = x_' num2str(kk) ';']); | ||
44 | eval(['y_save_' num2str(kk) ' = y_' num2str(kk) ';']); | ||
45 | |||
46 | end; | ||
47 | |||
48 | active_images_save = active_images; | ||
49 | ind_active_save = ind_active; | ||
50 | |||
51 | fc_save = fc; | ||
52 | cc_save = cc; | ||
53 | kc_save = kc; | ||
54 | KK_save = KK; | ||
55 | |||
56 | |||
57 | end; | ||
58 | |||
59 | |||
60 | |||
61 | |||
62 | %%% The main loop: | ||
63 | |||
64 | |||
65 | for ntrial = 1:N_runs, | ||
66 | |||
67 | fprintf(1,'\nRun number: %d\n',ntrial); | ||
68 | fprintf(1, '----------\n'); | ||
69 | |||
70 | for kk = 1:n_ima, | ||
71 | |||
72 | eval(['y_kk = y_save_' num2str(kk) ';']) | ||
73 | |||
74 | if active_images(kk) & ~isnan(y_kk(1,1)), | ||
75 | |||
76 | Nkk = size(y_kk,2); | ||
77 | |||
78 | x_kk_new = y_kk + [sx * randn(1,Nkk);sy*randn(1,Nkk)]; | ||
79 | |||
80 | eval(['x_' num2str(kk) ' = x_kk_new;']); | ||
81 | |||
82 | end; | ||
83 | |||
84 | end; | ||
85 | |||
86 | N_active = length(ind_active_save); | ||
87 | junk = randn(1,N_active); | ||
88 | [junk,junk2] = sort(junk); | ||
89 | |||
90 | active_images = zeros(1,n_ima); | ||
91 | active_images(ind_active_save(junk2(1:N_ima_active))) = ones(1,N_ima_active); | ||
92 | |||
93 | fc = fc_save; | ||
94 | cc = cc_save; | ||
95 | kc = kc_save; | ||
96 | KK = KK_save; | ||
97 | |||
98 | go_calib_optim; | ||
99 | |||
100 | fc_list = [fc_list fc]; | ||
101 | cc_list = [cc_list cc]; | ||
102 | kc_list = [kc_list kc]; | ||
103 | active_images_list = [active_images_list active_images']; | ||
104 | |||
105 | for kk=1:n_ima, | ||
106 | |||
107 | eval(['omc_list_' num2str(kk) ' = [ omc_list_' num2str(kk) ' omc_' num2str(kk) ' ];']); | ||
108 | eval(['Tc_list_' num2str(kk) ' = [ Tc_list_' num2str(kk) ' Tc_' num2str(kk) ' ];']); | ||
109 | |||
110 | end; | ||
111 | |||
112 | end; | ||
113 | |||
114 | |||
115 | |||
116 | |||
117 | if 0, | ||
118 | |||
119 | % Restoring the feature locations: | ||
120 | |||
121 | for kk = 1:n_ima, | ||
122 | |||
123 | eval(['x_' num2str(kk) ' = x_save_' num2str(kk) ';']); | ||
124 | |||
125 | end; | ||
126 | |||
127 | fprintf(1,'\nFinal run (with the real data)\n'); | ||
128 | fprintf(1, '------------------------------\n'); | ||
129 | |||
130 | active_images = active_images_save; | ||
131 | ind_active = ind_active_save; | ||
132 | |||
133 | go_calib_optim; | ||
134 | |||
135 | fc_list = [fc_list fc]; | ||
136 | cc_list = [cc_list cc]; | ||
137 | kc_list = [kc_list kc]; | ||
138 | active_images_list = [active_images_list active_images']; | ||
139 | |||
140 | for kk=1:n_ima, | ||
141 | |||
142 | eval(['omc_list_' num2str(kk) ' = [ omc_list_' num2str(kk) ' omc_' num2str(kk) ' ];']); | ||
143 | eval(['Tc_list_' num2str(kk) ' = [ Tc_list_' num2str(kk) ' Tc_' num2str(kk) ' ];']); | ||
144 | |||
145 | end; | ||
146 | |||
147 | end; | ||
148 | |||
149 | |||
150 | |||
151 | |||
152 | |||
153 | if saving, | ||
154 | |||
155 | disp(['Save Calibration accuracy results under Calib_Accuracies_' num2str(N_ima_active) '.mat']); | ||
156 | |||
157 | string_save = ['save Calib_Accuracies_' num2str(N_ima_active) ' active_images n_ima N_ima_active N_runs active_images_list fc cc kc fc_list cc_list kc_list']; | ||
158 | |||
159 | for kk = 1:n_ima, | ||
160 | string_save = [string_save ' Tc_list_' num2str(kk) ' omc_list_' num2str(kk) ' Tc_' num2str(kk) ' omc_' num2str(kk) ]; | ||
161 | end; | ||
162 | |||
163 | eval(string_save); | ||
164 | |||
165 | end; | ||
166 | |||
167 | |||
168 | return; | ||
169 | |||
170 | std(fc_list') | ||
171 | |||
172 | std(cc_list') | ||
173 | |||
174 | std(kc_list') | ||
175 | |||
176 | for kk = 1:n_ima, | ||
177 | |||
178 | eval(['std(Tc_list_' num2str(kk) ''')']) | ||
179 | |||
180 | end; | ||
181 | |||
182 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/export_calib_data.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/export_calib_data.m new file mode 100755 index 0000000..39506a8 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/export_calib_data.m | |||
@@ -0,0 +1,99 @@ | |||
1 | %% Export calibration data (corners + 3D coordinates) to | ||
2 | %% text files (in Willson-Heikkila's format or Zhang's format) | ||
3 | |||
4 | %% Thanks to Michael Goesele (from the Max-Planck-Institut) for the original suggestion | ||
5 | %% of adding thsi export function to the toolbox. | ||
6 | |||
7 | |||
8 | if ~exist('n_ima'), | ||
9 | fprintf(1,'ERROR: No calibration data to export\n'); | ||
10 | |||
11 | else | ||
12 | |||
13 | check_active_images; | ||
14 | |||
15 | check_extracted_images; | ||
16 | |||
17 | check_active_images; | ||
18 | |||
19 | fprintf(1,'Tool that exports calibration data to Willson-Heikkila or Zhang formats\n'); | ||
20 | |||
21 | qformat = -1; | ||
22 | |||
23 | while (qformat ~=0)&(qformat ~=1), | ||
24 | |||
25 | fprintf(1,'Two possible formats of export: 0=Willson and Heikkila, 1=Zhang\n') | ||
26 | qformat = input('Format of export (enter 0 or 1): '); | ||
27 | |||
28 | if isempty(qformat) | ||
29 | qformat = -1; | ||
30 | end; | ||
31 | |||
32 | if (qformat ~=0)&(qformat ~=1), | ||
33 | |||
34 | fprintf(1,'Invalid entry. Try again.\n') | ||
35 | |||
36 | end; | ||
37 | |||
38 | end; | ||
39 | |||
40 | if qformat == 0, | ||
41 | |||
42 | fprintf(1,'\nExport of calibration data to text files (Willson and Heikkila''s format)\n'); | ||
43 | outputfile = input('File basename: ','s'); | ||
44 | |||
45 | for kk = ind_active, | ||
46 | |||
47 | eval(['X_kk = X_' num2str(kk) ';']); | ||
48 | eval(['x_kk = x_' num2str(kk) ';']); | ||
49 | |||
50 | Xx = [X_kk ; x_kk]'; | ||
51 | |||
52 | file_name = [outputfile num2str(kk)]; | ||
53 | |||
54 | disp(['Exporting calibration data (3D world + 2D image coordinates) of image ' num2str(kk) ' to file ' file_name '...']); | ||
55 | |||
56 | eval(['save ' file_name ' Xx -ASCII']); | ||
57 | |||
58 | end; | ||
59 | |||
60 | else | ||
61 | |||
62 | fprintf(1,'\nExport of calibration data to text files (Zhang''s format)\n'); | ||
63 | modelfile = input('File basename for the 3D world coordinates: ','s'); | ||
64 | datafile = input('File basename for the 2D image coordinates: ','s'); | ||
65 | |||
66 | for kk = ind_active, | ||
67 | |||
68 | eval(['X_kk = X_' num2str(kk) ';']); | ||
69 | eval(['x_kk = x_' num2str(kk) ';']); | ||
70 | |||
71 | if ~exist(['n_sq_x_' num2str(kk)]), | ||
72 | n_sq_x = 1; | ||
73 | n_sq_y = size(X_kk,2); | ||
74 | else | ||
75 | eval(['n_sq_x = n_sq_x_' num2str(kk) ';']); | ||
76 | eval(['n_sq_y = n_sq_y_' num2str(kk) ';']); | ||
77 | end; | ||
78 | |||
79 | X = reshape(X_kk(1,:)',n_sq_x+1,n_sq_y+1)'; | ||
80 | Y = reshape(X_kk(2,:)',n_sq_x+1,n_sq_y+1)'; | ||
81 | XY = reshape([X;Y],n_sq_y+1,2*(n_sq_x+1)); | ||
82 | |||
83 | x = reshape(x_kk(1,:)',n_sq_x+1,n_sq_y+1)'; | ||
84 | y = reshape(x_kk(2,:)',n_sq_x+1,n_sq_y+1)'; | ||
85 | xy = reshape([x;y],n_sq_y+1,2*(n_sq_x+1)); | ||
86 | |||
87 | disp(['Exporting calibration data of image ' num2str(kk) ' to files ' modelfile num2str(kk) '.txt and ' datafile num2str(kk) '.txt...']); | ||
88 | |||
89 | eval(['save ' modelfile num2str(kk) '.txt XY -ASCII']); | ||
90 | eval(['save ' datafile num2str(kk) '.txt xy -ASCII']); | ||
91 | |||
92 | end; | ||
93 | |||
94 | |||
95 | end; | ||
96 | |||
97 | fprintf(1,'done\n'); | ||
98 | |||
99 | end; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/ext_calib.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/ext_calib.m new file mode 100755 index 0000000..04d6319 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/ext_calib.m | |||
@@ -0,0 +1,152 @@ | |||
1 | |||
2 | %%%%%%%%%%%%%%%%%%%% SHOW EXTRINSIC RESULTS %%%%%%%%%%%%%%%%%%%%%%%% | ||
3 | |||
4 | if ~exist('n_ima')|~exist('fc'), | ||
5 | fprintf(1,'No calibration data available.\n'); | ||
6 | return; | ||
7 | end; | ||
8 | |||
9 | check_active_images; | ||
10 | |||
11 | if ~exist(['omc_' num2str(ind_active(1))]), | ||
12 | fprintf(1,'No calibration data available.\n'); | ||
13 | return; | ||
14 | end; | ||
15 | |||
16 | %if ~exist('no_grid'), | ||
17 | no_grid = 0; | ||
18 | %end; | ||
19 | |||
20 | if ~exist(['n_sq_x_' num2str(ind_active(1))]), | ||
21 | no_grid = 1; | ||
22 | end; | ||
23 | |||
24 | |||
25 | if 0, | ||
26 | |||
27 | err_std = std(ex'); | ||
28 | |||
29 | fprintf(1,'\n\nCalibration results without principal point estimation:\n\n'); | ||
30 | fprintf(1,'Focal Length: fc = [ %3.5f %3.5f]\n',fc); | ||
31 | fprintf(1,'Principal point: cc = [ %3.5f %3.5f]\n',cc); | ||
32 | fprintf(1,'Distortion: kc = [ %3.5f %3.5f %3.5f %3.5f]\n',kc); | ||
33 | fprintf(1,'Pixel error: err = [ %3.5f %3.5f]\n\n',err_std); | ||
34 | |||
35 | end; | ||
36 | |||
37 | |||
38 | % Color code for each image: | ||
39 | |||
40 | colors = 'brgkcm'; | ||
41 | |||
42 | |||
43 | %%% Show the extrinsic parameters | ||
44 | |||
45 | if ~exist('dX'), | ||
46 | eval(['dX = norm(Tc_' num2str(ind_active(1)) ')/10;']); | ||
47 | dY = dX; | ||
48 | end; | ||
49 | |||
50 | IP = 5*dX*([0 nx-1 nx-1 0 0 ; 0 0 ny-1 ny-1 0;1 1 1 1 1] - [cc;0]*ones(1,5)) ./ ([fc;1]*ones(1,5)); | ||
51 | BASE = 5*dX*([0 1 0 0 0 0;0 0 0 1 0 0;0 0 0 0 0 1]); | ||
52 | IP = reshape([IP;BASE(:,1)*ones(1,5);IP],3,15); | ||
53 | |||
54 | figure(4); | ||
55 | [a,b] = view; | ||
56 | |||
57 | figure(4); | ||
58 | plot3(BASE(1,:),BASE(3,:),-BASE(2,:),'b-','linewidth',2'); | ||
59 | hold on; | ||
60 | plot3(IP(1,:),IP(3,:),-IP(2,:),'r-','linewidth',2); | ||
61 | text(6*dX,0,0,'X_c'); | ||
62 | text(-dX,5*dX,0,'Z_c'); | ||
63 | text(0,0,-6*dX,'Y_c'); | ||
64 | text(-dX,-dX,dX,'O_c'); | ||
65 | |||
66 | |||
67 | for kk = 1:n_ima, | ||
68 | |||
69 | if active_images(kk); | ||
70 | |||
71 | if exist(['X_' num2str(kk)]) & exist(['omc_' num2str(kk)]), | ||
72 | |||
73 | eval(['XX_kk = X_' num2str(kk) ';']); | ||
74 | |||
75 | if ~isnan(XX_kk(1,1)) | ||
76 | |||
77 | eval(['omc_kk = omc_' num2str(kk) ';']); | ||
78 | eval(['Tc_kk = Tc_' num2str(kk) ';']); | ||
79 | N_kk = size(XX_kk,2); | ||
80 | |||
81 | if ~exist(['n_sq_x_' num2str(kk)]), | ||
82 | no_grid = 1; | ||
83 | else | ||
84 | eval(['n_sq_x = n_sq_x_' num2str(kk) ';']); | ||
85 | if isnan(n_sq_x(1)), | ||
86 | no_grid = 1; | ||
87 | end; | ||
88 | end; | ||
89 | |||
90 | |||
91 | if ~no_grid, | ||
92 | eval(['n_sq_x = n_sq_x_' num2str(kk) ';']); | ||
93 | eval(['n_sq_y = n_sq_y_' num2str(kk) ';']); | ||
94 | if (N_kk ~= ((n_sq_x+1)*(n_sq_y+1))), | ||
95 | no_grid = 1; | ||
96 | end; | ||
97 | end; | ||
98 | |||
99 | if ~isnan(omc_kk(1,1)), | ||
100 | |||
101 | R_kk = rodrigues(omc_kk); | ||
102 | |||
103 | YY_kk = R_kk * XX_kk + Tc_kk * ones(1,length(XX_kk)); | ||
104 | |||
105 | uu = [-dX;-dY;0]/2; | ||
106 | uu = R_kk * uu + Tc_kk; | ||
107 | |||
108 | if ~no_grid, | ||
109 | YYx = zeros(n_sq_x+1,n_sq_y+1); | ||
110 | YYy = zeros(n_sq_x+1,n_sq_y+1); | ||
111 | YYz = zeros(n_sq_x+1,n_sq_y+1); | ||
112 | |||
113 | YYx(:) = YY_kk(1,:); | ||
114 | YYy(:) = YY_kk(2,:); | ||
115 | YYz(:) = YY_kk(3,:); | ||
116 | |||
117 | %keyboard; | ||
118 | |||
119 | figure(4); | ||
120 | hhh= mesh(YYx,YYz,-YYy); | ||
121 | set(hhh,'edgecolor',colors(rem(kk-1,6)+1),'linewidth',1); %,'facecolor','none'); | ||
122 | %plot3(YY_kk(1,:),YY_kk(3,:),-YY_kk(2,:),['o' colors(rem(kk-1,6)+1)]); | ||
123 | text(uu(1),uu(3),-uu(2),num2str(kk),'fontsize',14,'color',colors(rem(kk-1,6)+1)); | ||
124 | else | ||
125 | |||
126 | figure(4); | ||
127 | plot3(YY_kk(1,:),YY_kk(3,:),-YY_kk(2,:),['.' colors(rem(kk-1,6)+1)]); | ||
128 | text(uu(1),uu(3),-uu(2),num2str(kk),'fontsize',14,'color',colors(rem(kk-1,6)+1)); | ||
129 | |||
130 | end; | ||
131 | |||
132 | end; | ||
133 | |||
134 | end; | ||
135 | |||
136 | end; | ||
137 | |||
138 | end; | ||
139 | |||
140 | end; | ||
141 | |||
142 | figure(4);rotate3d on; | ||
143 | axis('equal'); | ||
144 | title('Extrinsic parameters'); | ||
145 | %view(60,30); | ||
146 | view(a,b); | ||
147 | hold off; | ||
148 | |||
149 | set(4,'Name','3D','NumberTitle','off'); | ||
150 | |||
151 | %fprintf(1,'To generate the complete movie associated to the optimization loop, try: check_convergence;\n'); | ||
152 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/extract_grid.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/extract_grid.m new file mode 100755 index 0000000..0cf9abe --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/extract_grid.m | |||
@@ -0,0 +1,234 @@ | |||
1 | function [x,X,n_sq_x,n_sq_y,ind_orig,ind_x,ind_y] = extract_grid(I,wintx,winty,fc,cc,kc,dX,dY); | ||
2 | |||
3 | map = gray(256); | ||
4 | |||
5 | minI = min(I(:)); | ||
6 | maxI = max(I(:)); | ||
7 | |||
8 | Id = 255*(I - minI)/(maxI - minI); | ||
9 | |||
10 | figure(2); | ||
11 | image(Id); | ||
12 | colormap(map); | ||
13 | |||
14 | |||
15 | if nargin < 2, | ||
16 | |||
17 | disp('Window size for corner finder (wintx and winty):'); | ||
18 | wintx = input('wintx ([] = 5) = '); | ||
19 | if isempty(wintx), wintx = 5; end; | ||
20 | wintx = round(wintx); | ||
21 | winty = input('winty ([] = 5) = '); | ||
22 | if isempty(winty), winty = 5; end; | ||
23 | winty = round(winty); | ||
24 | |||
25 | fprintf(1,'Window size = %dx%d\n',2*wintx+1,2*winty+1); | ||
26 | |||
27 | end; | ||
28 | |||
29 | |||
30 | |||
31 | title('Click on the four extreme corners of the rectangular pattern...'); | ||
32 | |||
33 | disp('Click on the four extreme corners of the rectangular complete pattern...'); | ||
34 | |||
35 | [x,y] = ginput3(4); | ||
36 | |||
37 | [Xc,good,bad,type] = cornerfinder([x';y'],I,winty,wintx); % the four corners | ||
38 | |||
39 | x = Xc(1,:)'; | ||
40 | y = Xc(2,:)'; | ||
41 | |||
42 | [y,indy] = sort(y); | ||
43 | x = x(indy); | ||
44 | |||
45 | if (x(2) > x(1)), | ||
46 | x4 = x(1);y4 = y(1); x3 = x(2); y3 = y(2); | ||
47 | else | ||
48 | x4 = x(2);y4 = y(2); x3 = x(1); y3 = y(1); | ||
49 | end; | ||
50 | if (x(3) > x(4)), | ||
51 | x2 = x(3);y2 = y(3); x1 = x(4); y1 = y(4); | ||
52 | else | ||
53 | x2 = x(4);y2 = y(4); x1 = x(3); y1 = y(3); | ||
54 | end; | ||
55 | |||
56 | x = [x1;x2;x3;x4]; | ||
57 | y = [y1;y2;y3;y4]; | ||
58 | |||
59 | |||
60 | figure(2); hold on; | ||
61 | plot([x;x(1)],[y;y(1)],'g-'); | ||
62 | plot(x,y,'og'); | ||
63 | hx=text((x(4)+x(3))/2,(y(4)+y(3))/2 - 20,'X'); | ||
64 | set(hx,'color','g','Fontsize',14); | ||
65 | hy=text((x(4)+x(1))/2-20,(y(4)+y(1))/2,'Y'); | ||
66 | set(hy,'color','g','Fontsize',14); | ||
67 | hold off; | ||
68 | |||
69 | |||
70 | % Try to automatically count the number of squares in the grid | ||
71 | |||
72 | n_sq_x1 = count_squares(I,x1,y1,x2,y2,wintx); | ||
73 | n_sq_x2 = count_squares(I,x3,y3,x4,y4,wintx); | ||
74 | n_sq_y1 = count_squares(I,x2,y2,x3,y3,wintx); | ||
75 | n_sq_y2 = count_squares(I,x4,y4,x1,y1,wintx); | ||
76 | |||
77 | |||
78 | |||
79 | % If could not count the number of squares, enter manually | ||
80 | |||
81 | if (n_sq_x1~=n_sq_x2)|(n_sq_y1~=n_sq_y2), | ||
82 | |||
83 | |||
84 | disp('Could not count the number of squares in the grid. Enter manually.'); | ||
85 | n_sq_x = input('Number of squares along the X direction ([]=10) = '); %6 | ||
86 | if isempty(n_sq_x), n_sq_x = 10; end; | ||
87 | n_sq_y = input('Number of squares along the Y direction ([]=10) = '); %6 | ||
88 | if isempty(n_sq_y), n_sq_y = 10; end; | ||
89 | |||
90 | else | ||
91 | |||
92 | n_sq_x = n_sq_x1; | ||
93 | n_sq_y = n_sq_y1; | ||
94 | |||
95 | end; | ||
96 | |||
97 | if ~exist('dX')|~exist('dY'), | ||
98 | |||
99 | % Enter the size of each square | ||
100 | |||
101 | dX = input(['Size dX of each square along the X direction ([]=30mm) = ']); | ||
102 | dY = input(['Size dY of each square along the Y direction ([]=30mm) = ']); | ||
103 | if isempty(dX), dX = 30; end; | ||
104 | if isempty(dY), dY = 30; end; | ||
105 | |||
106 | end; | ||
107 | |||
108 | |||
109 | % Compute the inside points through computation of the planar homography (collineation) | ||
110 | |||
111 | a00 = [x(1);y(1);1]; | ||
112 | a10 = [x(2);y(2);1]; | ||
113 | a11 = [x(3);y(3);1]; | ||
114 | a01 = [x(4);y(4);1]; | ||
115 | |||
116 | |||
117 | % Compute the planart collineation: (return the normalization matrice as well) | ||
118 | |||
119 | [Homo,Hnorm,inv_Hnorm] = compute_homography ([a00 a10 a11 a01],[0 1 1 0;0 0 1 1;1 1 1 1]); | ||
120 | |||
121 | |||
122 | % Build the grid using the planar collineation: | ||
123 | |||
124 | x_l = ((0:n_sq_x)'*ones(1,n_sq_y+1))/n_sq_x; | ||
125 | y_l = (ones(n_sq_x+1,1)*(0:n_sq_y))/n_sq_y; | ||
126 | pts = [x_l(:) y_l(:) ones((n_sq_x+1)*(n_sq_y+1),1)]'; | ||
127 | |||
128 | XX = Homo*pts; | ||
129 | XX = XX(1:2,:) ./ (ones(2,1)*XX(3,:)); | ||
130 | |||
131 | |||
132 | % Complete size of the rectangle | ||
133 | |||
134 | W = n_sq_x*dX; | ||
135 | L = n_sq_y*dY; | ||
136 | |||
137 | |||
138 | |||
139 | if nargin < 6, | ||
140 | |||
141 | %%%%%%%%%%%%%%%%%%%%%%%% ADDITIONAL STUFF IN THE CASE OF HIGHLY DISTORTED IMAGES %%%%%%%%%%%%% | ||
142 | figure(2); | ||
143 | hold on; | ||
144 | plot(XX(1,:),XX(2,:),'r+'); | ||
145 | title('The red crosses should be close to the image corners'); | ||
146 | hold off; | ||
147 | |||
148 | disp('If the guessed grid corners (red crosses on the image) are not close to the actual corners,'); | ||
149 | disp('it is necessary to enter an initial guess for the radial distortion factor kc (useful for subpixel detection)'); | ||
150 | quest_distort = input('Need of an initial guess for distortion? ([]=no, other=yes) '); | ||
151 | |||
152 | quest_distort = ~isempty(quest_distort); | ||
153 | |||
154 | if quest_distort, | ||
155 | % Estimation of focal length: | ||
156 | c_g = [size(I,2);size(I,1)]/2 + .5; | ||
157 | f_g = Distor2Calib(0,[[x(1) x(2) x(4) x(3)] - c_g(1);[y(1) y(2) y(4) y(3)] - c_g(2)],1,1,4,W,L,[-W/2 W/2 W/2 -W/2;L/2 L/2 -L/2 -L/2; 0 0 0 0],100,1,1); | ||
158 | f_g = mean(f_g); | ||
159 | script_fit_distortion; | ||
160 | end; | ||
161 | %%%%%%%%%%%%%%%%%%%%% END ADDITIONAL STUFF IN THE CASE OF HIGHLY DISTORTED IMAGES %%%%%%%%%%%%% | ||
162 | |||
163 | else | ||
164 | |||
165 | xy_corners_undist = comp_distortion_oulu([(x' - cc(1))/fc(1);(y'-cc(2))/fc(1)],kc); | ||
166 | |||
167 | xu = xy_corners_undist(1,:)'; | ||
168 | yu = xy_corners_undist(2,:)'; | ||
169 | |||
170 | [XXu] = projectedGrid ( [xu(1);yu(1)], [xu(2);yu(2)],[xu(3);yu(3)], [xu(4);yu(4)],n_sq_x+1,n_sq_y+1); % The full grid | ||
171 | |||
172 | r2 = sum(XXu.^2); | ||
173 | XX = (ones(2,1)*(1 + kc(1) * r2 + kc(2) * (r2.^2))) .* XXu; | ||
174 | XX(1,:) = fc(1)*XX(1,:)+cc(1); | ||
175 | XX(2,:) = fc(2)*XX(2,:)+cc(2); | ||
176 | |||
177 | end; | ||
178 | |||
179 | |||
180 | Np = (n_sq_x+1)*(n_sq_y+1); | ||
181 | |||
182 | disp('Corner extraction...'); | ||
183 | |||
184 | grid_pts = cornerfinder(XX,I,winty,wintx); %%% Finds the exact corners at every points! | ||
185 | |||
186 | grid_pts = grid_pts - 1; % subtract 1 to bring the origin to (0,0) instead of (1,1) in matlab (not necessary in C) | ||
187 | |||
188 | ind_corners = [1 n_sq_x+1 (n_sq_x+1)*n_sq_y+1 (n_sq_x+1)*(n_sq_y+1)]; % index of the 4 corners | ||
189 | ind_orig = (n_sq_x+1)*n_sq_y + 1; | ||
190 | xorig = grid_pts(1,ind_orig); | ||
191 | yorig = grid_pts(2,ind_orig); | ||
192 | dxpos = mean([grid_pts(:,ind_orig) grid_pts(:,ind_orig+1)]'); | ||
193 | dypos = mean([grid_pts(:,ind_orig) grid_pts(:,ind_orig-n_sq_x-1)]'); | ||
194 | |||
195 | |||
196 | ind_x = (n_sq_x+1)*(n_sq_y + 1); | ||
197 | ind_y = 1; | ||
198 | |||
199 | x_box_kk = [grid_pts(1,:)-(wintx+.5);grid_pts(1,:)+(wintx+.5);grid_pts(1,:)+(wintx+.5);grid_pts(1,:)-(wintx+.5);grid_pts(1,:)-(wintx+.5)]; | ||
200 | y_box_kk = [grid_pts(2,:)-(winty+.5);grid_pts(2,:)-(winty+.5);grid_pts(2,:)+(winty+.5);grid_pts(2,:)+(winty+.5);grid_pts(2,:)-(winty+.5)]; | ||
201 | |||
202 | |||
203 | figure(3); | ||
204 | image(Id); colormap(map); hold on; | ||
205 | plot(grid_pts(1,:)+1,grid_pts(2,:)+1,'r+'); | ||
206 | plot(x_box_kk+1,y_box_kk+1,'-b'); | ||
207 | plot(grid_pts(1,ind_corners)+1,grid_pts(2,ind_corners)+1,'mo'); | ||
208 | plot(xorig+1,yorig+1,'*m'); | ||
209 | h = text(xorig-15,yorig-15,'O'); | ||
210 | set(h,'Color','m','FontSize',14); | ||
211 | h2 = text(dxpos(1)-10,dxpos(2)-10,'dX'); | ||
212 | set(h2,'Color','g','FontSize',14); | ||
213 | h3 = text(dypos(1)-25,dypos(2)-3,'dY'); | ||
214 | set(h3,'Color','g','FontSize',14); | ||
215 | xlabel('Xc (in camera frame)'); | ||
216 | ylabel('Yc (in camera frame)'); | ||
217 | title('Extracted corners'); | ||
218 | zoom on; | ||
219 | drawnow; | ||
220 | hold off; | ||
221 | |||
222 | |||
223 | Xi = reshape(([0:n_sq_x]*dX)'*ones(1,n_sq_y+1),Np,1)'; | ||
224 | Yi = reshape(ones(n_sq_x+1,1)*[n_sq_y:-1:0]*dY,Np,1)'; | ||
225 | Zi = zeros(1,Np); | ||
226 | |||
227 | Xgrid = [Xi;Yi;Zi]; | ||
228 | |||
229 | |||
230 | % All the point coordinates (on the image, and in 3D) - for global optimization: | ||
231 | |||
232 | x = grid_pts; | ||
233 | X = Xgrid; | ||
234 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/extract_parameters.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/extract_parameters.m new file mode 100755 index 0000000..035b97d --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/extract_parameters.m | |||
@@ -0,0 +1,46 @@ | |||
1 | |||
2 | %%% Extraction of the final intrinsic and extrinsic paramaters: | ||
3 | |||
4 | check_active_images; | ||
5 | |||
6 | fc = solution(1:2);%*** | ||
7 | cc = solution(3:4);%*** | ||
8 | alpha_c = solution(5);%*** | ||
9 | kc = solution(6:9);%*** | ||
10 | |||
11 | |||
12 | % Calibration matrix: | ||
13 | |||
14 | KK = [fc(1) fc(1)*alpha_c cc(1);0 fc(2) cc(2); 0 0 1]; | ||
15 | inv_KK = inv(KK); | ||
16 | |||
17 | % Extract the extrinsic paramters, and recomputer the collineations | ||
18 | |||
19 | for kk = 1:n_ima, | ||
20 | |||
21 | if active_images(kk), | ||
22 | |||
23 | omckk = solution(15+6*(kk-1) + 1:15+6*(kk-1) + 3);%*** | ||
24 | Tckk = solution(15+6*(kk-1) + 4:15+6*(kk-1) + 6);%*** | ||
25 | |||
26 | Rckk = rodrigues(omckk); | ||
27 | |||
28 | Hkk = KK * [Rckk(:,1) Rckk(:,2) Tckk]; | ||
29 | |||
30 | Hkk = Hkk / Hkk(3,3); | ||
31 | |||
32 | else | ||
33 | |||
34 | omckk = NaN*ones(3,1); | ||
35 | Tckk = NaN*ones(3,1); | ||
36 | Rckk = NaN*ones(3,3); | ||
37 | Hkk = NaN*ones(3,3); | ||
38 | |||
39 | end; | ||
40 | |||
41 | eval(['omc_' num2str(kk) ' = omckk;']); | ||
42 | eval(['Rc_' num2str(kk) ' = Rckk;']); | ||
43 | eval(['Tc_' num2str(kk) ' = Tckk;']); | ||
44 | eval(['H_' num2str(kk) '= Hkk;']); | ||
45 | |||
46 | end; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/extract_parameters3D.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/extract_parameters3D.m new file mode 100755 index 0000000..841c6ab --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/extract_parameters3D.m | |||
@@ -0,0 +1,36 @@ | |||
1 | |||
2 | %%% Extraction of the final intrinsic and extrinsic paramaters: | ||
3 | |||
4 | |||
5 | fc = solution(1:2); | ||
6 | kc = solution(3:6); | ||
7 | cc = solution(6*n_ima + 4 +3:6*n_ima + 5 +3); | ||
8 | |||
9 | % Calibration matrix: | ||
10 | |||
11 | KK = [fc(1) 0 cc(1);0 fc(2) cc(2); 0 0 1]; | ||
12 | inv_KK = inv(KK); | ||
13 | |||
14 | % Extract the extrinsic paramters, and recomputer the collineations | ||
15 | |||
16 | for kk = 1:n_ima, | ||
17 | |||
18 | omckk = solution(4+6*(kk-1) + 3:6*kk + 3); | ||
19 | |||
20 | Tckk = solution(6*kk+1 + 3:6*kk+3 + 3); | ||
21 | |||
22 | Rckk = rodrigues(omckk); | ||
23 | |||
24 | Hlkk = KK * [Rckk(:,1) Rckk(:,2) Tckk]; | ||
25 | |||
26 | Hlkk = Hlkk / Hlkk(3,3); | ||
27 | |||
28 | eval(['omc_' num2str(kk) ' = omckk;']); | ||
29 | eval(['Rc_' num2str(kk) ' = Rckk;']); | ||
30 | eval(['Tc_' num2str(kk) ' = Tckk;']); | ||
31 | |||
32 | eval(['Hl_' num2str(kk) '=Hlkk;']); | ||
33 | |||
34 | end; | ||
35 | |||
36 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/extrinsic_computation.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/extrinsic_computation.m new file mode 100755 index 0000000..fbba78e --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/extrinsic_computation.m | |||
@@ -0,0 +1,185 @@ | |||
1 | %%% INPUT THE IMAGE FILE NAME: | ||
2 | |||
3 | if ~exist('fc')|~exist('cc')|~exist('kc')|~exist('alpha_c'), | ||
4 | fprintf(1,'No intrinsic camera parameters available.\n'); | ||
5 | return; | ||
6 | end; | ||
7 | |||
8 | dir; | ||
9 | |||
10 | fprintf(1,'\n'); | ||
11 | disp('Computation of the extrinsic parameters from an image of a pattern'); | ||
12 | disp('The intrinsic camera parameters are assumed to be known (previously computed)'); | ||
13 | |||
14 | fprintf(1,'\n'); | ||
15 | image_name = input('Image name (full name without extension): ','s'); | ||
16 | |||
17 | format_image2 = '0'; | ||
18 | |||
19 | while format_image2 == '0', | ||
20 | |||
21 | format_image2 = input('Image format: ([]=''r''=''ras'', ''b''=''bmp'', ''t''=''tif'', ''p''=''pgm'', ''j''=''jpg'', ''m''=''ppm'') ','s'); | ||
22 | |||
23 | if isempty(format_image2), | ||
24 | format_image2 = 'ras'; | ||
25 | end; | ||
26 | |||
27 | if lower(format_image2(1)) == 'm', | ||
28 | format_image2 = 'ppm'; | ||
29 | else | ||
30 | if lower(format_image2(1)) == 'b', | ||
31 | format_image2 = 'bmp'; | ||
32 | else | ||
33 | if lower(format_image2(1)) == 't', | ||
34 | format_image2 = 'tif'; | ||
35 | else | ||
36 | if lower(format_image2(1)) == 'p', | ||
37 | format_image2 = 'pgm'; | ||
38 | else | ||
39 | if lower(format_image2(1)) == 'j', | ||
40 | format_image2 = 'jpg'; | ||
41 | else | ||
42 | if lower(format_image2(1)) == 'r', | ||
43 | format_image2 = 'ras'; | ||
44 | else | ||
45 | disp('Invalid image format'); | ||
46 | format_image2 = '0'; % Ask for format once again | ||
47 | end; | ||
48 | end; | ||
49 | end; | ||
50 | end; | ||
51 | end; | ||
52 | end; | ||
53 | end; | ||
54 | |||
55 | ima_name = [image_name '.' format_image2]; | ||
56 | |||
57 | |||
58 | %%% READ IN IMAGE: | ||
59 | |||
60 | if format_image2(1) == 'p', | ||
61 | if format_image2(2) == 'p', | ||
62 | I = double(loadppm(ima_name)); | ||
63 | else | ||
64 | I = double(loadpgm(ima_name)); | ||
65 | end; | ||
66 | else | ||
67 | if format_image2(1) == 'r', | ||
68 | I = readras(ima_name); | ||
69 | else | ||
70 | I = double(imread(ima_name)); | ||
71 | end; | ||
72 | end; | ||
73 | |||
74 | if size(I,3)>1, | ||
75 | I = I(:,:,2); | ||
76 | end; | ||
77 | |||
78 | |||
79 | %%% EXTRACT GRID CORNERS: | ||
80 | |||
81 | fprintf(1,'\nExtraction of the grid corners on the image\n'); | ||
82 | |||
83 | disp('Window size for corner finder (wintx and winty):'); | ||
84 | wintx = input('wintx ([] = 5) = '); | ||
85 | if isempty(wintx), wintx = 5; end; | ||
86 | wintx = round(wintx); | ||
87 | winty = input('winty ([] = 5) = '); | ||
88 | if isempty(winty), winty = 5; end; | ||
89 | winty = round(winty); | ||
90 | |||
91 | fprintf(1,'Window size = %dx%d\n',2*wintx+1,2*winty+1); | ||
92 | |||
93 | [x_ext,X_ext,n_sq_x,n_sq_y,ind_orig,ind_x,ind_y] = extract_grid(I,wintx,winty,fc,cc,kc); | ||
94 | |||
95 | |||
96 | |||
97 | %%% Computation of the Extrinsic Parameters attached to the grid: | ||
98 | |||
99 | [omc_ext,Tc_ext,Rc_ext,H_ext] = compute_extrinsic(x_ext,X_ext,fc,cc,kc,alpha_c); | ||
100 | |||
101 | |||
102 | %%% Reproject the points on the image: | ||
103 | |||
104 | [x_reproj] = project_points2(X_ext,omc_ext,Tc_ext,fc,cc,kc,alpha_c); | ||
105 | |||
106 | err_reproj = x_ext - x_reproj; | ||
107 | |||
108 | err_std2 = std(err_reproj')'; | ||
109 | |||
110 | |||
111 | Basis = [X_ext(:,[ind_orig ind_x ind_orig ind_y ind_orig ])]; | ||
112 | |||
113 | VX = Basis(:,2) - Basis(:,1); | ||
114 | VY = Basis(:,4) - Basis(:,1); | ||
115 | |||
116 | nX = norm(VX); | ||
117 | nY = norm(VY); | ||
118 | |||
119 | VZ = min(nX,nY) * cross(VX/nX,VY/nY); | ||
120 | |||
121 | Basis = [Basis VZ]; | ||
122 | |||
123 | [x_basis] = project_points2(Basis,omc_ext,Tc_ext,fc,cc,kc,alpha_c); | ||
124 | |||
125 | dxpos = (x_basis(:,2) + x_basis(:,1))/2; | ||
126 | dypos = (x_basis(:,4) + x_basis(:,3))/2; | ||
127 | dzpos = (x_basis(:,6) + x_basis(:,5))/2; | ||
128 | |||
129 | |||
130 | |||
131 | figure(2); | ||
132 | image(I); | ||
133 | colormap(gray(256)); | ||
134 | hold on; | ||
135 | plot(x_ext(1,:)+1,x_ext(2,:)+1,'r+'); | ||
136 | plot(x_reproj(1,:)+1,x_reproj(2,:)+1,'yo'); | ||
137 | h = text(x_ext(1,ind_orig)-25,x_ext(2,ind_orig)-25,'O'); | ||
138 | set(h,'Color','g','FontSize',14); | ||
139 | h2 = text(dxpos(1)+1,dxpos(2)-30,'X'); | ||
140 | set(h2,'Color','g','FontSize',14); | ||
141 | h3 = text(dypos(1)-30,dypos(2)+1,'Y'); | ||
142 | set(h3,'Color','g','FontSize',14); | ||
143 | h4 = text(dzpos(1)-10,dzpos(2)-20,'Z'); | ||
144 | set(h4,'Color','g','FontSize',14); | ||
145 | plot(x_basis(1,:)+1,x_basis(2,:)+1,'g-','linewidth',2); | ||
146 | title('Image points (+) and reprojected grid points (o)'); | ||
147 | hold off; | ||
148 | |||
149 | |||
150 | fprintf(1,'\n\nExtrinsic parameters:\n\n'); | ||
151 | fprintf(1,'Translation vector: Tc_ext = [ %3.6f \t %3.6f \t %3.6f ]\n',Tc_ext); | ||
152 | fprintf(1,'Rotation vector: omc_ext = [ %3.6f \t %3.6f \t %3.6f ]\n',omc_ext); | ||
153 | fprintf(1,'Rotation matrix: Rc_ext = [ %3.6f \t %3.6f \t %3.6f\n',Rc_ext(1,:)'); | ||
154 | fprintf(1,' %3.6f \t %3.6f \t %3.6f\n',Rc_ext(2,:)'); | ||
155 | fprintf(1,' %3.6f \t %3.6f \t %3.6f ]\n',Rc_ext(3,:)'); | ||
156 | fprintf(1,'Pixel error: err = [ %3.5f \t %3.5f ]\n\n',err_std2); | ||
157 | |||
158 | |||
159 | |||
160 | |||
161 | |||
162 | return; | ||
163 | |||
164 | |||
165 | % Stores the results: | ||
166 | |||
167 | kk = 1; | ||
168 | |||
169 | % Stores location of grid wrt camera: | ||
170 | |||
171 | eval(['omc_' num2str(kk) ' = omc_ext;']); | ||
172 | eval(['Tc_' num2str(kk) ' = Tc_ext;']); | ||
173 | |||
174 | % Stores the projected points: | ||
175 | |||
176 | eval(['y_' num2str(kk) ' = x_reproj;']); | ||
177 | eval(['X_' num2str(kk) ' = X_ext;']); | ||
178 | eval(['x_' num2str(kk) ' = x_ext;']); | ||
179 | |||
180 | |||
181 | % Organize the points in a grid: | ||
182 | |||
183 | eval(['n_sq_x_' num2str(kk) ' = n_sq_x;']); | ||
184 | eval(['n_sq_y_' num2str(kk) ' = n_sq_y;']); | ||
185 | \ No newline at end of file | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/fixallvariables.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/fixallvariables.m new file mode 100755 index 0000000..b5808f3 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/fixallvariables.m | |||
@@ -0,0 +1,19 @@ | |||
1 | % Code that clears all empty or NaN variables | ||
2 | |||
3 | varlist = whos; | ||
4 | |||
5 | if ~isempty(varlist), | ||
6 | |||
7 | Nvar = size(varlist,1); | ||
8 | |||
9 | for c_var = 1:Nvar, | ||
10 | |||
11 | var2fix = varlist(c_var).name; | ||
12 | |||
13 | fixvariable; | ||
14 | |||
15 | end; | ||
16 | |||
17 | end; | ||
18 | |||
19 | clear varlist var2fix Nvar c_var \ No newline at end of file | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/fixvariable.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/fixvariable.m new file mode 100755 index 0000000..2213431 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/fixvariable.m | |||
@@ -0,0 +1,18 @@ | |||
1 | % Code that clears an empty variable, or a NaN vsriable. | ||
2 | % Does not clear structures, or cells. | ||
3 | |||
4 | if exist('var2fix'), | ||
5 | if eval(['exist(''' var2fix ''') == 1']), | ||
6 | if eval(['isempty(' var2fix ')']), | ||
7 | eval(['clear ' var2fix ]); | ||
8 | else | ||
9 | if eval(['~isstruct(' var2fix ')']), | ||
10 | if eval(['~iscell(' var2fix ')']), | ||
11 | if eval(['isnan(' var2fix '(1))']), | ||
12 | eval(['clear ' var2fix ]); | ||
13 | end; | ||
14 | end; | ||
15 | end; | ||
16 | end; | ||
17 | end; | ||
18 | end; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/ginput3.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/ginput3.m new file mode 100755 index 0000000..56fe496 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/ginput3.m | |||
@@ -0,0 +1,216 @@ | |||
1 | function [out1,out2,out3] = ginput2(arg1) | ||
2 | %GINPUT Graphical input from mouse. | ||
3 | % [X,Y] = GINPUT(N) gets N points from the current axes and returns | ||
4 | % the X- and Y-coordinates in length N vectors X and Y. The cursor | ||
5 | % can be positioned using a mouse (or by using the Arrow Keys on some | ||
6 | % systems). Data points are entered by pressing a mouse button | ||
7 | % or any key on the keyboard except carriage return, which terminates | ||
8 | % the input before N points are entered. | ||
9 | % | ||
10 | % [X,Y] = GINPUT gathers an unlimited number of points until the | ||
11 | % return key is pressed. | ||
12 | % | ||
13 | % [X,Y,BUTTON] = GINPUT(N) returns a third result, BUTTON, that | ||
14 | % contains a vector of integers specifying which mouse button was | ||
15 | % used (1,2,3 from left) or ASCII numbers if a key on the keyboard | ||
16 | % was used. | ||
17 | |||
18 | % Copyright (c) 1984-96 by The MathWorks, Inc. | ||
19 | % $Revision: 5.18 $ $Date: 1996/11/10 17:48:08 $ | ||
20 | |||
21 | % Fixed version by Jean-Yves Bouguet to have a cross instead of 2 lines | ||
22 | % More visible for images | ||
23 | |||
24 | P = NaN*ones(16,16); | ||
25 | P(1:15,1:15) = 2*ones(15,15); | ||
26 | P(2:14,2:14) = ones(13,13); | ||
27 | P(3:13,3:13) = NaN*ones(11,11); | ||
28 | P(6:10,6:10) = 2*ones(5,5); | ||
29 | P(7:9,7:9) = 1*ones(3,3); | ||
30 | |||
31 | out1 = []; out2 = []; out3 = []; y = []; | ||
32 | c = computer; | ||
33 | if ~strcmp(c(1:2),'PC') & ~strcmp(c(1:2),'MA') | ||
34 | tp = get(0,'TerminalProtocol'); | ||
35 | else | ||
36 | tp = 'micro'; | ||
37 | end | ||
38 | |||
39 | if ~strcmp(tp,'none') & ~strcmp(tp,'x') & ~strcmp(tp,'micro'), | ||
40 | if nargout == 1, | ||
41 | if nargin == 1, | ||
42 | eval('out1 = trmginput(arg1);'); | ||
43 | else | ||
44 | eval('out1 = trmginput;'); | ||
45 | end | ||
46 | elseif nargout == 2 | nargout == 0, | ||
47 | if nargin == 1, | ||
48 | eval('[out1,out2] = trmginput(arg1);'); | ||
49 | else | ||
50 | eval('[out1,out2] = trmginput;'); | ||
51 | end | ||
52 | if nargout == 0 | ||
53 | out1 = [ out1 out2 ]; | ||
54 | end | ||
55 | elseif nargout == 3, | ||
56 | if nargin == 1, | ||
57 | eval('[out1,out2,out3] = trmginput(arg1);'); | ||
58 | else | ||
59 | eval('[out1,out2,out3] = trmginput;'); | ||
60 | end | ||
61 | end | ||
62 | else | ||
63 | |||
64 | fig = gcf; | ||
65 | figure(gcf); | ||
66 | |||
67 | if nargin == 0 | ||
68 | how_many = -1; | ||
69 | b = []; | ||
70 | else | ||
71 | how_many = arg1; | ||
72 | b = []; | ||
73 | if isstr(how_many) ... | ||
74 | | size(how_many,1) ~= 1 | size(how_many,2) ~= 1 ... | ||
75 | | ~(fix(how_many) == how_many) ... | ||
76 | | how_many < 0 | ||
77 | error('Requires a positive integer.') | ||
78 | end | ||
79 | if how_many == 0 | ||
80 | ptr_fig = 0; | ||
81 | while(ptr_fig ~= fig) | ||
82 | ptr_fig = get(0,'PointerWindow'); | ||
83 | end | ||
84 | scrn_pt = get(0,'PointerLocation'); | ||
85 | loc = get(fig,'Position'); | ||
86 | pt = [scrn_pt(1) - loc(1), scrn_pt(2) - loc(2)]; | ||
87 | out1 = pt(1); y = pt(2); | ||
88 | elseif how_many < 0 | ||
89 | error('Argument must be a positive integer.') | ||
90 | end | ||
91 | end | ||
92 | |||
93 | pointer = get(gcf,'pointer'); | ||
94 | |||
95 | set(gcf,'Pointer','custom','PointerShapeCData',P,'PointerShapeHotSpot',[8,8]); | ||
96 | %set(gcf,'pointer','crosshair'); | ||
97 | fig_units = get(fig,'units'); | ||
98 | char = 0; | ||
99 | |||
100 | while how_many ~= 0 | ||
101 | % Use no-side effect WAITFORBUTTONPRESS | ||
102 | waserr = 0; | ||
103 | eval('keydown = wfbp;', 'waserr = 1;'); | ||
104 | if(waserr == 1) | ||
105 | if(ishandle(fig)) | ||
106 | set(fig,'pointer',pointer,'units',fig_units); | ||
107 | error('Interrupted'); | ||
108 | else | ||
109 | error('Interrupted by figure deletion'); | ||
110 | end | ||
111 | end | ||
112 | |||
113 | ptr_fig = get(0,'CurrentFigure'); | ||
114 | if(ptr_fig == fig) | ||
115 | if keydown | ||
116 | char = get(fig, 'CurrentCharacter'); | ||
117 | button = abs(get(fig, 'CurrentCharacter')); | ||
118 | scrn_pt = get(0, 'PointerLocation'); | ||
119 | set(fig,'units','pixels') | ||
120 | loc = get(fig, 'Position'); | ||
121 | pt = [scrn_pt(1) - loc(1), scrn_pt(2) - loc(2)]; | ||
122 | set(fig,'CurrentPoint',pt); | ||
123 | else | ||
124 | button = get(fig, 'SelectionType'); | ||
125 | if strcmp(button,'open') | ||
126 | button = b(length(b)); | ||
127 | elseif strcmp(button,'normal') | ||
128 | button = 1; | ||
129 | elseif strcmp(button,'extend') | ||
130 | button = 2; | ||
131 | elseif strcmp(button,'alt') | ||
132 | button = 3; | ||
133 | else | ||
134 | error('Invalid mouse selection.') | ||
135 | end | ||
136 | end | ||
137 | pt = get(gca, 'CurrentPoint'); | ||
138 | |||
139 | how_many = how_many - 1; | ||
140 | |||
141 | if(char == 13) % & how_many ~= 0) | ||
142 | % if the return key was pressed, char will == 13, | ||
143 | % and that's our signal to break out of here whether | ||
144 | % or not we have collected all the requested data | ||
145 | % points. | ||
146 | % If this was an early breakout, don't include | ||
147 | % the <Return> key info in the return arrays. | ||
148 | % We will no longer count it if it's the last input. | ||
149 | break; | ||
150 | end | ||
151 | |||
152 | out1 = [out1;pt(1,1)]; | ||
153 | y = [y;pt(1,2)]; | ||
154 | b = [b;button]; | ||
155 | end | ||
156 | end | ||
157 | |||
158 | set(fig,'pointer',pointer,'units',fig_units); | ||
159 | |||
160 | if nargout > 1 | ||
161 | out2 = y; | ||
162 | if nargout > 2 | ||
163 | out3 = b; | ||
164 | end | ||
165 | else | ||
166 | out1 = [out1 y]; | ||
167 | end | ||
168 | |||
169 | end | ||
170 | |||
171 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
172 | function key = wfbp | ||
173 | %WFBP Replacement for WAITFORBUTTONPRESS that has no side effects. | ||
174 | |||
175 | % Remove figure button functions | ||
176 | fprops = {'windowbuttonupfcn','buttondownfcn', ... | ||
177 | 'windowbuttondownfcn','windowbuttonmotionfcn'}; | ||
178 | fig = gcf; | ||
179 | fvals = get(fig,fprops); | ||
180 | set(fig,fprops,{'','','',''}) | ||
181 | |||
182 | % Remove all other buttondown functions | ||
183 | ax = findobj(fig,'type','axes'); | ||
184 | if isempty(ax) | ||
185 | ch = {}; | ||
186 | else | ||
187 | ch = get(ax,{'Children'}); | ||
188 | end | ||
189 | for i=1:length(ch), | ||
190 | ch{i} = ch{i}(:)'; | ||
191 | end | ||
192 | h = [ax(:)',ch{:}]; | ||
193 | vals = get(h,{'buttondownfcn'}); | ||
194 | mt = repmat({''},size(vals)); | ||
195 | set(h,{'buttondownfcn'},mt); | ||
196 | |||
197 | % Now wait for that buttonpress, and check for error conditions | ||
198 | waserr = 0; | ||
199 | eval(['if nargout==0,', ... | ||
200 | ' waitforbuttonpress,', ... | ||
201 | 'else,', ... | ||
202 | ' keydown = waitforbuttonpress;',... | ||
203 | 'end' ], 'waserr = 1;'); | ||
204 | |||
205 | % Put everything back | ||
206 | if(ishandle(fig)) | ||
207 | set(fig,fprops,fvals) | ||
208 | set(h,{'buttondownfcn'},vals) | ||
209 | end | ||
210 | |||
211 | if(waserr == 1) | ||
212 | error('Interrupted'); | ||
213 | end | ||
214 | |||
215 | if nargout>0, key = keydown; end | ||
216 | %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/go_calib_optim.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/go_calib_optim.m new file mode 100755 index 0000000..ad19f64 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/go_calib_optim.m | |||
@@ -0,0 +1,139 @@ | |||
1 | %go_calib_optim | ||
2 | % | ||
3 | %Main calibration function. Computes the intrinsic andextrinsic parameters. | ||
4 | %Runs as a script. | ||
5 | % | ||
6 | %INPUT: x_1,x_2,x_3,...: Feature locations on the images | ||
7 | % X_1,X_2,X_3,...: Corresponding grid coordinates | ||
8 | % | ||
9 | %OUTPUT: fc: Camera focal length | ||
10 | % cc: Principal point coordinates | ||
11 | % kc: Distortion coefficients | ||
12 | % KK: The camera matrix (containing fc and cc) | ||
13 | % omc_1,omc_2,omc_3,...: 3D rotation vectors attached to the grid positions in space | ||
14 | % Tc_1,Tc_2,Tc_3,...: 3D translation vectors attached to the grid positions in space | ||
15 | % Rc_1,Rc_2,Rc_3,...: 3D rotation matrices corresponding to the omc vectors | ||
16 | % | ||
17 | %Method: Minimizes the pixel reprojection error in the least squares sense over the intrinsic | ||
18 | % camera parameters, and the extrinsic parameters (3D locations of the grids in space) | ||
19 | % | ||
20 | %Note: If the intrinsic camera parameters (fc, cc, kc) do not exist before, they are initialized through | ||
21 | % the function init_intrinsic_param.m. Otherwise, the variables in memory are used as initial guesses. | ||
22 | % | ||
23 | %Note: The row vector active_images consists of zeros and ones. To deactivate an image, set the | ||
24 | % corresponding entry in the active_images vector to zero. | ||
25 | % | ||
26 | %VERY IMPORTANT: This function works for 2D and 3D calibration rigs, except for init_intrinsic_param.m | ||
27 | %that is so far implemented to work only with 2D rigs. | ||
28 | %In the future, a more general function will be there. | ||
29 | %For now, if using a 3D calibration rig, set quick_init to 1 for an easy initialization of the focal length | ||
30 | |||
31 | |||
32 | if ~exist('n_ima'), | ||
33 | data_calib; % Load the images | ||
34 | click_calib; % Extract the corners | ||
35 | end; | ||
36 | |||
37 | |||
38 | check_active_images; | ||
39 | |||
40 | check_extracted_images; | ||
41 | |||
42 | check_active_images; | ||
43 | |||
44 | |||
45 | desactivated_images = []; | ||
46 | |||
47 | |||
48 | if ~exist('center_optim'), | ||
49 | center_optim = 1; %%% Set this variable to 0 if your do not want to estimate the principal point | ||
50 | %%% Required when using one image, and VERY RECOMMENDED WHEN USING LESS THAN 4 images | ||
51 | end; | ||
52 | |||
53 | % Check 3D-ness of the calibration rig: | ||
54 | rig3D = 0; | ||
55 | for kk = ind_active, | ||
56 | eval(['X_kk = X_' num2str(kk) ';']); | ||
57 | if is3D(X_kk), | ||
58 | rig3D = 1; | ||
59 | end; | ||
60 | end; | ||
61 | |||
62 | |||
63 | if center_optim & (length(ind_active) < 2) & ~rig3D, | ||
64 | fprintf(1,'\nPrincipal point rejected from the optimization when using one image and planar rig (center_optim = 1).\n'); | ||
65 | center_optim = 0; %%% when using a single image, please, no principal point estimation!!! | ||
66 | est_alpha = 0; | ||
67 | end; | ||
68 | |||
69 | if ~exist('dont_ask'), | ||
70 | dont_ask = 0; | ||
71 | end; | ||
72 | |||
73 | if center_optim & (length(ind_active) < 5), | ||
74 | fprintf(1,'\nThe principal point estimation may be unreliable (using less than 5 images for calibration).\n'); | ||
75 | if ~dont_ask, | ||
76 | quest = input('Are you sure you want to keep the principal point in the optimization process? ([]=yes, other=no) '); | ||
77 | center_optim = isempty(quest); | ||
78 | end; | ||
79 | end; | ||
80 | |||
81 | if center_optim, | ||
82 | fprintf(1,'\nINFO: To reject the principal point from the optimization, set center_optim = 0 in go_calib_optim.m\n'); | ||
83 | end; | ||
84 | |||
85 | if ~exist('est_alpha'), | ||
86 | est_alpha = 0; % by default, do not estimate skew | ||
87 | end; | ||
88 | |||
89 | if ~center_optim & (est_alpha), | ||
90 | fprintf(1,'WARNING: Since there is no principal point estimation, no skew estimation (est_alpha = 0)\n'); | ||
91 | est_alpha = 0; | ||
92 | else | ||
93 | if ~est_alpha, | ||
94 | fprintf(1,'WARNING: Skew not optimized. Check variable est_alpha.\n'); | ||
95 | alpha_c = 0; | ||
96 | else | ||
97 | fprintf(1,'WARNING: Skew is optimized. To disable skew estimation, set est_alpha=0.\n'); | ||
98 | end; | ||
99 | end; | ||
100 | |||
101 | |||
102 | if ~exist('est_dist'); | ||
103 | est_dist = [1;1;1;1]; | ||
104 | end; | ||
105 | if ~prod(est_dist), | ||
106 | fprintf(1,'\nWARNING: Distortion not fully estimated. Check variable est_dist.\n'); | ||
107 | end; | ||
108 | |||
109 | |||
110 | |||
111 | |||
112 | %%% MAIN OPTIMIZATION CALL!!!!! (look into this function for the details of implementation) | ||
113 | go_calib_optim_iter; | ||
114 | |||
115 | |||
116 | |||
117 | if ~isempty(desactivated_images), | ||
118 | |||
119 | param_list_save = param_list; | ||
120 | |||
121 | fprintf(1,'\nNew optimization including the images that have been deactivated during the previous optimization.\n'); | ||
122 | active_images(desactivated_images) = ones(1,length(desactivated_images)); | ||
123 | desactivated_images = []; | ||
124 | |||
125 | go_calib_optim_iter; | ||
126 | |||
127 | if ~isempty(desactivated_images), | ||
128 | fprintf(1,['List of images left desactivated: ' num2str(desactivated_images) '\n' ] ); | ||
129 | end; | ||
130 | |||
131 | param_list = [param_list_save(:,1:end-1) param_list]; | ||
132 | |||
133 | end; | ||
134 | |||
135 | |||
136 | %%%%%%%%%%%%%%%%%%%% GRAPHICAL OUTPUT %%%%%%%%%%%%%%%%%%%%%%%% | ||
137 | |||
138 | %graphout_calib; | ||
139 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/go_calib_optim_iter.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/go_calib_optim_iter.m new file mode 100755 index 0000000..e3d22f6 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/go_calib_optim_iter.m | |||
@@ -0,0 +1,394 @@ | |||
1 | %go_calib_optim_iter | ||
2 | % | ||
3 | %Main calibration function. Computes the intrinsic andextrinsic parameters. | ||
4 | %Runs as a script. | ||
5 | % | ||
6 | %INPUT: x_1,x_2,x_3,...: Feature locations on the images | ||
7 | % X_1,X_2,X_3,...: Corresponding grid coordinates | ||
8 | % | ||
9 | %OUTPUT: fc: Camera focal length | ||
10 | % cc: Principal point coordinates | ||
11 | % kc: Distortion coefficients | ||
12 | % KK: The camera matrix (containing fc and cc) | ||
13 | % omc_1,omc_2,omc_3,...: 3D rotation vectors attached to the grid positions in space | ||
14 | % Tc_1,Tc_2,Tc_3,...: 3D translation vectors attached to the grid positions in space | ||
15 | % Rc_1,Rc_2,Rc_3,...: 3D rotation matrices corresponding to the omc vectors | ||
16 | % | ||
17 | %Method: Minimizes the pixel reprojection error in the least squares sense over the intrinsic | ||
18 | % camera parameters, and the extrinsic parameters (3D locations of the grids in space) | ||
19 | % | ||
20 | %Note: If the intrinsic camera parameters (fc, cc, kc) do not exist before, they are initialized through | ||
21 | % the function init_intrinsic_param.m. Otherwise, the variables in memory are used as initial guesses. | ||
22 | % | ||
23 | %Note: The row vector active_images consists of zeros and ones. To deactivate an image, set the | ||
24 | % corresponding entry in the active_images vector to zero. | ||
25 | % | ||
26 | %VERY IMPORTANT: This function works for 2D and 3D calibration rigs, except for init_intrinsic_param.m | ||
27 | %that is so far implemented to work only with 2D rigs. | ||
28 | %In the future, a more general function will be there. | ||
29 | %For now, if using a 3D calibration rig, quick_init is set to 1 for an easy initialization of the focal length | ||
30 | |||
31 | |||
32 | if ~exist('center_optim'), | ||
33 | center_optim = 1; %%% Set this variable to 0 if your do not want to estimate the principal point | ||
34 | end; | ||
35 | |||
36 | if ~exist('est_dist'), | ||
37 | est_dist = [1;1;1;1]; | ||
38 | end; | ||
39 | |||
40 | if ~exist('est_alpha'), | ||
41 | est_alpha = 0; % by default, do not estimate skew | ||
42 | end; | ||
43 | |||
44 | |||
45 | % Little fix in case of stupid values in the binary variables: | ||
46 | center_optim = ~~center_optim; | ||
47 | est_alpha = ~~est_alpha; | ||
48 | est_dist = ~~est_dist; | ||
49 | |||
50 | |||
51 | if ~exist('nx')&~exist('ny'), | ||
52 | fprintf(1,'WARNING: No image size (nx,ny) available. Setting nx=640 and ny=480\n'); | ||
53 | nx = 640; | ||
54 | ny = 480; | ||
55 | end; | ||
56 | |||
57 | |||
58 | check_active_images; | ||
59 | |||
60 | |||
61 | quick_init = 0; % Set to 1 for using a quick init (necessary when using 3D rigs) | ||
62 | |||
63 | |||
64 | if ~center_optim, % In the case where the principal point is not estimated, keep it at the center of the image | ||
65 | fprintf(1,'Principal point not optimized (center_optim=0). It is kept at the center of the image.\n'); | ||
66 | cc = [(nx-1)/2;(ny-1)/2]; | ||
67 | end; | ||
68 | |||
69 | |||
70 | if ~prod(est_dist), | ||
71 | fprintf(1,'\nDistortion not fully estimated. Check variable est_dist.\n'); | ||
72 | end; | ||
73 | |||
74 | if ~est_alpha, | ||
75 | fprintf(1,'Skew not optimized (est_alpha=0).\n'); | ||
76 | alpha_c = 0; | ||
77 | end; | ||
78 | |||
79 | |||
80 | % Check 3D-ness of the calibration rig: | ||
81 | rig3D = 0; | ||
82 | for kk = ind_active, | ||
83 | eval(['X_kk = X_' num2str(kk) ';']); | ||
84 | if is3D(X_kk), | ||
85 | rig3D = 1; | ||
86 | end; | ||
87 | end; | ||
88 | |||
89 | % If the rig is 3D, then no choice: the only valid initialization is manual! | ||
90 | if rig3D, | ||
91 | quick_init = 1; | ||
92 | end; | ||
93 | |||
94 | |||
95 | |||
96 | alpha_smooth = 1; % set alpha_smooth = 1; for steepest gradient descent | ||
97 | |||
98 | |||
99 | % Conditioning threshold for view rejection | ||
100 | thresh_cond = 1e6; | ||
101 | |||
102 | |||
103 | |||
104 | %% Initialization of the intrinsic parameters (if necessary) | ||
105 | |||
106 | if ~exist('cc'), | ||
107 | fprintf(1,'Initialization of the principal point at the center of the image.\n'); | ||
108 | cc = [(nx-1)/2;(ny-1)/2]; | ||
109 | alpha_smooth = 0.4; % slow convergence | ||
110 | end; | ||
111 | |||
112 | |||
113 | if ~exist('kc'), | ||
114 | fprintf(1,'Initialization of the image distortion to zero.\n'); | ||
115 | kc = zeros(4,1); | ||
116 | alpha_smooth = 0.4; % slow convergence | ||
117 | end; | ||
118 | |||
119 | if ~exist('alpha_c'), | ||
120 | fprintf(1,'Initialization of the image skew to zero.\n'); | ||
121 | alpha_c = 0; | ||
122 | alpha_smooth = 0.4; % slow convergence | ||
123 | end; | ||
124 | |||
125 | if ~exist('fc')& quick_init, | ||
126 | FOV_angle = 35; % Initial camera field of view in degrees | ||
127 | fprintf(1,['Initialization of the focal length to a FOV of ' num2str(FOV_angle) ' degrees.\n']); | ||
128 | fc = (nx/2)/tan(pi*FOV_angle/360) * ones(2,1); | ||
129 | alpha_smooth = 0.4; % slow | ||
130 | end; | ||
131 | |||
132 | |||
133 | if ~exist('fc'), | ||
134 | % Initialization of the intrinsic parameters: | ||
135 | fprintf(1,'Initialization of the intrinsic parameters using the vanishing points of planar patterns.\n') | ||
136 | init_intrinsic_param; % The right way to go (if quick_init is not active)! | ||
137 | alpha_smooth = 0.4; % slow convergence | ||
138 | end; | ||
139 | |||
140 | |||
141 | if ~prod(est_dist), | ||
142 | % If no distortion estimated, set to zero the variables that are not estimated | ||
143 | kc = kc .* est_dist; | ||
144 | end; | ||
145 | |||
146 | |||
147 | |||
148 | |||
149 | |||
150 | %% Initialization of the extrinsic parameters for global minimization: | ||
151 | |||
152 | |||
153 | init_param = [fc;cc;alpha_c;kc;zeros(6,1)]; | ||
154 | |||
155 | |||
156 | |||
157 | for kk = 1:n_ima, | ||
158 | |||
159 | if exist(['x_' num2str(kk)]), | ||
160 | |||
161 | eval(['x_kk = x_' num2str(kk) ';']); | ||
162 | eval(['X_kk = X_' num2str(kk) ';']); | ||
163 | |||
164 | if (isnan(x_kk(1,1))), | ||
165 | if active_images(kk), | ||
166 | fprintf(1,'Warning: Cannot calibrate with image %d. Need to extract grid corners first.\n',kk) | ||
167 | fprintf(1,' Set active_images(%d)=1; and run Extract grid corners.\n',kk) | ||
168 | end; | ||
169 | active_images(kk) = 0; | ||
170 | end; | ||
171 | if active_images(kk), | ||
172 | [omckk,Tckk] = compute_extrinsic_init(x_kk,X_kk,fc,cc,kc,alpha_c); | ||
173 | [omckk,Tckk,Rckk,JJ_kk] = compute_extrinsic_refine(omckk,Tckk,x_kk,X_kk,fc,cc,kc,alpha_c,20,thresh_cond); | ||
174 | if cond(JJ_kk)> thresh_cond, | ||
175 | active_images(kk) = 0; | ||
176 | omckk = NaN*ones(3,1); | ||
177 | Tckk = NaN*ones(3,1); | ||
178 | fprintf(1,'\nWarning: View #%d ill-conditioned. This image is now set inactive.\n',kk) | ||
179 | desactivated_images = [desactivated_images kk]; | ||
180 | end; | ||
181 | if isnan(omckk(1,1)), | ||
182 | %fprintf(1,'\nWarning: Desactivating image %d. Re-activate it later by typing:\nactive_images(%d)=1;\nand re-run optimization\n',[kk kk]) | ||
183 | active_images(kk) = 0; | ||
184 | end; | ||
185 | else | ||
186 | omckk = NaN*ones(3,1); | ||
187 | Tckk = NaN*ones(3,1); | ||
188 | end; | ||
189 | |||
190 | else | ||
191 | |||
192 | omckk = NaN*ones(3,1); | ||
193 | Tckk = NaN*ones(3,1); | ||
194 | |||
195 | if active_images(kk), | ||
196 | fprintf(1,'Warning: Cannot calibrate with image %d. Need to extract grid corners first.\n',kk) | ||
197 | fprintf(1,' Set active_images(%d)=1; and run Extract grid corners.\n',kk) | ||
198 | end; | ||
199 | |||
200 | active_images(kk) = 0; | ||
201 | |||
202 | end; | ||
203 | |||
204 | eval(['omc_' num2str(kk) ' = omckk;']); | ||
205 | eval(['Tc_' num2str(kk) ' = Tckk;']); | ||
206 | |||
207 | init_param = [init_param; omckk ; Tckk]; | ||
208 | |||
209 | end; | ||
210 | |||
211 | |||
212 | check_active_images; | ||
213 | |||
214 | |||
215 | |||
216 | %-------------------- Main Optimization: | ||
217 | |||
218 | fprintf(1,'\nMain calibration optimization procedure - Number of images: %d\n',length(ind_active)); | ||
219 | |||
220 | |||
221 | param = init_param; | ||
222 | change = 1; | ||
223 | |||
224 | iter = 0; | ||
225 | |||
226 | fprintf(1,'Gradient descent iterations: '); | ||
227 | |||
228 | param_list = param; | ||
229 | |||
230 | MaxIter = 30; | ||
231 | |||
232 | |||
233 | while (change > 1e-6)&(iter < MaxIter), | ||
234 | |||
235 | fprintf(1,'%d...',iter+1); | ||
236 | |||
237 | |||
238 | %% The first step consists of updating the whole vector of knowns (intrinsic + extrinsic of active | ||
239 | %% images) through a one step steepest gradient descent. | ||
240 | |||
241 | JJ = []; | ||
242 | ex = []; | ||
243 | |||
244 | f = param(1:2); | ||
245 | c = param(3:4); | ||
246 | alpha = param(5); | ||
247 | k = param(6:9); | ||
248 | |||
249 | |||
250 | for kk = 1:n_ima, | ||
251 | |||
252 | if active_images(kk), | ||
253 | |||
254 | %omckk = param(4+6*(kk-1) + 3:6*kk + 3); | ||
255 | |||
256 | %Tckk = param(6*kk+1 + 3:6*kk+3 + 3); | ||
257 | |||
258 | omckk = param(15+6*(kk-1) + 1:15+6*(kk-1) + 3); | ||
259 | |||
260 | Tckk = param(15+6*(kk-1) + 4:15+6*(kk-1) + 6); | ||
261 | |||
262 | if isnan(omckk(1)), | ||
263 | fprintf(1,'Intrinsic parameters at frame %d do not exist\n',kk); | ||
264 | return; | ||
265 | end; | ||
266 | |||
267 | eval(['X_kk = X_' num2str(kk) ';']); | ||
268 | eval(['x_kk = x_' num2str(kk) ';']); | ||
269 | |||
270 | Np = size(X_kk,2); | ||
271 | |||
272 | JJkk = zeros(2*Np,n_ima * 6 + 15); | ||
273 | |||
274 | [x,dxdom,dxdT,dxdf,dxdc,dxdk,dxdalpha] = project_points2(X_kk,omckk,Tckk,f,c,k,alpha); | ||
275 | |||
276 | exkk = x_kk - x; | ||
277 | |||
278 | ex = [ex;exkk(:)]; | ||
279 | |||
280 | JJkk(:,1:2) = dxdf; | ||
281 | JJkk(:,3:4) = dxdc; | ||
282 | JJkk(:,5) = dxdalpha; | ||
283 | JJkk(:,6:9) = dxdk; | ||
284 | JJkk(:,15+6*(kk-1) + 1:15+6*(kk-1) + 3) = dxdom; | ||
285 | JJkk(:,15+6*(kk-1) + 4:15+6*(kk-1) + 6) = dxdT; | ||
286 | |||
287 | |||
288 | |||
289 | JJ = [JJ;JJkk]; | ||
290 | |||
291 | |||
292 | % Check if this view is ill-conditioned: | ||
293 | JJ_kk = [dxdom dxdT]; | ||
294 | if cond(JJ_kk)> thresh_cond, | ||
295 | active_images(kk) = 0; | ||
296 | fprintf(1,'\nWarning: View #%d ill-conditioned. This image is now set inactive.\n',kk) | ||
297 | desactivated_images = [desactivated_images kk]; | ||
298 | param(15+6*(kk-1) + 1:15+6*(kk-1) + 6) = NaN*ones(6,1); | ||
299 | end; | ||
300 | |||
301 | |||
302 | end; | ||
303 | |||
304 | end; | ||
305 | |||
306 | |||
307 | % List of active images (necessary if changed): | ||
308 | check_active_images; | ||
309 | |||
310 | |||
311 | % The following vector helps to select the variables to update (for only active images): | ||
312 | |||
313 | ind_Jac = find([ones(2,1);center_optim*ones(2,1);est_alpha;est_dist;zeros(6,1);reshape(ones(6,1)*active_images,6*n_ima,1)])'; | ||
314 | |||
315 | |||
316 | JJ = JJ(:,ind_Jac); | ||
317 | |||
318 | JJ2 = JJ'*JJ; | ||
319 | |||
320 | |||
321 | % Smoothing coefficient: | ||
322 | |||
323 | alpha_smooth2 = 1-(1-alpha_smooth)^(iter+1); %set to 1 to undo any smoothing! | ||
324 | |||
325 | |||
326 | param_innov = alpha_smooth2*inv(JJ2)*(JJ')*ex; | ||
327 | param_up = param(ind_Jac) + param_innov; | ||
328 | param(ind_Jac) = param_up; | ||
329 | |||
330 | |||
331 | % New intrinsic parameters: | ||
332 | |||
333 | fc_current = param(1:2); | ||
334 | cc_current = param(3:4); | ||
335 | alpha_current = param(5); | ||
336 | kc_current = param(6:9); | ||
337 | |||
338 | |||
339 | % Change on the intrinsic parameters: | ||
340 | change = norm([fc_current;cc_current] - [f;c])/norm([fc_current;cc_current]); | ||
341 | |||
342 | |||
343 | %% Second step: (optional) - It makes convergence faster, and the region of convergence LARGER!!! | ||
344 | %% Recompute the extrinsic parameters only using compute_extrinsic.m (this may be useful sometimes) | ||
345 | %% The complete gradient descent method is useful to precisely update the intrinsic parameters. | ||
346 | |||
347 | MaxIter2 = 20; | ||
348 | |||
349 | |||
350 | for kk = 1:n_ima, | ||
351 | if active_images(kk), | ||
352 | omc_current = param(15+6*(kk-1) + 1:15+6*(kk-1) + 3); | ||
353 | Tc_current = param(15+6*(kk-1) + 4:15+6*(kk-1) + 6); | ||
354 | eval(['X_kk = X_' num2str(kk) ';']); | ||
355 | eval(['x_kk = x_' num2str(kk) ';']); | ||
356 | [omc_current,Tc_current] = compute_extrinsic_init(x_kk,X_kk,fc_current,cc_current,kc_current,alpha_current); | ||
357 | [omckk,Tckk,Rckk,JJ_kk] = compute_extrinsic_refine(omc_current,Tc_current,x_kk,X_kk,fc_current,cc_current,kc_current,alpha_current,MaxIter2,thresh_cond); | ||
358 | if cond(JJ_kk)> thresh_cond, | ||
359 | active_images(kk) = 0; | ||
360 | fprintf(1,'\nWarning: View #%d ill-conditioned. This image is now set inactive.\n',kk) | ||
361 | desactivated_images = [desactivated_images kk]; | ||
362 | omckk = NaN*ones(3,1); | ||
363 | Tckk = NaN*ones(3,1); | ||
364 | end; | ||
365 | param(15+6*(kk-1) + 1:15+6*(kk-1) + 3) = omckk; | ||
366 | param(15+6*(kk-1) + 4:15+6*(kk-1) + 6) = Tckk; | ||
367 | end; | ||
368 | end; | ||
369 | |||
370 | param_list = [param_list param]; | ||
371 | |||
372 | iter = iter + 1; | ||
373 | |||
374 | end; | ||
375 | |||
376 | fprintf(1,'\n'); | ||
377 | |||
378 | |||
379 | solution = param; | ||
380 | |||
381 | |||
382 | %%% Extraction of the final intrinsic and extrinsic paramaters: | ||
383 | |||
384 | extract_parameters; | ||
385 | |||
386 | comp_error_calib; | ||
387 | |||
388 | fprintf(1,'\n\nCalibration results after optimization:\n\n'); | ||
389 | fprintf(1,'Focal Length: fc = [ %3.5f %3.5f ]\n',fc); | ||
390 | fprintf(1,'Principal point: cc = [ %3.5f %3.5f ]\n',cc); | ||
391 | fprintf(1,'Skew: alpha_c = [ %3.5f ] => angle of pixel = %3.5f degrees\n',alpha_c,90 - atan(alpha_c)*180/pi); | ||
392 | fprintf(1,'Distortion: kc = [ %3.5f %3.5f %3.5f %3.5f ]\n',kc); | ||
393 | fprintf(1,'Pixel error: err = [ %3.5f %3.5f ]\n\n',err_std); | ||
394 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/ima_read_calib.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/ima_read_calib.m new file mode 100755 index 0000000..dbbc4e0 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/ima_read_calib.m | |||
@@ -0,0 +1,158 @@ | |||
1 | |||
2 | if ~exist('calib_name')|~exist('format_image'), | ||
3 | data_calib; | ||
4 | return; | ||
5 | end; | ||
6 | |||
7 | check_directory; | ||
8 | |||
9 | if ~exist('n_ima'), | ||
10 | data_calib; | ||
11 | return; | ||
12 | end; | ||
13 | |||
14 | check_active_images; | ||
15 | |||
16 | |||
17 | images_read = active_images; | ||
18 | |||
19 | |||
20 | if exist('image_numbers'), | ||
21 | first_num = image_numbers(1); | ||
22 | end; | ||
23 | |||
24 | |||
25 | % Just to fix a minor bug: | ||
26 | if ~exist('first_num'), | ||
27 | first_num = image_numbers(1); | ||
28 | end; | ||
29 | |||
30 | |||
31 | image_numbers = first_num:n_ima-1+first_num; | ||
32 | |||
33 | no_image_file = 0; | ||
34 | |||
35 | i = 1; | ||
36 | |||
37 | while (i <= n_ima), % & (~no_image_file), | ||
38 | |||
39 | if active_images(i), | ||
40 | |||
41 | %fprintf(1,'Loading image %d...\n',i); | ||
42 | |||
43 | if ~type_numbering, | ||
44 | number_ext = num2str(image_numbers(i)); | ||
45 | else | ||
46 | number_ext = sprintf(['%.' num2str(N_slots) 'd'],image_numbers(i)); | ||
47 | end; | ||
48 | |||
49 | ima_name = [calib_name number_ext '.' format_image]; | ||
50 | |||
51 | if i == ind_active(1), | ||
52 | fprintf(1,'Loading image '); | ||
53 | end; | ||
54 | |||
55 | if exist(ima_name), | ||
56 | |||
57 | fprintf(1,'%d...',i); | ||
58 | |||
59 | if format_image(1) == 'p', | ||
60 | if format_image(2) == 'p', | ||
61 | Ii = double(loadppm(ima_name)); | ||
62 | else | ||
63 | Ii = double(loadpgm(ima_name)); | ||
64 | end; | ||
65 | else | ||
66 | if format_image(1) == 'r', | ||
67 | Ii = readras(ima_name); | ||
68 | else | ||
69 | Ii = double(imread(ima_name)); | ||
70 | end; | ||
71 | end; | ||
72 | |||
73 | |||
74 | if size(Ii,3)>1, | ||
75 | Ii = Ii(:,:,2); | ||
76 | end; | ||
77 | |||
78 | eval(['I_' num2str(i) ' = Ii;']); | ||
79 | |||
80 | else | ||
81 | |||
82 | fprintf(1,'%d...no image...',i); | ||
83 | |||
84 | images_read(i) = 0; | ||
85 | |||
86 | %no_image_file = 1; | ||
87 | |||
88 | end; | ||
89 | |||
90 | end; | ||
91 | |||
92 | i = i+1; | ||
93 | |||
94 | end; | ||
95 | |||
96 | |||
97 | ind_read = find(images_read); | ||
98 | |||
99 | |||
100 | |||
101 | |||
102 | if isempty(ind_read), | ||
103 | |||
104 | fprintf(1,'\nWARNING! No image were read\n'); | ||
105 | |||
106 | no_image_file = 1; | ||
107 | |||
108 | |||
109 | else | ||
110 | |||
111 | |||
112 | %fprintf(1,'\nWARNING! Every exsisting image in the directory is set active.\n'); | ||
113 | |||
114 | |||
115 | if no_image_file, | ||
116 | |||
117 | %fprintf(1,'WARNING! Some images were not read properly\n'); | ||
118 | |||
119 | end; | ||
120 | |||
121 | |||
122 | fprintf(1,'\n'); | ||
123 | |||
124 | if size(I_1,1)~=480, | ||
125 | small_calib_image = 1; | ||
126 | else | ||
127 | small_calib_image = 0; | ||
128 | end; | ||
129 | |||
130 | [Hcal,Wcal] = size(I_1); % size of the calibration image | ||
131 | |||
132 | [ny,nx] = size(I_1); | ||
133 | |||
134 | clickname = []; | ||
135 | |||
136 | map = gray(256); | ||
137 | |||
138 | %string_save = 'save calib_data n_ima type_numbering N_slots image_numbers format_image calib_name Hcal Wcal nx ny map small_calib_image'; | ||
139 | |||
140 | %eval(string_save); | ||
141 | |||
142 | disp('done'); | ||
143 | %click_calib; | ||
144 | |||
145 | end; | ||
146 | |||
147 | if ~exist('map'), map = gray(256); end; | ||
148 | |||
149 | active_images = images_read; | ||
150 | |||
151 | % Show all the calibration images: | ||
152 | |||
153 | |||
154 | if ~isempty(ind_read), | ||
155 | |||
156 | mosaic; | ||
157 | |||
158 | end; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/init_intrinsic_param.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/init_intrinsic_param.m new file mode 100755 index 0000000..94a5240 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/init_intrinsic_param.m | |||
@@ -0,0 +1,158 @@ | |||
1 | %init_intrinsic_param | ||
2 | % | ||
3 | %Initialization of the intrinsic parameters. | ||
4 | %Runs as a script. | ||
5 | % | ||
6 | %INPUT: x_1,x_2,x_3,...: Feature locations on the images | ||
7 | % X_1,X_2,X_3,...: Corresponding grid coordinates | ||
8 | % | ||
9 | %OUTPUT: fc: Camera focal length | ||
10 | % cc: Principal point coordinates | ||
11 | % kc: Distortion coefficients | ||
12 | % alpha_c: skew coefficient | ||
13 | % KK: The camera matrix (containing fc, cc and alpha_c) | ||
14 | % | ||
15 | %Method: Computes the planar homographies H_1, H_2, H_3, ... and computes | ||
16 | % the focal length fc from orthogonal vanishing points constraint. | ||
17 | % The principal point cc is assumed at the center of the image. | ||
18 | % Assumes no image distortion (kc = [0;0;0;0]) | ||
19 | % | ||
20 | %Note: The row vector active_images consists of zeros and ones. To deactivate an image, set the | ||
21 | % corresponding entry in the active_images vector to zero. | ||
22 | % | ||
23 | % | ||
24 | %Important function called within that program: | ||
25 | % | ||
26 | %compute_homography.m: Computes the planar homography between points on the grid in 3D, and the image plane. | ||
27 | % | ||
28 | % | ||
29 | %VERY IMPORTANT: This function works only with 2D rigs. | ||
30 | %In the future, a more general function will be there (working with 3D rigs as well). | ||
31 | |||
32 | |||
33 | |||
34 | check_active_images; | ||
35 | |||
36 | if ~exist(['x_' num2str(ind_active(1)) ]), | ||
37 | click_calib; | ||
38 | end; | ||
39 | |||
40 | |||
41 | fprintf(1,'\nInitialization of the intrinsic parameters - Number of images: %d\n',length(ind_active)); | ||
42 | |||
43 | |||
44 | % Initialize the homographies: | ||
45 | |||
46 | for kk = 1:n_ima, | ||
47 | eval(['x_kk = x_' num2str(kk) ';']); | ||
48 | eval(['X_kk = X_' num2str(kk) ';']); | ||
49 | if (isnan(x_kk(1,1))), | ||
50 | if active_images(kk), | ||
51 | fprintf(1,'WARNING: Cannot calibrate with image %d. Need to extract grid corners first.\n',kk) | ||
52 | fprintf(1,' Set active_images(%d)=1; and run Extract grid corners.\n',kk) | ||
53 | end; | ||
54 | active_images(kk) = 0; | ||
55 | end; | ||
56 | if active_images(kk), | ||
57 | eval(['H_' num2str(kk) ' = compute_homography(x_kk,X_kk(1:2,:));']); | ||
58 | else | ||
59 | eval(['H_' num2str(kk) ' = NaN*ones(3,3);']); | ||
60 | end; | ||
61 | end; | ||
62 | |||
63 | check_active_images; | ||
64 | |||
65 | % initial guess for principal point and distortion: | ||
66 | |||
67 | if ~exist('nx'), [ny,nx] = size(I); end; | ||
68 | |||
69 | c_init = [nx;ny]/2 - 0.5; % initialize at the center of the image | ||
70 | k_init = [0;0;0;0]; % initialize to zero (no distortion) | ||
71 | |||
72 | |||
73 | |||
74 | % Compute explicitely the focal length using all the (mutually orthogonal) vanishing points | ||
75 | % note: The vanihing points are hidden in the planar collineations H_kk | ||
76 | |||
77 | A = []; | ||
78 | b = []; | ||
79 | |||
80 | % matrix that subtract the principal point: | ||
81 | Sub_cc = [1 0 -c_init(1);0 1 -c_init(2);0 0 1]; | ||
82 | |||
83 | for kk=1:n_ima, | ||
84 | |||
85 | if active_images(kk), | ||
86 | |||
87 | eval(['Hkk = H_' num2str(kk) ';']); | ||
88 | |||
89 | Hkk = Sub_cc * Hkk; | ||
90 | |||
91 | % Extract vanishing points (direct and diagonals): | ||
92 | |||
93 | V_hori_pix = Hkk(:,1); | ||
94 | V_vert_pix = Hkk(:,2); | ||
95 | V_diag1_pix = (Hkk(:,1)+Hkk(:,2))/2; | ||
96 | V_diag2_pix = (Hkk(:,1)-Hkk(:,2))/2; | ||
97 | |||
98 | V_hori_pix = V_hori_pix/norm(V_hori_pix); | ||
99 | V_vert_pix = V_vert_pix/norm(V_vert_pix); | ||
100 | V_diag1_pix = V_diag1_pix/norm(V_diag1_pix); | ||
101 | V_diag2_pix = V_diag2_pix/norm(V_diag2_pix); | ||
102 | |||
103 | a1 = V_hori_pix(1); | ||
104 | b1 = V_hori_pix(2); | ||
105 | c1 = V_hori_pix(3); | ||
106 | |||
107 | a2 = V_vert_pix(1); | ||
108 | b2 = V_vert_pix(2); | ||
109 | c2 = V_vert_pix(3); | ||
110 | |||
111 | a3 = V_diag1_pix(1); | ||
112 | b3 = V_diag1_pix(2); | ||
113 | c3 = V_diag1_pix(3); | ||
114 | |||
115 | a4 = V_diag2_pix(1); | ||
116 | b4 = V_diag2_pix(2); | ||
117 | c4 = V_diag2_pix(3); | ||
118 | |||
119 | A_kk = [a1*a2 b1*b2; | ||
120 | a3*a4 b3*b4]; | ||
121 | |||
122 | b_kk = -[c1*c2;c3*c4]; | ||
123 | |||
124 | |||
125 | A = [A;A_kk]; | ||
126 | b = [b;b_kk]; | ||
127 | |||
128 | end; | ||
129 | |||
130 | end; | ||
131 | |||
132 | |||
133 | % use all the vanishing points to estimate focal length: | ||
134 | |||
135 | f_init = sqrt(abs(1./(inv(A'*A)*A'*b))); % if using a two-focal model for initial guess | ||
136 | |||
137 | alpha_init = 0; | ||
138 | |||
139 | %f_init = sqrt(b'*(sum(A')') / (b'*b)) * ones(2,1); % if single focal length model is used | ||
140 | |||
141 | |||
142 | % Global calibration matrix (initial guess): | ||
143 | |||
144 | KK = [f_init(1) alpha_init*f_init(1) c_init(1);0 f_init(2) c_init(2); 0 0 1]; | ||
145 | inv_KK = inv(KK); | ||
146 | |||
147 | |||
148 | cc = c_init; | ||
149 | fc = f_init; | ||
150 | kc = k_init; | ||
151 | alpha_c = alpha_init; | ||
152 | |||
153 | |||
154 | fprintf(1,'\n\nCalibration parameters after initialization:\n\n'); | ||
155 | fprintf(1,'Focal Length: fc = [ %3.5f %3.5f ]\n',fc); | ||
156 | fprintf(1,'Principal point: cc = [ %3.5f %3.5f ]\n',cc); | ||
157 | fprintf(1,'Skew: alpha_c = [ %3.5f ] => angle of pixel = %3.5f degrees\n',alpha_c,90 - atan(alpha_c)*180/pi); | ||
158 | fprintf(1,'Distortion: kc = [ %3.5f %3.5f %3.5f %3.5f ]\n',kc); | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/is3D.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/is3D.m new file mode 100755 index 0000000..ab00b3d --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/is3D.m | |||
@@ -0,0 +1,19 @@ | |||
1 | function test = is3D(X), | ||
2 | |||
3 | |||
4 | Np = size(X,2); | ||
5 | |||
6 | %% Check for planarity of the structure: | ||
7 | |||
8 | X_mean = mean(X')'; | ||
9 | |||
10 | Y = X - (X_mean*ones(1,Np)); | ||
11 | |||
12 | YY = Y*Y'; | ||
13 | |||
14 | [U,S,V] = svd(YY); | ||
15 | |||
16 | r = S(3,3)/S(2,2); | ||
17 | |||
18 | test = (r > 1e-3); | ||
19 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/loading_calib.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/loading_calib.m new file mode 100755 index 0000000..a0f50d2 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/loading_calib.m | |||
@@ -0,0 +1,10 @@ | |||
1 | if ~exist('Calib_Results.mat'), | ||
2 | fprintf(1,'\nCalibration file Calib_Results.mat not found!\n'); | ||
3 | return; | ||
4 | end; | ||
5 | |||
6 | fprintf(1,'\nLoading calibration results from Calib_Results.mat\n'); | ||
7 | |||
8 | load Calib_Results | ||
9 | |||
10 | fprintf(1,'done\n'); | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/loadinr.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/loadinr.m new file mode 100755 index 0000000..91b6f89 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/loadinr.m | |||
@@ -0,0 +1,52 @@ | |||
1 | %LOADINR Load an INRIMAGE format file | ||
2 | % | ||
3 | % LOADINR(filename, im) | ||
4 | % | ||
5 | % Load an INRIA image format file and return it as a matrix | ||
6 | % | ||
7 | % SEE ALSO: saveinr | ||
8 | % | ||
9 | % Copyright (c) Peter Corke, 1999 Machine Vision Toolbox for Matlab | ||
10 | |||
11 | |||
12 | % Peter Corke 1996 | ||
13 | |||
14 | function im = loadinr(fname, im) | ||
15 | |||
16 | fid = fopen(fname, 'r'); | ||
17 | |||
18 | s = fgets(fid); | ||
19 | if strcmp(s(1:12), '#INRIMAGE-4#') == 0, | ||
20 | error('not INRIMAGE format'); | ||
21 | end | ||
22 | |||
23 | % not very complete, only looks for the X/YDIM keys | ||
24 | while 1, | ||
25 | s = fgets(fid); | ||
26 | n = length(s) - 1; | ||
27 | if s(1) == '#', | ||
28 | break | ||
29 | end | ||
30 | if strcmp(s(1:5), 'XDIM='), | ||
31 | cols = str2num(s(6:n)); | ||
32 | end | ||
33 | if strcmp(s(1:5), 'YDIM='), | ||
34 | rows = str2num(s(6:n)); | ||
35 | end | ||
36 | if strcmp(s(1:4), 'CPU='), | ||
37 | if strcmp(s(5:n), 'sun') == 0, | ||
38 | error('not sun data ordering'); | ||
39 | end | ||
40 | end | ||
41 | |||
42 | end | ||
43 | disp(['INRIMAGE format file ' num2str(rows) ' x ' num2str(cols)]) | ||
44 | |||
45 | % now the binary data | ||
46 | fseek(fid, 256, 'bof'); | ||
47 | [im count] = fread(fid, [cols rows], 'float32'); | ||
48 | im = im'; | ||
49 | if count ~= (rows*cols), | ||
50 | error('file too short'); | ||
51 | end | ||
52 | fclose(fid); | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/loadpgm.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/loadpgm.m new file mode 100755 index 0000000..dfa8b61 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/loadpgm.m | |||
@@ -0,0 +1,89 @@ | |||
1 | %LOADPGM Load a PGM image | ||
2 | % | ||
3 | % I = loadpgm(filename) | ||
4 | % | ||
5 | % Returns a matrix containing the image loaded from the PGM format | ||
6 | % file filename. Handles ASCII (P2) and binary (P5) PGM file formats. | ||
7 | % | ||
8 | % If the filename has no extension, and open fails, a '.pgm' will | ||
9 | % be appended. | ||
10 | % | ||
11 | % | ||
12 | % Copyright (c) Peter Corke, 1999 Machine Vision Toolbox for Matlab | ||
13 | |||
14 | |||
15 | % Peter Corke 1994 | ||
16 | |||
17 | function I = loadpgm(file) | ||
18 | white = [' ' 9 10 13]; % space, tab, lf, cr | ||
19 | white = setstr(white); | ||
20 | |||
21 | fid = fopen(file, 'r'); | ||
22 | if fid < 0, | ||
23 | fid = fopen([file '.pgm'], 'r'); | ||
24 | end | ||
25 | if fid < 0, | ||
26 | error('Couldn''t open file'); | ||
27 | end | ||
28 | |||
29 | magic = fread(fid, 2, 'char'); | ||
30 | while 1 | ||
31 | c = fread(fid,1,'char'); | ||
32 | if c == '#', | ||
33 | fgetl(fid); | ||
34 | elseif ~any(c == white) | ||
35 | fseek(fid, -1, 'cof'); % unputc() | ||
36 | break; | ||
37 | end | ||
38 | end | ||
39 | cols = fscanf(fid, '%d', 1); | ||
40 | while 1 | ||
41 | c = fread(fid,1,'char'); | ||
42 | if c == '#', | ||
43 | fgetl(fid); | ||
44 | elseif ~any(c == white) | ||
45 | fseek(fid, -1, 'cof'); % unputc() | ||
46 | break; | ||
47 | end | ||
48 | end | ||
49 | rows = fscanf(fid, '%d', 1); | ||
50 | while 1 | ||
51 | c = fread(fid,1,'char'); | ||
52 | if c == '#', | ||
53 | fgetl(fid); | ||
54 | elseif ~any(c == white) | ||
55 | fseek(fid, -1, 'cof'); % unputc() | ||
56 | break; | ||
57 | end | ||
58 | end | ||
59 | maxval = fscanf(fid, '%d', 1); | ||
60 | while 1 | ||
61 | c = fread(fid,1,'char'); | ||
62 | if c == '#', | ||
63 | fgetl(fid); | ||
64 | elseif ~any(c == white) | ||
65 | fseek(fid, -1, 'cof'); % unputc() | ||
66 | break; | ||
67 | end | ||
68 | end | ||
69 | if magic(1) == 'P', | ||
70 | if magic(2) == '2', | ||
71 | %disp(['ASCII PGM file ' num2str(rows) ' x ' num2str(cols)]) | ||
72 | I = fscanf(fid, '%d', [cols rows])'; | ||
73 | elseif magic(2) == '5', | ||
74 | %disp(['Binary PGM file ' num2str(rows) ' x ' num2str(cols)]) | ||
75 | if maxval == 1, | ||
76 | fmt = 'unint1'; | ||
77 | elseif maxval == 15, | ||
78 | fmt = 'uint4'; | ||
79 | elseif maxval == 255, | ||
80 | fmt = 'uint8'; | ||
81 | elseif maxval == 2^32-1, | ||
82 | fmt = 'uint32'; | ||
83 | end | ||
84 | I = fread(fid, [cols rows], fmt)'; | ||
85 | else | ||
86 | disp('Not a PGM file'); | ||
87 | end | ||
88 | end | ||
89 | fclose(fid); | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/loadppm.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/loadppm.m new file mode 100755 index 0000000..0c004fc --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/loadppm.m | |||
@@ -0,0 +1,109 @@ | |||
1 | %LOADPPM Load a PPM image | ||
2 | % | ||
3 | % I = loadppm(filename) | ||
4 | % | ||
5 | % Returns a matrix containing the image loaded from the PPM format | ||
6 | % file filename. Handles ASCII (P3) and binary (P6) PPM file formats. | ||
7 | % | ||
8 | % If the filename has no extension, and open fails, a '.ppm' and | ||
9 | % '.pnm' extension will be tried. | ||
10 | % | ||
11 | % SEE ALSO: saveppm loadpgm | ||
12 | % | ||
13 | % Copyright (c) Peter Corke, 1999 Machine Vision Toolbox for Matlab | ||
14 | |||
15 | |||
16 | % Peter Corke 1994 | ||
17 | |||
18 | function I = loadppm(file) | ||
19 | white = [' ' 9 10 13]; % space, tab, lf, cr | ||
20 | white = setstr(white); | ||
21 | |||
22 | fid = fopen(file, 'r'); | ||
23 | if fid < 0, | ||
24 | fid = fopen([file '.ppm'], 'r'); | ||
25 | end | ||
26 | if fid < 0, | ||
27 | fid = fopen([file '.pnm'], 'r'); | ||
28 | end | ||
29 | if fid < 0, | ||
30 | error('Couldn''t open file'); | ||
31 | end | ||
32 | |||
33 | magic = fread(fid, 2, 'char'); | ||
34 | while 1 | ||
35 | c = fread(fid,1,'char'); | ||
36 | if c == '#', | ||
37 | fgetl(fid); | ||
38 | elseif ~any(c == white) | ||
39 | fseek(fid, -1, 'cof'); % unputc() | ||
40 | break; | ||
41 | end | ||
42 | end | ||
43 | cols = fscanf(fid, '%d', 1); | ||
44 | while 1 | ||
45 | c = fread(fid,1,'char'); | ||
46 | if c == '#', | ||
47 | fgetl(fid); | ||
48 | elseif ~any(c == white) | ||
49 | fseek(fid, -1, 'cof'); % unputc() | ||
50 | break; | ||
51 | end | ||
52 | end | ||
53 | rows = fscanf(fid, '%d', 1); | ||
54 | while 1 | ||
55 | c = fread(fid,1,'char'); | ||
56 | if c == '#', | ||
57 | fgetl(fid); | ||
58 | elseif ~any(c == white) | ||
59 | fseek(fid, -1, 'cof'); % unputc() | ||
60 | break; | ||
61 | end | ||
62 | end | ||
63 | maxval = fscanf(fid, '%d', 1); | ||
64 | while 1 | ||
65 | c = fread(fid,1,'char'); | ||
66 | if c == '#', | ||
67 | fgetl(fid); | ||
68 | elseif ~any(c == white) | ||
69 | fseek(fid, -1, 'cof'); % unputc() | ||
70 | break; | ||
71 | end | ||
72 | end | ||
73 | if magic(1) == 'P', | ||
74 | if magic(2) == '3', | ||
75 | %disp(['ASCII PPM file ' num2str(rows) ' x ' num2str(cols)]) | ||
76 | I = fscanf(fid, '%d', [cols*3 rows]); | ||
77 | elseif magic(2) == '6', | ||
78 | %disp(['Binary PPM file ' num2str(rows) ' x ' num2str(cols)]) | ||
79 | if maxval == 1, | ||
80 | fmt = 'unint1'; | ||
81 | elseif maxval == 15, | ||
82 | fmt = 'uint4'; | ||
83 | elseif maxval == 255, | ||
84 | fmt = 'uint8'; | ||
85 | elseif maxval == 2^32-1, | ||
86 | fmt = 'uint32'; | ||
87 | end | ||
88 | I = fread(fid, [cols*3 rows], fmt); | ||
89 | else | ||
90 | disp('Not a PPM file'); | ||
91 | end | ||
92 | end | ||
93 | % | ||
94 | % now the matrix has interleaved columns of R, G, B | ||
95 | % | ||
96 | I = I'; | ||
97 | size(I); | ||
98 | R = I(:,1:3:(cols*3)); | ||
99 | G = I(:,2:3:(cols*3)); | ||
100 | B = I(:,3:3:(cols*3)); | ||
101 | fclose(fid); | ||
102 | |||
103 | |||
104 | I = zeros(rows,cols,3); | ||
105 | I(:,:,1) = R; | ||
106 | I(:,:,2) = G; | ||
107 | I(:,:,3) = B; | ||
108 | I = uint8(I); | ||
109 | \ No newline at end of file | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/mean_std_robust.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/mean_std_robust.m new file mode 100755 index 0000000..0d18a62 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/mean_std_robust.m | |||
@@ -0,0 +1,7 @@ | |||
1 | function [m,s] = mean_std_robust(x); | ||
2 | |||
3 | x = x(:); | ||
4 | |||
5 | m = median(x); | ||
6 | |||
7 | s = median(abs(x - m))*1.4836; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/mosaic.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/mosaic.m new file mode 100755 index 0000000..b056661 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/mosaic.m | |||
@@ -0,0 +1,92 @@ | |||
1 | |||
2 | if ~exist('I_1'), | ||
3 | active_images_save = active_images; | ||
4 | ima_read_calib; | ||
5 | active_images = active_images_save; | ||
6 | check_active_images; | ||
7 | end; | ||
8 | |||
9 | check_active_images; | ||
10 | |||
11 | if isempty(ind_read), | ||
12 | return; | ||
13 | end; | ||
14 | |||
15 | |||
16 | n_col = floor(sqrt(n_ima*nx/ny)); | ||
17 | |||
18 | n_row = ceil(n_ima / n_col); | ||
19 | |||
20 | |||
21 | ker2 = 1; | ||
22 | for ii = 1:n_col, | ||
23 | ker2 = conv(ker2,[1/4 1/2 1/4]); | ||
24 | end; | ||
25 | |||
26 | |||
27 | II = I_1(1:n_col:end,1:n_col:end); | ||
28 | |||
29 | [ny2,nx2] = size(II); | ||
30 | |||
31 | |||
32 | |||
33 | kk_c = 1; | ||
34 | |||
35 | II_mosaic = []; | ||
36 | |||
37 | for jj = 1:n_row, | ||
38 | |||
39 | |||
40 | II_row = []; | ||
41 | |||
42 | for ii = 1:n_col, | ||
43 | |||
44 | if (exist(['I_' num2str(kk_c)])) & (kk_c <= n_ima), | ||
45 | |||
46 | if active_images(kk_c), | ||
47 | eval(['I = I_' num2str(kk_c) ';']); | ||
48 | %I = conv2(conv2(I,ker2,'same'),ker2','same'); % anti-aliasing | ||
49 | I = I(1:n_col:end,1:n_col:end); | ||
50 | else | ||
51 | I = zeros(ny2,nx2); | ||
52 | end; | ||
53 | |||
54 | else | ||
55 | |||
56 | I = zeros(ny2,nx2); | ||
57 | |||
58 | end; | ||
59 | |||
60 | |||
61 | |||
62 | II_row = [II_row I]; | ||
63 | |||
64 | if ii ~= n_col, | ||
65 | |||
66 | II_row = [II_row zeros(ny2,3)]; | ||
67 | |||
68 | end; | ||
69 | |||
70 | |||
71 | kk_c = kk_c + 1; | ||
72 | |||
73 | end; | ||
74 | |||
75 | nn2 = size(II_row,2); | ||
76 | |||
77 | if jj ~= n_row, | ||
78 | II_row = [II_row; zeros(3,nn2)]; | ||
79 | end; | ||
80 | |||
81 | II_mosaic = [II_mosaic ; II_row]; | ||
82 | |||
83 | end; | ||
84 | |||
85 | figure(2); | ||
86 | image(II_mosaic); | ||
87 | colormap(gray(256)); | ||
88 | title('Calibration images'); | ||
89 | set(gca,'Xtick',[]) | ||
90 | set(gca,'Ytick',[]) | ||
91 | axis('image'); | ||
92 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/normalize.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/normalize.m new file mode 100755 index 0000000..6dc7149 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/normalize.m | |||
@@ -0,0 +1,43 @@ | |||
1 | function [xn] = normalize(x_kk,fc,cc,kc,alpha_c), | ||
2 | |||
3 | %normalize | ||
4 | % | ||
5 | %[xn] = normalize(x_kk,fc,cc,kc,alpha_c) | ||
6 | % | ||
7 | %Computes the normalized coordinates xn given the pixel coordinates x_kk | ||
8 | %and the intrinsic camera parameters fc, cc and kc. | ||
9 | % | ||
10 | %INPUT: x_kk: Feature locations on the images | ||
11 | % fc: Camera focal length | ||
12 | % cc: Principal point coordinates | ||
13 | % kc: Distortion coefficients | ||
14 | % alpha_c: Skew coefficient | ||
15 | % | ||
16 | %OUTPUT: xn: Normalized feature locations on the image plane (a 2XN matrix) | ||
17 | % | ||
18 | %Important functions called within that program: | ||
19 | % | ||
20 | %comp_distortion_oulu: undistort pixel coordinates. | ||
21 | |||
22 | if nargin < 5, | ||
23 | alpha_c = 0; | ||
24 | if nargin < 4; | ||
25 | kc = [0;0;0;0]; | ||
26 | if nargin < 3; | ||
27 | cc = [0;0]; | ||
28 | if nargin < 2, | ||
29 | fc = [1;1]; | ||
30 | end; | ||
31 | end; | ||
32 | end; | ||
33 | end; | ||
34 | |||
35 | |||
36 | % First subtract principal point, and divide by the focal length: | ||
37 | temp = (x_kk(2,:) - cc(2))/fc(2); | ||
38 | x_distort = [(x_kk(1,:) - cc(1))/fc(1) - alpha_c*temp;temp]; | ||
39 | |||
40 | |||
41 | %Compensate for lens distortion: | ||
42 | |||
43 | xn = comp_distortion_oulu(x_distort,kc); | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/pgmread.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/pgmread.m new file mode 100755 index 0000000..c96ccb7 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/pgmread.m | |||
@@ -0,0 +1,26 @@ | |||
1 | function img = pgmread(filename) | ||
2 | % function img = pgmread(filename) | ||
3 | % this is my version of pgmread for the pgm file created by XV. | ||
4 | % | ||
5 | % this program also corrects for the shifts in the image from pm file. | ||
6 | |||
7 | fid = fopen(filename,'r'); | ||
8 | fscanf(fid, 'P5\n'); | ||
9 | cmt = '#'; | ||
10 | while findstr(cmt, '#'), | ||
11 | cmt = fgets(fid); | ||
12 | if length(findstr(cmt, '#')) ~= 1, | ||
13 | YX = sscanf(cmt, '%d %d'); | ||
14 | y = YX(1); x = YX(2); | ||
15 | end | ||
16 | end | ||
17 | |||
18 | %fgets(fid); | ||
19 | |||
20 | %img = fscanf(fid,'%d',size); | ||
21 | %img = img'; | ||
22 | |||
23 | img = fread(fid,[y,x],'uint8'); | ||
24 | img = img'; | ||
25 | fclose(fid); | ||
26 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/project2_oulu.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/project2_oulu.m new file mode 100755 index 0000000..c5c4a34 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/project2_oulu.m | |||
@@ -0,0 +1,53 @@ | |||
1 | function [x] = project2_oulu(X,R,T,f,t,k) | ||
2 | %PROJECT Subsidiary to calib | ||
3 | |||
4 | % (c) Pietro Perona -- March 24, 1994 | ||
5 | % California Institute of Technology | ||
6 | % Pasadena, CA | ||
7 | % | ||
8 | % Renamed because project exists in matlab 5.2!!! | ||
9 | % Now uses the more elaborate intrinsic model from Oulu | ||
10 | |||
11 | |||
12 | |||
13 | [m,n] = size(X); | ||
14 | |||
15 | Y = R*X + T*ones(1,n); | ||
16 | Z = Y(3,:); | ||
17 | |||
18 | f = f(:); %% make a column vector | ||
19 | if length(f)==1, | ||
20 | f = [f f]'; | ||
21 | end; | ||
22 | |||
23 | x = (Y(1:2,:) ./ (ones(2,1) * Z)) ; | ||
24 | |||
25 | |||
26 | radius_2 = x(1,:).^2 + x(2,:).^2; | ||
27 | |||
28 | if length(k) > 1, | ||
29 | |||
30 | radial_distortion = 1 + ones(2,1) * ((k(1) * radius_2) + (k(2) * radius_2.^2)); | ||
31 | |||
32 | if length(k) < 4, | ||
33 | |||
34 | delta_x = zeros(2,n); | ||
35 | |||
36 | else | ||
37 | |||
38 | delta_x = [2*k(3)*x(1,:).*x(2,:) + k(4)*(radius_2 + 2*x(1,:).^2) ; | ||
39 | k(3) * (radius_2 + 2*x(2,:).^2)+2*k(4)*x(1,:).*x(2,:)]; | ||
40 | |||
41 | end; | ||
42 | |||
43 | |||
44 | else | ||
45 | |||
46 | radial_distortion = 1 + ones(2,1) * ((k(1) * radius_2)); | ||
47 | |||
48 | delta_x = zeros(2,n); | ||
49 | |||
50 | end; | ||
51 | |||
52 | |||
53 | x = (x .* radial_distortion + delta_x).* (f * ones(1,n)) + t*ones(1,n); | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/project_points.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/project_points.m new file mode 100755 index 0000000..1823490 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/project_points.m | |||
@@ -0,0 +1,276 @@ | |||
1 | function [xp,dxpdom,dxpdT,dxpdf,dxpdc,dxpdk] = project_points(X,om,T,f,c,k) | ||
2 | |||
3 | %project_points.m | ||
4 | % | ||
5 | %[xp,dxpdom,dxpdT,dxpdf,dxpdc,dxpdk] = project_points(X,om,T,f,c,k) | ||
6 | % | ||
7 | %Projects a 3D structure onto the image plane. | ||
8 | % | ||
9 | %INPUT: X: 3D structure in the world coordinate frame (3xN matrix for N points) | ||
10 | % (om,T): Rigid motion parameters between world coordinate frame and camera reference frame | ||
11 | % om: rotation vector (3x1 vector); T: translation vector (3x1 vector) | ||
12 | % f: camera focal length in units of horizontal and vertical pixel units (2x1 vector) | ||
13 | % c: principal point location in pixel units (2x1 vector) | ||
14 | % k: Distortion coefficients (radial and tangential) (4x1 vector) | ||
15 | % | ||
16 | %OUTPUT: xp: Projected pixel coordinates (2xN matrix for N points) | ||
17 | % dxpdom: Derivative of xp with respect to om ((2N)x3 matrix) | ||
18 | % dxpdT: Derivative of xp with respect to T ((2N)x3 matrix) | ||
19 | % dxpdf: Derivative of xp with respect to f ((2N)x2 matrix) | ||
20 | % dxpdc: Derivative of xp with respect to c ((2N)x2 matrix) | ||
21 | % dxpdk: Derivative of xp with respect to k ((2N)x4 matrix) | ||
22 | % | ||
23 | %Definitions: | ||
24 | %Let P be a point in 3D of coordinates X in the world reference frame (stored in the matrix X) | ||
25 | %The coordinate vector of P in the camera reference frame is: Xc = R*X + T | ||
26 | %where R is the rotation matrix corresponding to the rotation vector om: R = rodrigues(om); | ||
27 | %call x, y and z the 3 coordinates of Xc: x = Xc(1); y = Xc(2); z = Xc(3); | ||
28 | %The pinehole projection coordinates of P is [a;b] where a=x/z and b=y/z. | ||
29 | %call r^2 = a^2 + b^2. | ||
30 | %The distorted point coordinates are: xd = [xx;yy] where: | ||
31 | % | ||
32 | %xx = a * (1 + kc(1)*r^2 + kc(2)*r^4) + 2*kc(3)*a*b + kc(4)*(r^2 + 2*a^2); | ||
33 | %yy = b * (1 + kc(1)*r^2 + kc(2)*r^4) + kc(3)*(r^2 + 2*b^2) + 2*kc(4)*a*b; | ||
34 | % | ||
35 | %The left terms correspond to radial distortion, the right terms correspond to tangential distortion | ||
36 | % | ||
37 | %Fianlly, convertion into pixel coordinates: The final pixel coordinates vector xp=[xxp;yyp] where: | ||
38 | % | ||
39 | %xxp = f(1)*xx + c(1) | ||
40 | %yyp = f(2)*yy + c(2) | ||
41 | % | ||
42 | % | ||
43 | %NOTE: About 90 percent of the code takes care fo computing the Jacobian matrices | ||
44 | % | ||
45 | % | ||
46 | %Important function called within that program: | ||
47 | % | ||
48 | %rodrigues.m: Computes the rotation matrix corresponding to a rotation vector | ||
49 | % | ||
50 | %rigid_motion.m: Computes the rigid motion transformation of a given structure | ||
51 | |||
52 | |||
53 | |||
54 | if nargin < 6, | ||
55 | k = zeros(4,1); | ||
56 | if nargin < 5, | ||
57 | c = zeros(2,1); | ||
58 | if nargin < 4, | ||
59 | f = ones(2,1); | ||
60 | if nargin < 3, | ||
61 | T = zeros(3,1); | ||
62 | if nargin < 2, | ||
63 | om = zeros(3,1); | ||
64 | if nargin < 1, | ||
65 | error('Need at least a 3D structure to project (in project_points.m)'); | ||
66 | return; | ||
67 | end; | ||
68 | end; | ||
69 | end; | ||
70 | end; | ||
71 | end; | ||
72 | end; | ||
73 | |||
74 | |||
75 | [m,n] = size(X); | ||
76 | |||
77 | [Y,dYdom,dYdT] = rigid_motion(X,om,T); | ||
78 | |||
79 | |||
80 | inv_Z = 1./Y(3,:); | ||
81 | |||
82 | x = (Y(1:2,:) .* (ones(2,1) * inv_Z)) ; | ||
83 | |||
84 | |||
85 | bb = (-x(1,:) .* inv_Z)'*ones(1,3); | ||
86 | cc = (-x(2,:) .* inv_Z)'*ones(1,3); | ||
87 | |||
88 | |||
89 | dxdom = zeros(2*n,3); | ||
90 | dxdom(1:2:end,:) = ((inv_Z')*ones(1,3)) .* dYdom(1:3:end,:) + bb .* dYdom(3:3:end,:); | ||
91 | dxdom(2:2:end,:) = ((inv_Z')*ones(1,3)) .* dYdom(2:3:end,:) + cc .* dYdom(3:3:end,:); | ||
92 | |||
93 | dxdT = zeros(2*n,3); | ||
94 | dxdT(1:2:end,:) = ((inv_Z')*ones(1,3)) .* dYdT(1:3:end,:) + bb .* dYdT(3:3:end,:); | ||
95 | dxdT(2:2:end,:) = ((inv_Z')*ones(1,3)) .* dYdT(2:3:end,:) + cc .* dYdT(3:3:end,:); | ||
96 | |||
97 | |||
98 | % Add distortion: | ||
99 | |||
100 | r2 = x(1,:).^2 + x(2,:).^2; | ||
101 | |||
102 | |||
103 | |||
104 | dr2dom = 2*((x(1,:)')*ones(1,3)) .* dxdom(1:2:end,:) + 2*((x(2,:)')*ones(1,3)) .* dxdom(2:2:end,:); | ||
105 | dr2dT = 2*((x(1,:)')*ones(1,3)) .* dxdT(1:2:end,:) + 2*((x(2,:)')*ones(1,3)) .* dxdT(2:2:end,:); | ||
106 | |||
107 | |||
108 | r4 = r2.^2; | ||
109 | |||
110 | dr4dom = 2*((r2')*ones(1,3)) .* dr2dom; | ||
111 | dr4dT = 2*((r2')*ones(1,3)) .* dr2dT; | ||
112 | |||
113 | |||
114 | % Radial distortion: | ||
115 | |||
116 | cdist = 1 + k(1) * r2 + k(2) * r4; | ||
117 | |||
118 | dcdistdom = k(1) * dr2dom + k(2) * dr4dom; | ||
119 | dcdistdT = k(1) * dr2dT+ k(2) * dr4dT; | ||
120 | dcdistdk = [ r2' r4' zeros(n,2)]; | ||
121 | |||
122 | |||
123 | xd1 = x .* (ones(2,1)*cdist); | ||
124 | |||
125 | dxd1dom = zeros(2*n,3); | ||
126 | dxd1dom(1:2:end,:) = (x(1,:)'*ones(1,3)) .* dcdistdom; | ||
127 | dxd1dom(2:2:end,:) = (x(2,:)'*ones(1,3)) .* dcdistdom; | ||
128 | coeff = (reshape([cdist;cdist],2*n,1)*ones(1,3)); | ||
129 | dxd1dom = dxd1dom + coeff.* dxdom; | ||
130 | |||
131 | dxd1dT = zeros(2*n,3); | ||
132 | dxd1dT(1:2:end,:) = (x(1,:)'*ones(1,3)) .* dcdistdT; | ||
133 | dxd1dT(2:2:end,:) = (x(2,:)'*ones(1,3)) .* dcdistdT; | ||
134 | dxd1dT = dxd1dT + coeff.* dxdT; | ||
135 | |||
136 | dxd1dk = zeros(2*n,4); | ||
137 | dxd1dk(1:2:end,:) = (x(1,:)'*ones(1,4)) .* dcdistdk; | ||
138 | dxd1dk(2:2:end,:) = (x(2,:)'*ones(1,4)) .* dcdistdk; | ||
139 | |||
140 | |||
141 | |||
142 | % tangential distortion: | ||
143 | |||
144 | a1 = 2.*x(1,:).*x(2,:); | ||
145 | a2 = r2 + 2*x(1,:).^2; | ||
146 | a3 = r2 + 2*x(2,:).^2; | ||
147 | |||
148 | delta_x = [k(3)*a1 + k(4)*a2 ; | ||
149 | k(3) * a3 + k(4)*a1]; | ||
150 | |||
151 | |||
152 | ddelta_xdx = zeros(2*n,2*n); | ||
153 | aa = (2*k(3)*x(2,:)+6*k(4)*x(1,:))'*ones(1,3); | ||
154 | bb = (2*k(3)*x(1,:)+2*k(4)*x(2,:))'*ones(1,3); | ||
155 | cc = (6*k(3)*x(2,:)+2*k(4)*x(1,:))'*ones(1,3); | ||
156 | |||
157 | ddelta_xdom = zeros(2*n,3); | ||
158 | ddelta_xdom(1:2:end,:) = aa .* dxdom(1:2:end,:) + bb .* dxdom(2:2:end,:); | ||
159 | ddelta_xdom(2:2:end,:) = bb .* dxdom(1:2:end,:) + cc .* dxdom(2:2:end,:); | ||
160 | |||
161 | ddelta_xdT = zeros(2*n,3); | ||
162 | ddelta_xdT(1:2:end,:) = aa .* dxdT(1:2:end,:) + bb .* dxdT(2:2:end,:); | ||
163 | ddelta_xdT(2:2:end,:) = bb .* dxdT(1:2:end,:) + cc .* dxdT(2:2:end,:); | ||
164 | |||
165 | ddelta_xdk = zeros(2*n,4); | ||
166 | ddelta_xdk(1:2:end,3) = a1'; | ||
167 | ddelta_xdk(1:2:end,4) = a2'; | ||
168 | ddelta_xdk(2:2:end,3) = a3'; | ||
169 | ddelta_xdk(2:2:end,4) = a1'; | ||
170 | |||
171 | |||
172 | |||
173 | xd2 = xd1 + delta_x; | ||
174 | |||
175 | dxd2dom = dxd1dom + ddelta_xdom ; | ||
176 | dxd2dT = dxd1dT + ddelta_xdT; | ||
177 | dxd2dk = dxd1dk + ddelta_xdk ; | ||
178 | |||
179 | |||
180 | % Pixel coordinates: | ||
181 | |||
182 | xp = xd2 .* (f * ones(1,n)) + c*ones(1,n); | ||
183 | |||
184 | coeff = reshape(f*ones(1,n),2*n,1); | ||
185 | |||
186 | dxpdom = (coeff*ones(1,3)) .* dxd2dom; | ||
187 | dxpdT = (coeff*ones(1,3)) .* dxd2dT; | ||
188 | dxpdk = (coeff*ones(1,4)) .* dxd2dk; | ||
189 | |||
190 | dxpdf = zeros(2*n,2); | ||
191 | dxpdf(1:2:end,1) = xd2(1,:)'; | ||
192 | dxpdf(2:2:end,2) = xd2(2,:)'; | ||
193 | |||
194 | dxpdc = zeros(2*n,2); | ||
195 | dxpdc(1:2:end,1) = ones(n,1); | ||
196 | dxpdc(2:2:end,2) = ones(n,1); | ||
197 | |||
198 | |||
199 | return; | ||
200 | |||
201 | % Test of the Jacobians: | ||
202 | |||
203 | n = 10; | ||
204 | |||
205 | X = 10*randn(3,n); | ||
206 | om = randn(3,1); | ||
207 | T = [10*randn(2,1);40]; | ||
208 | f = 1000*rand(2,1); | ||
209 | c = 1000*randn(2,1); | ||
210 | k = 0.5*randn(4,1); | ||
211 | |||
212 | |||
213 | [x,dxdom,dxdT,dxdf,dxdc,dxdk] = project_points(X,om,T,f,c,k); | ||
214 | |||
215 | |||
216 | % Test on om: NOT OK | ||
217 | |||
218 | dom = 0.000000001 * norm(om)*randn(3,1); | ||
219 | om2 = om + dom; | ||
220 | |||
221 | [x2] = project_points(X,om2,T,f,c,k); | ||
222 | |||
223 | x_pred = x + reshape(dxdom * dom,2,n); | ||
224 | |||
225 | |||
226 | norm(x2-x)/norm(x2 - x_pred) | ||
227 | |||
228 | |||
229 | % Test on T: OK!! | ||
230 | |||
231 | dT = 0.0001 * norm(T)*randn(3,1); | ||
232 | T2 = T + dT; | ||
233 | |||
234 | [x2] = project_points(X,om,T2,f,c,k); | ||
235 | |||
236 | x_pred = x + reshape(dxdT * dT,2,n); | ||
237 | |||
238 | |||
239 | norm(x2-x)/norm(x2 - x_pred) | ||
240 | |||
241 | |||
242 | |||
243 | % Test on f: OK!! | ||
244 | |||
245 | df = 0.001 * norm(f)*randn(2,1); | ||
246 | f2 = f + df; | ||
247 | |||
248 | [x2] = project_points(X,om,T,f2,c,k); | ||
249 | |||
250 | x_pred = x + reshape(dxdf * df,2,n); | ||
251 | |||
252 | |||
253 | norm(x2-x)/norm(x2 - x_pred) | ||
254 | |||
255 | |||
256 | % Test on c: OK!! | ||
257 | |||
258 | dc = 0.01 * norm(c)*randn(2,1); | ||
259 | c2 = c + dc; | ||
260 | |||
261 | [x2] = project_points(X,om,T,f,c2,k); | ||
262 | |||
263 | x_pred = x + reshape(dxdc * dc,2,n); | ||
264 | |||
265 | norm(x2-x)/norm(x2 - x_pred) | ||
266 | |||
267 | % Test on k: OK!! | ||
268 | |||
269 | dk = 0.001 * norm(4)*randn(4,1); | ||
270 | k2 = k + dk; | ||
271 | |||
272 | [x2] = project_points(X,om,T,f,c,k2); | ||
273 | |||
274 | x_pred = x + reshape(dxdk * dk,2,n); | ||
275 | |||
276 | norm(x2-x)/norm(x2 - x_pred) | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/project_points2.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/project_points2.m new file mode 100755 index 0000000..5bb1b91 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/project_points2.m | |||
@@ -0,0 +1,312 @@ | |||
1 | function [xp,dxpdom,dxpdT,dxpdf,dxpdc,dxpdk,dxpdalpha] = project_points2(X,om,T,f,c,k,alpha) | ||
2 | |||
3 | %project_points.m | ||
4 | % | ||
5 | %[xp,dxpdom,dxpdT,dxpdf,dxpdc,dxpdk] = project_points2(X,om,T,f,c,k,alpha) | ||
6 | % | ||
7 | %Projects a 3D structure onto the image plane. | ||
8 | % | ||
9 | %INPUT: X: 3D structure in the world coordinate frame (3xN matrix for N points) | ||
10 | % (om,T): Rigid motion parameters between world coordinate frame and camera reference frame | ||
11 | % om: rotation vector (3x1 vector); T: translation vector (3x1 vector) | ||
12 | % f: camera focal length in units of horizontal and vertical pixel units (2x1 vector) | ||
13 | % c: principal point location in pixel units (2x1 vector) | ||
14 | % k: Distortion coefficients (radial and tangential) (4x1 vector) | ||
15 | % alpha: Skew coefficient between x and y pixel (alpha = 0 <=> square pixels) | ||
16 | % | ||
17 | %OUTPUT: xp: Projected pixel coordinates (2xN matrix for N points) | ||
18 | % dxpdom: Derivative of xp with respect to om ((2N)x3 matrix) | ||
19 | % dxpdT: Derivative of xp with respect to T ((2N)x3 matrix) | ||
20 | % dxpdf: Derivative of xp with respect to f ((2N)x2 matrix) | ||
21 | % dxpdc: Derivative of xp with respect to c ((2N)x2 matrix) | ||
22 | % dxpdk: Derivative of xp with respect to k ((2N)x4 matrix) | ||
23 | % | ||
24 | %Definitions: | ||
25 | %Let P be a point in 3D of coordinates X in the world reference frame (stored in the matrix X) | ||
26 | %The coordinate vector of P in the camera reference frame is: Xc = R*X + T | ||
27 | %where R is the rotation matrix corresponding to the rotation vector om: R = rodrigues(om); | ||
28 | %call x, y and z the 3 coordinates of Xc: x = Xc(1); y = Xc(2); z = Xc(3); | ||
29 | %The pinehole projection coordinates of P is [a;b] where a=x/z and b=y/z. | ||
30 | %call r^2 = a^2 + b^2. | ||
31 | %The distorted point coordinates are: xd = [xx;yy] where: | ||
32 | % | ||
33 | %xx = a * (1 + kc(1)*r^2 + kc(2)*r^4) + 2*kc(3)*a*b + kc(4)*(r^2 + 2*a^2); | ||
34 | %yy = b * (1 + kc(1)*r^2 + kc(2)*r^4) + kc(3)*(r^2 + 2*b^2) + 2*kc(4)*a*b; | ||
35 | % | ||
36 | %The left terms correspond to radial distortion, the right terms correspond to tangential distortion | ||
37 | % | ||
38 | %Finally, convertion into pixel coordinates: The final pixel coordinates vector xp=[xxp;yyp] where: | ||
39 | % | ||
40 | %xxp = f(1)*(xx + alpha*yy) + c(1) | ||
41 | %yyp = f(2)*yy + c(2) | ||
42 | % | ||
43 | % | ||
44 | %NOTE: About 90 percent of the code takes care fo computing the Jacobian matrices | ||
45 | % | ||
46 | % | ||
47 | %Important function called within that program: | ||
48 | % | ||
49 | %rodrigues.m: Computes the rotation matrix corresponding to a rotation vector | ||
50 | % | ||
51 | %rigid_motion.m: Computes the rigid motion transformation of a given structure | ||
52 | |||
53 | |||
54 | if nargin < 7, | ||
55 | alpha = 0; | ||
56 | if nargin < 6, | ||
57 | k = zeros(4,1); | ||
58 | if nargin < 5, | ||
59 | c = zeros(2,1); | ||
60 | if nargin < 4, | ||
61 | f = ones(2,1); | ||
62 | if nargin < 3, | ||
63 | T = zeros(3,1); | ||
64 | if nargin < 2, | ||
65 | om = zeros(3,1); | ||
66 | if nargin < 1, | ||
67 | error('Need at least a 3D structure to project (in project_points.m)'); | ||
68 | return; | ||
69 | end; | ||
70 | end; | ||
71 | end; | ||
72 | end; | ||
73 | end; | ||
74 | end; | ||
75 | end; | ||
76 | |||
77 | |||
78 | [m,n] = size(X); | ||
79 | |||
80 | [Y,dYdom,dYdT] = rigid_motion(X,om,T); | ||
81 | |||
82 | |||
83 | inv_Z = 1./Y(3,:); | ||
84 | |||
85 | x = (Y(1:2,:) .* (ones(2,1) * inv_Z)) ; | ||
86 | |||
87 | |||
88 | bb = (-x(1,:) .* inv_Z)'*ones(1,3); | ||
89 | cc = (-x(2,:) .* inv_Z)'*ones(1,3); | ||
90 | |||
91 | |||
92 | dxdom = zeros(2*n,3); | ||
93 | dxdom(1:2:end,:) = ((inv_Z')*ones(1,3)) .* dYdom(1:3:end,:) + bb .* dYdom(3:3:end,:); | ||
94 | dxdom(2:2:end,:) = ((inv_Z')*ones(1,3)) .* dYdom(2:3:end,:) + cc .* dYdom(3:3:end,:); | ||
95 | |||
96 | dxdT = zeros(2*n,3); | ||
97 | dxdT(1:2:end,:) = ((inv_Z')*ones(1,3)) .* dYdT(1:3:end,:) + bb .* dYdT(3:3:end,:); | ||
98 | dxdT(2:2:end,:) = ((inv_Z')*ones(1,3)) .* dYdT(2:3:end,:) + cc .* dYdT(3:3:end,:); | ||
99 | |||
100 | |||
101 | % Add distortion: | ||
102 | |||
103 | r2 = x(1,:).^2 + x(2,:).^2; | ||
104 | |||
105 | |||
106 | |||
107 | dr2dom = 2*((x(1,:)')*ones(1,3)) .* dxdom(1:2:end,:) + 2*((x(2,:)')*ones(1,3)) .* dxdom(2:2:end,:); | ||
108 | dr2dT = 2*((x(1,:)')*ones(1,3)) .* dxdT(1:2:end,:) + 2*((x(2,:)')*ones(1,3)) .* dxdT(2:2:end,:); | ||
109 | |||
110 | |||
111 | r4 = r2.^2; | ||
112 | |||
113 | dr4dom = 2*((r2')*ones(1,3)) .* dr2dom; | ||
114 | dr4dT = 2*((r2')*ones(1,3)) .* dr2dT; | ||
115 | |||
116 | |||
117 | % Radial distortion: | ||
118 | |||
119 | cdist = 1 + k(1) * r2 + k(2) * r4; | ||
120 | |||
121 | dcdistdom = k(1) * dr2dom + k(2) * dr4dom; | ||
122 | dcdistdT = k(1) * dr2dT+ k(2) * dr4dT; | ||
123 | dcdistdk = [ r2' r4' zeros(n,2)]; | ||
124 | |||
125 | |||
126 | xd1 = x .* (ones(2,1)*cdist); | ||
127 | |||
128 | dxd1dom = zeros(2*n,3); | ||
129 | dxd1dom(1:2:end,:) = (x(1,:)'*ones(1,3)) .* dcdistdom; | ||
130 | dxd1dom(2:2:end,:) = (x(2,:)'*ones(1,3)) .* dcdistdom; | ||
131 | coeff = (reshape([cdist;cdist],2*n,1)*ones(1,3)); | ||
132 | dxd1dom = dxd1dom + coeff.* dxdom; | ||
133 | |||
134 | dxd1dT = zeros(2*n,3); | ||
135 | dxd1dT(1:2:end,:) = (x(1,:)'*ones(1,3)) .* dcdistdT; | ||
136 | dxd1dT(2:2:end,:) = (x(2,:)'*ones(1,3)) .* dcdistdT; | ||
137 | dxd1dT = dxd1dT + coeff.* dxdT; | ||
138 | |||
139 | dxd1dk = zeros(2*n,4); | ||
140 | dxd1dk(1:2:end,:) = (x(1,:)'*ones(1,4)) .* dcdistdk; | ||
141 | dxd1dk(2:2:end,:) = (x(2,:)'*ones(1,4)) .* dcdistdk; | ||
142 | |||
143 | |||
144 | |||
145 | % tangential distortion: | ||
146 | |||
147 | a1 = 2.*x(1,:).*x(2,:); | ||
148 | a2 = r2 + 2*x(1,:).^2; | ||
149 | a3 = r2 + 2*x(2,:).^2; | ||
150 | |||
151 | delta_x = [k(3)*a1 + k(4)*a2 ; | ||
152 | k(3) * a3 + k(4)*a1]; | ||
153 | |||
154 | |||
155 | ddelta_xdx = zeros(2*n,2*n); | ||
156 | aa = (2*k(3)*x(2,:)+6*k(4)*x(1,:))'*ones(1,3); | ||
157 | bb = (2*k(3)*x(1,:)+2*k(4)*x(2,:))'*ones(1,3); | ||
158 | cc = (6*k(3)*x(2,:)+2*k(4)*x(1,:))'*ones(1,3); | ||
159 | |||
160 | ddelta_xdom = zeros(2*n,3); | ||
161 | ddelta_xdom(1:2:end,:) = aa .* dxdom(1:2:end,:) + bb .* dxdom(2:2:end,:); | ||
162 | ddelta_xdom(2:2:end,:) = bb .* dxdom(1:2:end,:) + cc .* dxdom(2:2:end,:); | ||
163 | |||
164 | ddelta_xdT = zeros(2*n,3); | ||
165 | ddelta_xdT(1:2:end,:) = aa .* dxdT(1:2:end,:) + bb .* dxdT(2:2:end,:); | ||
166 | ddelta_xdT(2:2:end,:) = bb .* dxdT(1:2:end,:) + cc .* dxdT(2:2:end,:); | ||
167 | |||
168 | ddelta_xdk = zeros(2*n,4); | ||
169 | ddelta_xdk(1:2:end,3) = a1'; | ||
170 | ddelta_xdk(1:2:end,4) = a2'; | ||
171 | ddelta_xdk(2:2:end,3) = a3'; | ||
172 | ddelta_xdk(2:2:end,4) = a1'; | ||
173 | |||
174 | |||
175 | |||
176 | xd2 = xd1 + delta_x; | ||
177 | |||
178 | dxd2dom = dxd1dom + ddelta_xdom ; | ||
179 | dxd2dT = dxd1dT + ddelta_xdT; | ||
180 | dxd2dk = dxd1dk + ddelta_xdk ; | ||
181 | |||
182 | |||
183 | % Add Skew: | ||
184 | |||
185 | xd3 = [xd2(1,:) + alpha*xd2(2,:);xd2(2,:)]; | ||
186 | |||
187 | % Compute: dxd3dom, dxd3dT, dxd3dk, dxd3dalpha | ||
188 | |||
189 | dxd3dom = zeros(2*n,3); | ||
190 | dxd3dom(1:2:2*n,:) = dxd2dom(1:2:2*n,:) + alpha*dxd2dom(2:2:2*n,:); | ||
191 | dxd3dom(2:2:2*n,:) = dxd2dom(2:2:2*n,:); | ||
192 | dxd3dT = zeros(2*n,3); | ||
193 | dxd3dT(1:2:2*n,:) = dxd2dT(1:2:2*n,:) + alpha*dxd2dT(2:2:2*n,:); | ||
194 | dxd3dT(2:2:2*n,:) = dxd2dT(2:2:2*n,:); | ||
195 | dxd3dk = zeros(2*n,4); | ||
196 | dxd3dk(1:2:2*n,:) = dxd2dk(1:2:2*n,:) + alpha*dxd2dk(2:2:2*n,:); | ||
197 | dxd3dk(2:2:2*n,:) = dxd2dk(2:2:2*n,:); | ||
198 | dxd3dalpha = zeros(2*n,1); | ||
199 | dxd3dalpha(1:2:2*n,:) = xd2(2,:)'; | ||
200 | |||
201 | |||
202 | |||
203 | % Pixel coordinates: | ||
204 | |||
205 | xp = xd3 .* (f * ones(1,n)) + c*ones(1,n); | ||
206 | |||
207 | coeff = reshape(f*ones(1,n),2*n,1); | ||
208 | |||
209 | dxpdom = (coeff*ones(1,3)) .* dxd3dom; | ||
210 | dxpdT = (coeff*ones(1,3)) .* dxd3dT; | ||
211 | dxpdk = (coeff*ones(1,4)) .* dxd3dk; | ||
212 | dxpdalpha = (coeff) .* dxd3dalpha; | ||
213 | |||
214 | dxpdf = zeros(2*n,2); | ||
215 | dxpdf(1:2:end,1) = xd2(1,:)'; | ||
216 | dxpdf(2:2:end,2) = xd2(2,:)'; | ||
217 | |||
218 | dxpdc = zeros(2*n,2); | ||
219 | dxpdc(1:2:end,1) = ones(n,1); | ||
220 | dxpdc(2:2:end,2) = ones(n,1); | ||
221 | |||
222 | |||
223 | return; | ||
224 | |||
225 | % Test of the Jacobians: | ||
226 | |||
227 | n = 10; | ||
228 | |||
229 | X = 10*randn(3,n); | ||
230 | om = randn(3,1); | ||
231 | T = [10*randn(2,1);40]; | ||
232 | f = 1000*rand(2,1); | ||
233 | c = 1000*randn(2,1); | ||
234 | k = 0.5*randn(4,1); | ||
235 | alpha = 0.01*randn(1,1); | ||
236 | |||
237 | [x,dxdom,dxdT,dxdf,dxdc,dxdk,dxdalpha] = project_points2(X,om,T,f,c,k,alpha); | ||
238 | |||
239 | |||
240 | % Test on om: NOT OK | ||
241 | |||
242 | dom = 0.000000001 * norm(om)*randn(3,1); | ||
243 | om2 = om + dom; | ||
244 | |||
245 | [x2] = project_points2(X,om2,T,f,c,k,alpha); | ||
246 | |||
247 | x_pred = x + reshape(dxdom * dom,2,n); | ||
248 | |||
249 | |||
250 | norm(x2-x)/norm(x2 - x_pred) | ||
251 | |||
252 | |||
253 | % Test on T: OK!! | ||
254 | |||
255 | dT = 0.0001 * norm(T)*randn(3,1); | ||
256 | T2 = T + dT; | ||
257 | |||
258 | [x2] = project_points2(X,om,T2,f,c,k,alpha); | ||
259 | |||
260 | x_pred = x + reshape(dxdT * dT,2,n); | ||
261 | |||
262 | |||
263 | norm(x2-x)/norm(x2 - x_pred) | ||
264 | |||
265 | |||
266 | |||
267 | % Test on f: OK!! | ||
268 | |||
269 | df = 0.001 * norm(f)*randn(2,1); | ||
270 | f2 = f + df; | ||
271 | |||
272 | [x2] = project_points2(X,om,T,f2,c,k,alpha); | ||
273 | |||
274 | x_pred = x + reshape(dxdf * df,2,n); | ||
275 | |||
276 | |||
277 | norm(x2-x)/norm(x2 - x_pred) | ||
278 | |||
279 | |||
280 | % Test on c: OK!! | ||
281 | |||
282 | dc = 0.01 * norm(c)*randn(2,1); | ||
283 | c2 = c + dc; | ||
284 | |||
285 | [x2] = project_points2(X,om,T,f,c2,k,alpha); | ||
286 | |||
287 | x_pred = x + reshape(dxdc * dc,2,n); | ||
288 | |||
289 | norm(x2-x)/norm(x2 - x_pred) | ||
290 | |||
291 | % Test on k: OK!! | ||
292 | |||
293 | dk = 0.001 * norm(k)*randn(4,1); | ||
294 | k2 = k + dk; | ||
295 | |||
296 | [x2] = project_points2(X,om,T,f,c,k2,alpha); | ||
297 | |||
298 | x_pred = x + reshape(dxdk * dk,2,n); | ||
299 | |||
300 | norm(x2-x)/norm(x2 - x_pred) | ||
301 | |||
302 | |||
303 | % Test on alpha: OK!! | ||
304 | |||
305 | dalpha = 0.001 * norm(k)*randn(1,1); | ||
306 | alpha2 = alpha + dalpha; | ||
307 | |||
308 | [x2] = project_points2(X,om,T,f,c,k,alpha2); | ||
309 | |||
310 | x_pred = x + reshape(dxdalpha * dalpha,2,n); | ||
311 | |||
312 | norm(x2-x)/norm(x2 - x_pred) | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/projectedGrid.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/projectedGrid.m new file mode 100755 index 0000000..561a7d0 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/projectedGrid.m | |||
@@ -0,0 +1,24 @@ | |||
1 | function [XX,H] = projectedGrid ( P1, P2, P3, P4 , nx, ny); | ||
2 | |||
3 | % new formalism using homographies | ||
4 | |||
5 | a00 = [P1;1]; | ||
6 | a10 = [P2;1]; | ||
7 | a11 = [P3;1]; | ||
8 | a01 = [P4;1]; | ||
9 | |||
10 | % Compute the planart collineation: | ||
11 | |||
12 | [H] = compute_collineation (a00, a10, a11, a01); | ||
13 | |||
14 | |||
15 | % Build the grid using the planar collineation: | ||
16 | |||
17 | x_l = ((0:(nx-1))'*ones(1,ny))/(nx-1); | ||
18 | y_l = (ones(nx,1)*(0:(ny-1)))/(ny-1); | ||
19 | |||
20 | pts = [x_l(:) y_l(:) ones(nx*ny,1)]'; | ||
21 | |||
22 | XX = H*pts; | ||
23 | |||
24 | XX = XX(1:2,:) ./ (ones(2,1)*XX(3,:)); | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/projector_calib.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/projector_calib.m new file mode 100755 index 0000000..bb4ef86 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/projector_calib.m | |||
@@ -0,0 +1,258 @@ | |||
1 | %%% This code is an additional code that helps doing projector calibration in 3D scanning setup. | ||
2 | %%% This is not a useful code for anyone else but me. | ||
3 | %%% I included it in the toolbox for illustration only. | ||
4 | |||
5 | |||
6 | load camera_results; | ||
7 | |||
8 | |||
9 | proj_name = input('Basename projector calibration images (without number nor suffix): ','s'); | ||
10 | |||
11 | |||
12 | i = 1; | ||
13 | |||
14 | while (i <= n_ima), % & (~no_image_file), | ||
15 | |||
16 | if active_images(i), | ||
17 | |||
18 | %fprintf(1,'Loading image %d...\n',i); | ||
19 | |||
20 | if ~type_numbering, | ||
21 | number_ext = num2str(image_numbers(i)); | ||
22 | else | ||
23 | number_ext = sprintf(['%.' num2str(N_slots) 'd'],image_numbers(i)); | ||
24 | end; | ||
25 | |||
26 | ima_namep = [proj_name number_ext 'p.' format_image]; | ||
27 | ima_namen = [proj_name number_ext 'n.' format_image]; | ||
28 | |||
29 | if i == ind_active(1), | ||
30 | fprintf(1,'Loading image '); | ||
31 | end; | ||
32 | |||
33 | fprintf(1,'%d...',i); | ||
34 | |||
35 | if format_image(1) == 'p', | ||
36 | if format_image(2) == 'p', | ||
37 | Ip = double(loadppm(ima_namep)); | ||
38 | In = double(loadppm(ima_namen)); | ||
39 | else | ||
40 | Ip = double(loadpgm(ima_namep)); | ||
41 | In = double(loadpgm(ima_namen)); | ||
42 | end; | ||
43 | else | ||
44 | if format_image(1) == 'r', | ||
45 | Ip = readras(ima_namep); | ||
46 | In = readras(ima_namen); | ||
47 | else | ||
48 | Ip = double(imread(ima_namep)); | ||
49 | In = double(imread(ima_namen)); | ||
50 | end; | ||
51 | end; | ||
52 | |||
53 | |||
54 | if size(Ip,3)>1, | ||
55 | Ip = Ip(:,:,2); | ||
56 | In = In(:,:,2); | ||
57 | end; | ||
58 | |||
59 | eval(['Ip_' num2str(i) ' = Ip;']); | ||
60 | eval(['In_' num2str(i) ' = In;']); | ||
61 | |||
62 | end; | ||
63 | |||
64 | i = i+1; | ||
65 | |||
66 | end; | ||
67 | |||
68 | |||
69 | fprintf(1,'\nExtraction of the grid corners on the image\n'); | ||
70 | |||
71 | disp('Window size for corner finder (wintx and winty):'); | ||
72 | wintx = input('wintx ([] = 5) = '); | ||
73 | if isempty(wintx), wintx = 5; end; | ||
74 | wintx = round(wintx); | ||
75 | winty = input('winty ([] = 5) = '); | ||
76 | if isempty(winty), winty = 5; end; | ||
77 | winty = round(winty); | ||
78 | fprintf(1,'Window size = %dx%d\n',2*wintx+1,2*winty+1); | ||
79 | |||
80 | |||
81 | disp('The projector you are using is the DLP or Intel'); | ||
82 | nx = 800; | ||
83 | ny = 600; | ||
84 | |||
85 | dX = input('Size dX in x of the squares (in pixels) [50] = '); | ||
86 | dY = input('Size dY in y of the squares (in pixels) [50] = '); | ||
87 | |||
88 | if isempty(dX), dX=50; end; | ||
89 | if isempty(dY), dY=50; end; | ||
90 | |||
91 | dXoff = input('Position in x of your reference (in pixels) [399.5] = '); | ||
92 | dYoff = input('Position in y of your reference (in pixels) [299.5] = '); | ||
93 | |||
94 | if isempty(dXoff), dXoff=399.5; end; | ||
95 | if isempty(dYoff), dYoff=299.5; end; | ||
96 | |||
97 | end; | ||
98 | |||
99 | |||
100 | |||
101 | for kk = ind_active, | ||
102 | |||
103 | eval(['Ip = Ip_' num2str(kk) ';']); | ||
104 | eval(['In = In_' num2str(kk) ';']); | ||
105 | |||
106 | [x,X,n_sq_x,n_sq_y,ind_orig,ind_x,ind_y] = extract_grid(In,wintx,winty,fc,cc,kc,dX,dY); | ||
107 | xproj = x; | ||
108 | |||
109 | Np_proj = size(x,2); | ||
110 | |||
111 | figure(2); | ||
112 | image(Ip); | ||
113 | hold on; | ||
114 | plot(xproj(1,:)+1,xproj(2,:)+1,'r+'); | ||
115 | title('Click on your reference point'); | ||
116 | xlabel('Xc (in camera frame)'); | ||
117 | ylabel('Yc (in camera frame)'); | ||
118 | hold off; | ||
119 | |||
120 | disp('Click on your reference point...'); | ||
121 | |||
122 | [xr,yr] = ginput2(1); | ||
123 | |||
124 | err = sqrt(sum((xproj - [xr;yr]*ones(1,Np_proj)).^2)); | ||
125 | ind_ref = find(err == min(err)); | ||
126 | |||
127 | ref_pt = xproj(:,ind_ref); | ||
128 | |||
129 | |||
130 | figure(2); | ||
131 | hold on; | ||
132 | plot(ref_pt(1)+1,ref_pt(2)+1,'go'); hold off; | ||
133 | |||
134 | |||
135 | nn = floor(ind_ref/(n_sq_x+1)); | ||
136 | off_x = ind_ref - nn*(n_sq_x+1) - 1; | ||
137 | off_y = n_sq_y - nn; | ||
138 | |||
139 | |||
140 | xprojn = xproj - cc * ones(1,Np_proj); | ||
141 | xprojn = xprojn ./ (fc * ones(1,Np_proj)); | ||
142 | xprojn = comp_distortion(xprojn,kc); | ||
143 | |||
144 | eval(['Rc = Rc_' num2str(kk) ';']); | ||
145 | eval(['Tc = Tc_' num2str(kk) ';']); | ||
146 | |||
147 | Zc = ((Rc(:,3)'*Tc) * (1./(Rc(:,3)' * [xprojn; ones(1,Np_proj)]))); | ||
148 | Xcp = (ones(3,1)*Zc) .* [xprojn; ones(1,Np_proj)]; % % in the camera frame | ||
149 | %Xproj = Rc'* Xcp - (Rc'*Tc)*ones(1,Np); % in the object frame !!! it works! | ||
150 | %Xproj(3,:) = zeros(1,Np); | ||
151 | |||
152 | eval(['X_proj_' num2str(kk) ' = Xcp;']); % coordinates of the points in the | ||
153 | |||
154 | x_proj = X(1:2,:) + ([dXoff - dX * off_x ; dYoff - dY * off_y]*ones(1,Np_proj)); | ||
155 | |||
156 | eval(['x_proj_' num2str(kk) ' = x_proj;']); % coordinates of the points in the | ||
157 | |||
158 | end; | ||
159 | |||
160 | |||
161 | |||
162 | X_proj = []; | ||
163 | x_proj = []; | ||
164 | |||
165 | for kk = ind_active, | ||
166 | eval(['X_proj = [X_proj X_proj_' num2str(kk) '];']); | ||
167 | eval(['x_proj = [x_proj x_proj_' num2str(kk) '];']); | ||
168 | end; | ||
169 | |||
170 | |||
171 | %Save camera parameters: | ||
172 | fc_save = fc; | ||
173 | cc_save = cc; | ||
174 | kc_save = kc; | ||
175 | |||
176 | omc_1_save = omc_1; | ||
177 | Rc_1_save = Rc_1; | ||
178 | Tc_1_save = Tc_1; | ||
179 | |||
180 | |||
181 | % Get started to calibrate projector: | ||
182 | clear fc cc kc | ||
183 | |||
184 | n_ima = 1; | ||
185 | X_1 = X_proj; | ||
186 | x_1 = x_proj; | ||
187 | |||
188 | |||
189 | % Image size: (may or may not be available) | ||
190 | |||
191 | nx = 800; | ||
192 | ny = 600; | ||
193 | |||
194 | % No calibration image is available (only the corner coordinates) | ||
195 | |||
196 | no_image = 1; | ||
197 | |||
198 | % Set the toolbox not to prompt the user (choose default values) | ||
199 | |||
200 | dont_ask = 1; | ||
201 | |||
202 | % Do not estimate distortion: | ||
203 | |||
204 | est_dist = [0;0;0;0]; | ||
205 | est_dist = ones(4,1); | ||
206 | |||
207 | center_optim = 1; | ||
208 | |||
209 | % Run the main calibration routine: | ||
210 | |||
211 | go_calib_optim_iter; | ||
212 | |||
213 | % Shows the extrinsic parameters: | ||
214 | |||
215 | dX = 3; | ||
216 | dY = 3; | ||
217 | |||
218 | ext_calib; | ||
219 | |||
220 | % Reprojection on the original images: | ||
221 | |||
222 | reproject_calib; | ||
223 | |||
224 | |||
225 | |||
226 | |||
227 | %----------------------- Retrieve results: | ||
228 | |||
229 | % Intrinsic: | ||
230 | |||
231 | % Projector: | ||
232 | fp = fc; | ||
233 | cp = cc; | ||
234 | kp = kc; | ||
235 | |||
236 | % Camera: | ||
237 | fc = fc_save; | ||
238 | cc = cc_save; | ||
239 | kc = kc_save; | ||
240 | |||
241 | % Extrinsic: | ||
242 | |||
243 | % Relative position of projector and camera: | ||
244 | T = Tc_1; | ||
245 | om = omc_1; | ||
246 | R = rodrigues(om); | ||
247 | |||
248 | % Relative prosition of camera wrt world: | ||
249 | omc = omc_1_save; | ||
250 | Rc = Rc_1_save; | ||
251 | Tc = Tc_1_save; | ||
252 | |||
253 | % relative position of projector wrt world: | ||
254 | Rp = R*Rc; | ||
255 | omp = rodrigues(Rp); | ||
256 | Tp = T + R*Tc; | ||
257 | |||
258 | eval(['save calib_cam_proj R om T fc fp cc cp kc kp Rc Rp Tc Tp']); | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/readras.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/readras.m new file mode 100755 index 0000000..fc1820b --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/readras.m | |||
@@ -0,0 +1,87 @@ | |||
1 | function [X, map] = readras(filename, ys, ye, xs, xe); | ||
2 | %READRAS Read an image file in sun raster format. | ||
3 | % READRAS('imagefile.ras') reads a "sun.raster" image file. | ||
4 | % [X, map] = READRAS('imagefile.ras') returns both the image and a | ||
5 | % color map, so that | ||
6 | % [X, map] = readras('imagefile.ras'); | ||
7 | % image(X) | ||
8 | % colormap(map) | ||
9 | % axis('equal') | ||
10 | % will display the result with the proper colors. | ||
11 | % NOTE: readras cannot deal with complicated color maps. | ||
12 | % In fact, Matlab doesn't quite allow to work with colormaps | ||
13 | % with more than 64 entries. | ||
14 | % | ||
15 | |||
16 | %% | ||
17 | %% (C) Thomas K. Leung 3/30/93. | ||
18 | %% California Institute of Technology. | ||
19 | %% Modified by Andrea Mennucci to deal with color images | ||
20 | %% | ||
21 | |||
22 | % PC and UNIX version of readras - Jean-Yves Bouguet - Dec. 1998 | ||
23 | |||
24 | dot = max(find(filename == '.')); | ||
25 | suffix = filename(dot+1:dot+3); | ||
26 | |||
27 | if(strcmp(suffix, 'ras')) % raster file format % | ||
28 | fp = fopen(filename, 'rb'); | ||
29 | if(fp<0) error(['Cannot open ' filename '.']), end | ||
30 | |||
31 | %Read and crack the 32-byte header | ||
32 | fseek(fp, 4, -1); | ||
33 | |||
34 | width = 2^24 * fread(fp, 1, 'uchar') + 2^16 * fread(fp, 1, 'uchar') + 2^8 * fread(fp, 1, 'uchar') + fread(fp, 1, 'uchar'); | ||
35 | |||
36 | height = 2^24 * fread(fp, 1, 'uchar') + 2^16 * fread(fp, 1, 'uchar') + 2^8 * fread(fp, 1, 'uchar') + fread(fp, 1, 'uchar'); | ||
37 | |||
38 | depth = 2^24 * fread(fp, 1, 'uchar') + 2^16 * fread(fp, 1, 'uchar') + 2^8 * fread(fp, 1, 'uchar') + fread(fp, 1, 'uchar'); | ||
39 | |||
40 | length = 2^24 * fread(fp, 1, 'uchar') + 2^16 * fread(fp, 1, 'uchar') + 2^8 * fread(fp, 1, 'uchar') + fread(fp, 1, 'uchar'); | ||
41 | |||
42 | type = 2^24 * fread(fp, 1, 'uchar') + 2^16 * fread(fp, 1, 'uchar') + 2^8 * fread(fp, 1, 'uchar') + fread(fp, 1, 'uchar'); | ||
43 | |||
44 | maptype = 2^24 * fread(fp, 1, 'uchar') + 2^16 * fread(fp, 1, 'uchar') + 2^8 * fread(fp, 1, 'uchar') + fread(fp, 1, 'uchar'); | ||
45 | |||
46 | maplen = 2^24 * fread(fp, 1, 'uchar') + 2^16 * fread(fp, 1, 'uchar') + 2^8 * fread(fp, 1, 'uchar') + fread(fp, 1, 'uchar'); | ||
47 | |||
48 | maplen = maplen / 3; | ||
49 | |||
50 | if maptype == 2 % RMT_RAW | ||
51 | map = fread(fp, [maplen, 3], 'uchar')/255; | ||
52 | % if maplen<64, map=[map',zeros(3,64-maplen)]';maplen=64; end; | ||
53 | elseif maptype == 1 % RMT_EQUAL_RGB | ||
54 | map(:,1) = fread(fp, [maplen], 'uchar'); | ||
55 | map(:,2) = fread(fp, [maplen], 'uchar'); | ||
56 | map(:,3) = fread(fp, [maplen], 'uchar'); | ||
57 | %maxmap = max(max(map)); | ||
58 | map = map/255; | ||
59 | if maplen<64, map=[map',zeros(3,64-maplen)]'; maplen=64; end; | ||
60 | else % RMT_NONE | ||
61 | map = []; | ||
62 | end | ||
63 | % if maplen>64, | ||
64 | % map=[map',zeros(3,256-maplen)]'; | ||
65 | % end; | ||
66 | |||
67 | % Read the image | ||
68 | |||
69 | if rem(width,2) == 1 | ||
70 | Xt = fread(fp, [width+1, height], 'uchar'); | ||
71 | X = Xt(1:width, :)'; | ||
72 | else | ||
73 | Xt = fread(fp, [width, height], 'uchar'); | ||
74 | X = Xt'; | ||
75 | end | ||
76 | X = X + 1; | ||
77 | fclose(fp); | ||
78 | else | ||
79 | error('Image file name must end in either ''ras'' or ''rast''.'); | ||
80 | end | ||
81 | |||
82 | |||
83 | if nargin == 5 | ||
84 | |||
85 | X = X(ys:ye, xs:xe); | ||
86 | |||
87 | end \ No newline at end of file | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/recomp_corner_calib.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/recomp_corner_calib.m new file mode 100755 index 0000000..0909c69 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/recomp_corner_calib.m | |||
@@ -0,0 +1,119 @@ | |||
1 | % Re-select te corners after calibration | ||
2 | |||
3 | if ~exist('n_ima')|~exist('fc'), | ||
4 | fprintf(1,'No calibration data available.\n'); | ||
5 | return; | ||
6 | end; | ||
7 | |||
8 | check_active_images; | ||
9 | |||
10 | flag = 0; | ||
11 | for kk = ind_active, | ||
12 | if ~exist(['y_' num2str(kk)]), | ||
13 | flag = 1; | ||
14 | else | ||
15 | eval(['ykk = y_' num2str(kk) ';']); | ||
16 | if isnan(ykk(1,1)), | ||
17 | flag = 1; | ||
18 | end; | ||
19 | end; | ||
20 | end; | ||
21 | |||
22 | if flag, | ||
23 | fprintf(1,'Need to calibrate once before before recomputing image corners. Maybe need to load Calib_Results.mat file.\n'); | ||
24 | return; | ||
25 | end; | ||
26 | |||
27 | |||
28 | if ~exist(['I_' num2str(ind_active(1))]), | ||
29 | n_ima_save = n_ima; | ||
30 | active_images_save = active_images; | ||
31 | ima_read_calib; | ||
32 | n_ima = n_ima_save; | ||
33 | active_images = active_images_save; | ||
34 | check_active_images; | ||
35 | if no_image_file, | ||
36 | disp('Cannot extract corners without images'); | ||
37 | return; | ||
38 | end; | ||
39 | end; | ||
40 | |||
41 | fprintf(1,'\nRe-extraction of the grid corners on the images (after first calibration)\n'); | ||
42 | |||
43 | disp('Window size for corner finder (wintx and winty):'); | ||
44 | wintx = input('wintx ([] = 5) = '); | ||
45 | if isempty(wintx), wintx = 5; end; | ||
46 | wintx = round(wintx); | ||
47 | winty = input('winty ([] = 5) = '); | ||
48 | if isempty(winty), winty = 5; end; | ||
49 | winty = round(winty); | ||
50 | |||
51 | fprintf(1,'Window size = %dx%d\n',2*wintx+1,2*winty+1); | ||
52 | |||
53 | ima_numbers = input('Number(s) of image(s) to process ([] = all images) = '); | ||
54 | |||
55 | if isempty(ima_numbers), | ||
56 | ima_proc = 1:n_ima; | ||
57 | else | ||
58 | ima_proc = ima_numbers; | ||
59 | end; | ||
60 | |||
61 | q_auto = input('Use the projection of 3D grid or manual click ([]=auto, other=manual): '); | ||
62 | |||
63 | fprintf(1,'Processing image '); | ||
64 | |||
65 | for kk = ima_proc; | ||
66 | |||
67 | if active_images(kk), | ||
68 | |||
69 | fprintf(1,'%d...',kk); | ||
70 | |||
71 | if isempty(q_auto), | ||
72 | |||
73 | eval(['I = I_' num2str(kk) ';']); | ||
74 | |||
75 | eval(['y = y_' num2str(kk) ';']); | ||
76 | |||
77 | xc = cornerfinder(y+1,I,winty,wintx); % the four corners | ||
78 | |||
79 | eval(['wintx_' num2str(kk) ' = wintx;']); | ||
80 | eval(['winty_' num2str(kk) ' = winty;']); | ||
81 | |||
82 | eval(['x_' num2str(kk) '= xc - 1;']); | ||
83 | |||
84 | else | ||
85 | |||
86 | fprintf(1,'\n'); | ||
87 | |||
88 | click_ima_calib; | ||
89 | |||
90 | end; | ||
91 | |||
92 | else | ||
93 | |||
94 | if ~exist(['omc_' num2str(kk)]), | ||
95 | |||
96 | eval(['dX_' num2str(kk) ' = NaN;']); | ||
97 | eval(['dY_' num2str(kk) ' = NaN;']); | ||
98 | |||
99 | eval(['wintx_' num2str(kk) ' = NaN;']); | ||
100 | eval(['winty_' num2str(kk) ' = NaN;']); | ||
101 | |||
102 | eval(['x_' num2str(kk) ' = NaN*ones(2,1);']); | ||
103 | eval(['X_' num2str(kk) ' = NaN*ones(3,1);']); | ||
104 | |||
105 | eval(['n_sq_x_' num2str(kk) ' = NaN;']); | ||
106 | eval(['n_sq_y_' num2str(kk) ' = NaN;']); | ||
107 | |||
108 | end; | ||
109 | |||
110 | end; | ||
111 | |||
112 | |||
113 | end; | ||
114 | |||
115 | % Recompute the error: | ||
116 | |||
117 | comp_error_calib; | ||
118 | |||
119 | fprintf(1,'\ndone\n'); \ No newline at end of file | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/rect.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/rect.m new file mode 100755 index 0000000..ccac7a5 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/rect.m | |||
@@ -0,0 +1,127 @@ | |||
1 | function [Irec] = rect(I,R,f,c,k,alpha,KK_new); | ||
2 | |||
3 | |||
4 | if nargin < 5, | ||
5 | k = 0; | ||
6 | if nargin < 4, | ||
7 | c = [0;0]; | ||
8 | if nargin < 3, | ||
9 | f = [1;1]; | ||
10 | if nargin < 2, | ||
11 | R = eye(3); | ||
12 | if nargin < 1, | ||
13 | error('ERROR: Need an image to rectify'); | ||
14 | break; | ||
15 | end; | ||
16 | end; | ||
17 | end; | ||
18 | end; | ||
19 | end; | ||
20 | |||
21 | |||
22 | if nargin < 7, | ||
23 | if nargin < 6, | ||
24 | KK_new = [f(1) 0 c(1);0 f(2) c(2);0 0 1]; | ||
25 | else | ||
26 | KK_new = alpha; % the 6th argument is actually KK_new | ||
27 | end; | ||
28 | alpha = 0; | ||
29 | end; | ||
30 | |||
31 | |||
32 | |||
33 | % Note: R is the motion of the points in space | ||
34 | % So: X2 = R*X where X: coord in the old reference frame, X2: coord in the new ref frame. | ||
35 | |||
36 | |||
37 | if ~exist('KK_new'), | ||
38 | KK_new = [f(1) alpha_c*fc(1) c(1);0 f(2) c(2);0 0 1]; | ||
39 | end; | ||
40 | |||
41 | |||
42 | [nr,nc] = size(I); | ||
43 | |||
44 | Irec = 255*ones(nr,nc); | ||
45 | |||
46 | [mx,my] = meshgrid(1:nc, 1:nr); | ||
47 | px = reshape(mx',nc*nr,1); | ||
48 | py = reshape(my',nc*nr,1); | ||
49 | |||
50 | rays = inv(KK_new)*[(px - 1)';(py - 1)';ones(1,length(px))]; | ||
51 | |||
52 | |||
53 | % Rotation: (or affine transformation): | ||
54 | |||
55 | rays2 = R'*rays; | ||
56 | |||
57 | x = [rays2(1,:)./rays2(3,:);rays2(2,:)./rays2(3,:)]; | ||
58 | |||
59 | |||
60 | % Add distortion: | ||
61 | |||
62 | k1 = k(1); | ||
63 | k2 = k(2); | ||
64 | |||
65 | p1 = k(3); | ||
66 | p2 = k(4); | ||
67 | |||
68 | r_2 = sum(x.^2); | ||
69 | |||
70 | delta_x = [2*p1*x(1,:).*x(2,:) + p2*(r_2 + 2*x(1,:).^2) ; | ||
71 | p1 * (r_2 + 2*x(2,:).^2)+2*p2*x(1,:).*x(2,:)]; | ||
72 | |||
73 | xd = (ones(2,1)*( 1 + k1 * r_2 + k2 * r_2.^2)) .* x + delta_x; | ||
74 | |||
75 | |||
76 | % Reconvert in pixels: | ||
77 | |||
78 | px2 = f(1)*(xd(1,:)+alpha_c*xd(2,:))+c(1); | ||
79 | py2 = f(2)*xd(2,:)+c(2); | ||
80 | |||
81 | |||
82 | % Interpolate between the closest pixels: | ||
83 | |||
84 | px_0 = floor(px2); | ||
85 | px_1 = px_0 + 1; | ||
86 | alpha_x = px2 - px_0; | ||
87 | |||
88 | py_0 = floor(py2); | ||
89 | py_1 = py_0 + 1; | ||
90 | alpha_y = py2 - py_0; | ||
91 | |||
92 | good_points = find((px_0 >= 0) & (px_1 <= (nc-1)) & (py_0 >= 0) & (py_1 <= (nr-1))); | ||
93 | |||
94 | I_lu = I(px_0(good_points) * nr + py_0(good_points) + 1); | ||
95 | I_ru = I(px_1(good_points) * nr + py_0(good_points) + 1); | ||
96 | I_ld = I(px_0(good_points) * nr + py_1(good_points) + 1); | ||
97 | I_rd = I(px_1(good_points) * nr + py_1(good_points) + 1); | ||
98 | |||
99 | |||
100 | I_interp = (1 - alpha_y(good_points)).*((1 - alpha_x(good_points)).* I_lu + alpha_x(good_points) .* I_ru) + alpha_y(good_points) .* ((1 - alpha_x(good_points)).* I_ld + alpha_x(good_points) .* I_rd); | ||
101 | |||
102 | |||
103 | Irec((px(good_points)-1)*nr + py(good_points)) = I_interp; | ||
104 | |||
105 | |||
106 | |||
107 | return; | ||
108 | |||
109 | |||
110 | % Convert in indices: | ||
111 | |||
112 | fact = 3; | ||
113 | |||
114 | [XX,YY]= meshgrid(1:nc,1:nr); | ||
115 | [XXi,YYi]= meshgrid(1:1/fact:nc,1:1/fact:nr); | ||
116 | |||
117 | %tic; | ||
118 | Iinterp = interp2(XX,YY,I,XXi,YYi); | ||
119 | %toc | ||
120 | |||
121 | [nri,nci] = size(Iinterp); | ||
122 | |||
123 | |||
124 | ind_col = round(fact*(f(1)*xd(1,:)+c(1)))+1; | ||
125 | ind_row = round(fact*(f(2)*xd(2,:)+c(2)))+1; | ||
126 | |||
127 | good_points = find((ind_col >=1)&(ind_col<=nci)&(ind_row >=1)& (ind_row <=nri)); | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/reproject_calib.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/reproject_calib.m new file mode 100755 index 0000000..d3ad3d2 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/reproject_calib.m | |||
@@ -0,0 +1,121 @@ | |||
1 | %%%%%%%%%%%%%%%%%%%% REPROJECT ON THE IMAGES %%%%%%%%%%%%%%%%%%%%%%%% | ||
2 | |||
3 | if ~exist('n_ima')|~exist('fc'), | ||
4 | fprintf(1,'No calibration data available.\n'); | ||
5 | return; | ||
6 | end; | ||
7 | |||
8 | if ~exist('no_image'), | ||
9 | no_image = 0; | ||
10 | end; | ||
11 | |||
12 | if ~exist('nx')&~exist('ny'), | ||
13 | fprintf(1,'WARNING: No image size (nx,ny) available. Setting nx=640 and ny=480\n'); | ||
14 | nx = 640; | ||
15 | ny = 480; | ||
16 | end; | ||
17 | |||
18 | |||
19 | check_active_images; | ||
20 | |||
21 | |||
22 | % Color code for each image: | ||
23 | |||
24 | colors = 'brgkcm'; | ||
25 | |||
26 | % Reproject the patterns on the images, and compute the pixel errors: | ||
27 | |||
28 | % Reload the images if necessary | ||
29 | |||
30 | if ~exist(['omc_' num2str(ind_active(1)) ]), | ||
31 | fprintf(1,'Need to calibrate before showing image reprojection. Maybe need to load Calib_Results.mat file.\n'); | ||
32 | return; | ||
33 | end; | ||
34 | |||
35 | if ~no_image, | ||
36 | if ~exist(['I_' num2str(ind_active(1)) ]'), | ||
37 | n_ima_save = n_ima; | ||
38 | active_images_save = active_images; | ||
39 | ima_read_calib; | ||
40 | n_ima = n_ima_save; | ||
41 | active_images = active_images_save; | ||
42 | check_active_images; | ||
43 | if no_image_file, | ||
44 | fprintf(1,'WARNING: Do not show the original images\n'); %return; | ||
45 | end; | ||
46 | end; | ||
47 | else | ||
48 | no_image_file = 1; | ||
49 | end; | ||
50 | |||
51 | |||
52 | if ~exist('dont_ask'), | ||
53 | dont_ask = 0; | ||
54 | end; | ||
55 | |||
56 | |||
57 | if ~dont_ask, | ||
58 | ima_numbers = input('Number(s) of image(s) to show ([] = all images) = '); | ||
59 | else | ||
60 | ima_numbers = []; | ||
61 | end; | ||
62 | |||
63 | |||
64 | if isempty(ima_numbers), | ||
65 | ima_proc = 1:n_ima; | ||
66 | else | ||
67 | ima_proc = ima_numbers; | ||
68 | end; | ||
69 | |||
70 | |||
71 | figure(5); | ||
72 | for kk = ima_proc, %1:n_ima, | ||
73 | if exist(['y_' num2str(kk)]), | ||
74 | if active_images(kk) & eval(['~isnan(y_' num2str(kk) '(1,1))']), | ||
75 | eval(['plot(ex_' num2str(kk) '(1,:),ex_' num2str(kk) '(2,:),''' colors(rem(kk-1,6)+1) '+'');']); | ||
76 | hold on; | ||
77 | end; | ||
78 | end; | ||
79 | end; | ||
80 | hold off; | ||
81 | axis('equal'); | ||
82 | title('Reprojection error (in pixel)'); | ||
83 | xlabel('x'); | ||
84 | ylabel('y'); | ||
85 | drawnow; | ||
86 | |||
87 | set(5,'Name','error','NumberTitle','off'); | ||
88 | |||
89 | |||
90 | |||
91 | for kk = ima_proc, | ||
92 | if exist(['y_' num2str(kk)]), | ||
93 | if active_images(kk) & eval(['~isnan(y_' num2str(kk) '(1,1))']), | ||
94 | |||
95 | if exist(['I_' num2str(kk)]), | ||
96 | eval(['I = I_' num2str(kk) ';']); | ||
97 | else | ||
98 | I = 255*ones(ny,nx); | ||
99 | end; | ||
100 | |||
101 | figure(5+kk); | ||
102 | image(I); hold on; | ||
103 | colormap(gray(256)); | ||
104 | title(['Image ' num2str(kk) ' - Image points (+) and reprojected grid points (o)']); | ||
105 | eval(['plot(x_' num2str(kk) '(1,:)+1,x_' num2str(kk) '(2,:)+1,''r+'');']); | ||
106 | eval(['plot(y_' num2str(kk) '(1,:)+1,y_' num2str(kk) '(2,:)+1,''' colors(rem(kk-1,6)+1) 'o'');']); | ||
107 | zoom on; | ||
108 | axis([1 nx 1 ny]); | ||
109 | hold off; | ||
110 | drawnow; | ||
111 | |||
112 | set(5+kk,'Name',num2str(kk),'NumberTitle','off'); | ||
113 | |||
114 | end; | ||
115 | end; | ||
116 | end; | ||
117 | |||
118 | |||
119 | err_std = std(ex')'; | ||
120 | |||
121 | fprintf(1,'Pixel error: err = [%3.5f %3.5f] (all active images)\n\n',err_std); | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/rigid_motion.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/rigid_motion.m new file mode 100755 index 0000000..473405c --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/rigid_motion.m | |||
@@ -0,0 +1,66 @@ | |||
1 | function [Y,dYdom,dYdT] = rigid_motion(X,om,T); | ||
2 | |||
3 | %rigid_motion.m | ||
4 | % | ||
5 | %[Y,dYdom,dYdT] = rigid_motion(X,om,T) | ||
6 | % | ||
7 | %Computes the rigid motion transformation Y = R*X+T, where R = rodrigues(om). | ||
8 | % | ||
9 | %INPUT: X: 3D structure in the world coordinate frame (3xN matrix for N points) | ||
10 | % (om,T): Rigid motion parameters between world coordinate frame and camera reference frame | ||
11 | % om: rotation vector (3x1 vector); T: translation vector (3x1 vector) | ||
12 | % | ||
13 | %OUTPUT: Y: 3D coordinates of the structure points in the camera reference frame (3xN matrix for N points) | ||
14 | % dYdom: Derivative of Y with respect to om ((3N)x3 matrix) | ||
15 | % dYdT: Derivative of Y with respect to T ((3N)x3 matrix) | ||
16 | % | ||
17 | %Definitions: | ||
18 | %Let P be a point in 3D of coordinates X in the world reference frame (stored in the matrix X) | ||
19 | %The coordinate vector of P in the camera reference frame is: Y = R*X + T | ||
20 | %where R is the rotation matrix corresponding to the rotation vector om: R = rodrigues(om); | ||
21 | % | ||
22 | %Important function called within that program: | ||
23 | % | ||
24 | %rodrigues.m: Computes the rotation matrix corresponding to a rotation vector | ||
25 | |||
26 | |||
27 | |||
28 | if nargin < 3, | ||
29 | T = zeros(3,1); | ||
30 | if nargin < 2, | ||
31 | om = zeros(3,1); | ||
32 | if nargin < 1, | ||
33 | error('Need at least a 3D structure as input (in rigid_motion.m)'); | ||
34 | return; | ||
35 | end; | ||
36 | end; | ||
37 | end; | ||
38 | |||
39 | |||
40 | [R,dRdom] = rodrigues(om); | ||
41 | |||
42 | [m,n] = size(X); | ||
43 | |||
44 | Y = R*X + T*ones(1,n); | ||
45 | |||
46 | if nargout > 1, | ||
47 | |||
48 | |||
49 | dYdR = zeros(3*n,9); | ||
50 | dYdT = zeros(3*n,3); | ||
51 | |||
52 | dYdR(1:3:end,1:3:end) = X'; | ||
53 | dYdR(2:3:end,2:3:end) = X'; | ||
54 | dYdR(3:3:end,3:3:end) = X'; | ||
55 | |||
56 | dYdT(1:3:end,1) = ones(n,1); | ||
57 | dYdT(2:3:end,2) = ones(n,1); | ||
58 | dYdT(3:3:end,3) = ones(n,1); | ||
59 | |||
60 | dYdom = dYdR * dRdom; | ||
61 | |||
62 | end; | ||
63 | |||
64 | |||
65 | |||
66 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/rodrigues.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/rodrigues.m new file mode 100755 index 0000000..9d55337 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/rodrigues.m | |||
@@ -0,0 +1,217 @@ | |||
1 | function [out,dout]=rodrigues(in) | ||
2 | |||
3 | % RODRIGUES Transform rotation matrix into rotation vector and viceversa. | ||
4 | % | ||
5 | % Sintax: [OUT]=RODRIGUES(IN) | ||
6 | % If IN is a 3x3 rotation matrix then OUT is the | ||
7 | % corresponding 3x1 rotation vector | ||
8 | % if IN is a rotation 3-vector then OUT is the | ||
9 | % corresponding 3x3 rotation matrix | ||
10 | % | ||
11 | |||
12 | %% | ||
13 | %% Copyright (c) March 1993 -- Pietro Perona | ||
14 | %% California Institute of Technology | ||
15 | %% | ||
16 | |||
17 | %% ALL CHECKED BY JEAN-YVES BOUGUET, October 1995. | ||
18 | %% FOR ALL JACOBIAN MATRICES !!! LOOK AT THE TEST AT THE END !! | ||
19 | |||
20 | %% BUG when norm(om)=pi fixed -- April 6th, 1997; | ||
21 | %% Jean-Yves Bouguet | ||
22 | |||
23 | |||
24 | [m,n] = size(in); | ||
25 | %bigeps = 10e+4*eps; | ||
26 | bigeps = 10e+20*eps; | ||
27 | |||
28 | if ((m==1) & (n==3)) | ((m==3) & (n==1)) %% it is a rotation vector | ||
29 | theta = norm(in); | ||
30 | if theta < eps | ||
31 | R = eye(3); | ||
32 | |||
33 | %if nargout > 1, | ||
34 | |||
35 | dRdin = [0 0 0; | ||
36 | 0 0 1; | ||
37 | 0 -1 0; | ||
38 | 0 0 -1; | ||
39 | 0 0 0; | ||
40 | 1 0 0; | ||
41 | 0 1 0; | ||
42 | -1 0 0; | ||
43 | 0 0 0]; | ||
44 | |||
45 | %end; | ||
46 | |||
47 | else | ||
48 | if n==length(in) in=in'; end; %% make it a column vec. if necess. | ||
49 | |||
50 | %m3 = [in,theta] | ||
51 | |||
52 | dm3din = [eye(3);in'/theta]; | ||
53 | |||
54 | omega = in/theta; | ||
55 | |||
56 | %m2 = [omega;theta] | ||
57 | |||
58 | dm2dm3 = [eye(3)/theta -in/theta^2; zeros(1,3) 1]; | ||
59 | |||
60 | alpha = cos(theta); | ||
61 | beta = sin(theta); | ||
62 | gamma = 1-cos(theta); | ||
63 | omegav=[[0 -omega(3) omega(2)];[omega(3) 0 -omega(1)];[-omega(2) omega(1) 0 ]]; | ||
64 | A = omega*omega'; | ||
65 | |||
66 | %m1 = [alpha;beta;gamma;omegav;A]; | ||
67 | |||
68 | dm1dm2 = zeros(21,4); | ||
69 | dm1dm2(1,4) = -sin(theta); | ||
70 | dm1dm2(2,4) = cos(theta); | ||
71 | dm1dm2(3,4) = sin(theta); | ||
72 | dm1dm2(4:12,1:3) = [0 0 0 0 0 1 0 -1 0; | ||
73 | 0 0 -1 0 0 0 1 0 0; | ||
74 | 0 1 0 -1 0 0 0 0 0]'; | ||
75 | |||
76 | w1 = omega(1); | ||
77 | w2 = omega(2); | ||
78 | w3 = omega(3); | ||
79 | |||
80 | dm1dm2(13:21,1) = [2*w1;w2;w3;w2;0;0;w3;0;0]; | ||
81 | dm1dm2(13: 21,2) = [0;w1;0;w1;2*w2;w3;0;w3;0]; | ||
82 | dm1dm2(13:21,3) = [0;0;w1;0;0;w2;w1;w2;2*w3]; | ||
83 | |||
84 | R = eye(3)*alpha + omegav*beta + A*gamma; | ||
85 | |||
86 | dRdm1 = zeros(9,21); | ||
87 | |||
88 | dRdm1([1 5 9],1) = ones(3,1); | ||
89 | dRdm1(:,2) = omegav(:); | ||
90 | dRdm1(:,4:12) = beta*eye(9); | ||
91 | dRdm1(:,3) = A(:); | ||
92 | dRdm1(:,13:21) = gamma*eye(9); | ||
93 | |||
94 | dRdin = dRdm1 * dm1dm2 * dm2dm3 * dm3din; | ||
95 | |||
96 | |||
97 | end; | ||
98 | out = R; | ||
99 | dout = dRdin; | ||
100 | |||
101 | %% it is prob. a rot matr. | ||
102 | elseif ((m==n) & (m==3) & (norm(in' * in - eye(3)) < bigeps)... | ||
103 | & (abs(det(in)-1) < bigeps)) | ||
104 | R = in; | ||
105 | |||
106 | |||
107 | |||
108 | tr = (trace(R)-1)/2; | ||
109 | dtrdR = [1 0 0 0 1 0 0 0 1]/2; | ||
110 | theta = real(acos(tr)); | ||
111 | |||
112 | |||
113 | if sin(theta) >= 1e-5, | ||
114 | |||
115 | dthetadtr = -1/sqrt(1-tr^2); | ||
116 | |||
117 | dthetadR = dthetadtr * dtrdR; | ||
118 | % var1 = [vth;theta]; | ||
119 | vth = 1/(2*sin(theta)); | ||
120 | dvthdtheta = -vth*cos(theta)/sin(theta); | ||
121 | dvar1dtheta = [dvthdtheta;1]; | ||
122 | |||
123 | dvar1dR = dvar1dtheta * dthetadR; | ||
124 | |||
125 | |||
126 | om1 = [R(3,2)-R(2,3), R(1,3)-R(3,1), R(2,1)-R(1,2)]'; | ||
127 | |||
128 | dom1dR = [0 0 0 0 0 1 0 -1 0; | ||
129 | 0 0 -1 0 0 0 1 0 0; | ||
130 | 0 1 0 -1 0 0 0 0 0]; | ||
131 | |||
132 | % var = [om1;vth;theta]; | ||
133 | dvardR = [dom1dR;dvar1dR]; | ||
134 | |||
135 | % var2 = [om;theta]; | ||
136 | om = vth*om1; | ||
137 | domdvar = [vth*eye(3) om1 zeros(3,1)]; | ||
138 | dthetadvar = [0 0 0 0 1]; | ||
139 | dvar2dvar = [domdvar;dthetadvar]; | ||
140 | |||
141 | |||
142 | out = om*theta; | ||
143 | domegadvar2 = [theta*eye(3) om]; | ||
144 | |||
145 | dout = domegadvar2 * dvar2dvar * dvardR; | ||
146 | |||
147 | |||
148 | else | ||
149 | if tr > 0; % case norm(om)=0; | ||
150 | |||
151 | out = [0 0 0]'; | ||
152 | |||
153 | dout = [0 0 0 0 0 1/2 0 -1/2 0; | ||
154 | 0 0 -1/2 0 0 0 1/2 0 0; | ||
155 | 0 1/2 0 -1/2 0 0 0 0 0]; | ||
156 | else % case norm(om)=pi; %% fixed April 6th | ||
157 | |||
158 | |||
159 | out = theta * (sqrt((diag(R)+1)/2).*[1;2*(R(1,2:3)>=0)'-1]); | ||
160 | %keyboard; | ||
161 | |||
162 | if nargout > 1, | ||
163 | fprintf(1,'WARNING!!!! Jacobian domdR undefined!!!\n'); | ||
164 | dout = NaN*ones(3,9); | ||
165 | end; | ||
166 | end; | ||
167 | end; | ||
168 | |||
169 | else | ||
170 | error('Neither a rotation matrix nor a rotation vector were provided'); | ||
171 | end; | ||
172 | |||
173 | return; | ||
174 | |||
175 | %% test of the Jacobians: | ||
176 | |||
177 | %%%% TEST OF dRdom: | ||
178 | om = randn(3,1); | ||
179 | dom = randn(3,1)/1000000; | ||
180 | |||
181 | [R1,dR1] = rodrigues(om); | ||
182 | R2 = rodrigues(om+dom); | ||
183 | |||
184 | R2a = R1 + reshape(dR1 * dom,3,3); | ||
185 | |||
186 | gain = norm(R2 - R1)/norm(R2 - R2a) | ||
187 | |||
188 | %%% TEST OF dOmdR: | ||
189 | om = randn(3,1); | ||
190 | R = rodrigues(om); | ||
191 | dom = randn(3,1)/10000; | ||
192 | dR = rodrigues(om+dom) - R; | ||
193 | |||
194 | [omc,domdR] = rodrigues(R); | ||
195 | [om2] = rodrigues(R+dR); | ||
196 | |||
197 | om_app = omc + domdR*dR(:); | ||
198 | |||
199 | gain = norm(om2 - omc)/norm(om2 - om_app) | ||
200 | |||
201 | |||
202 | %%% OTHER BUG: (FIXED NOW!!!) | ||
203 | |||
204 | omu = randn(3,1); | ||
205 | omu = omu/norm(omu) | ||
206 | om = pi*omu; | ||
207 | [R,dR]= rodrigues(om); | ||
208 | [om2] = rodrigues(R); | ||
209 | [om om2] | ||
210 | |||
211 | %%% NORMAL OPERATION | ||
212 | |||
213 | om = randn(3,1); | ||
214 | [R,dR]= rodrigues(om); | ||
215 | [om2] = rodrigues(R); | ||
216 | [om om2] | ||
217 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/rotation.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/rotation.m new file mode 100755 index 0000000..87ee2fe --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/rotation.m | |||
@@ -0,0 +1,23 @@ | |||
1 | function [] = rotation(st); | ||
2 | |||
3 | if nargin < 1, | ||
4 | st= 1; | ||
5 | end; | ||
6 | |||
7 | |||
8 | fig = gcf; | ||
9 | |||
10 | ax = gca; | ||
11 | |||
12 | vv = get(ax,'view'); | ||
13 | |||
14 | az = vv(1); | ||
15 | el = vv(2); | ||
16 | |||
17 | for azi = az:-abs(st):az-360, | ||
18 | |||
19 | set(ax,'view',[azi el]); | ||
20 | figure(fig); | ||
21 | drawnow; | ||
22 | |||
23 | end; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/run_error_analysis.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/run_error_analysis.m new file mode 100755 index 0000000..095e17e --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/run_error_analysis.m | |||
@@ -0,0 +1,65 @@ | |||
1 | %%% Program that launchs the complete | ||
2 | |||
3 | for N_ima_active = 1:30, | ||
4 | |||
5 | error_analysis; | ||
6 | |||
7 | end; | ||
8 | |||
9 | |||
10 | |||
11 | return; | ||
12 | |||
13 | |||
14 | f = []; | ||
15 | f_std = []; | ||
16 | |||
17 | c = []; | ||
18 | c_std = []; | ||
19 | |||
20 | k = []; | ||
21 | k_std = []; | ||
22 | |||
23 | NN = 30; | ||
24 | |||
25 | for rr = 1:NN, | ||
26 | |||
27 | load(['Calib_Accuracies_' num2str(rr)]); | ||
28 | |||
29 | [m1,s1] = mean_std_robust(fc_list(1,:)); | ||
30 | [m2,s2] = mean_std_robust(fc_list(2,:)); | ||
31 | |||
32 | f = [f [m1;m2]]; | ||
33 | f_std = [f_std [s1;s2]]; | ||
34 | |||
35 | [m1,s1] = mean_std_robust(cc_list(1,:)); | ||
36 | [m2,s2] = mean_std_robust(cc_list(2,:)); | ||
37 | |||
38 | c = [c [m1;m2]]; | ||
39 | c_std = [c_std [s1;s2]]; | ||
40 | |||
41 | [m1,s1] = mean_std_robust(kc_list(1,:)); | ||
42 | [m2,s2] = mean_std_robust(kc_list(2,:)); | ||
43 | [m3,s3] = mean_std_robust(kc_list(3,:)); | ||
44 | [m4,s4] = mean_std_robust(kc_list(4,:)); | ||
45 | |||
46 | k = [k [m1;m2;m3;m4]]; | ||
47 | k_std = [k_std [s1;s2;s3;s4]]; | ||
48 | |||
49 | end; | ||
50 | |||
51 | figure(1); | ||
52 | errorbar([1:NN;1:NN]',f',f_std'); | ||
53 | figure(2); | ||
54 | errorbar([1:NN;1:NN]',c',c_std'); | ||
55 | figure(3); | ||
56 | errorbar([1:NN;1:NN;1:NN;1:NN]',k',k_std'); | ||
57 | |||
58 | figure(4); | ||
59 | semilogy(f_std'); | ||
60 | |||
61 | figure(5); | ||
62 | semilogy(c_std'); | ||
63 | |||
64 | figure(6); | ||
65 | semilogy(k_std'); | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/saveinr.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/saveinr.m new file mode 100755 index 0000000..a176e39 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/saveinr.m | |||
@@ -0,0 +1,46 @@ | |||
1 | %SAVEINR Write an INRIMAGE format file | ||
2 | % | ||
3 | % SAVEINR(filename, im) | ||
4 | % | ||
5 | % Saves the specified image array in a INRIA image format file. | ||
6 | % | ||
7 | % SEE ALSO: loadinr | ||
8 | % | ||
9 | % Copyright (c) Peter Corke, 1999 Machine Vision Toolbox for Matlab | ||
10 | |||
11 | % Peter Corke 1996 | ||
12 | |||
13 | function saveinr(fname, im) | ||
14 | |||
15 | fid = fopen(fname, 'w'); | ||
16 | [r,c] = size(im'); | ||
17 | |||
18 | % build the header | ||
19 | hdr = []; | ||
20 | s = sprintf('#INRIMAGE-4#{\n'); | ||
21 | hdr = [hdr s]; | ||
22 | s = sprintf('XDIM=%d\n',c); | ||
23 | hdr = [hdr s]; | ||
24 | s = sprintf('YDIM=%d\n',r); | ||
25 | hdr = [hdr s]; | ||
26 | s = sprintf('ZDIM=1\n'); | ||
27 | hdr = [hdr s]; | ||
28 | s = sprintf('VDIM=1\n'); | ||
29 | hdr = [hdr s]; | ||
30 | s = sprintf('TYPE=float\n'); | ||
31 | hdr = [hdr s]; | ||
32 | s = sprintf('PIXSIZE=32\n'); | ||
33 | hdr = [hdr s]; | ||
34 | s = sprintf('SCALE=2**0\n'); | ||
35 | hdr = [hdr s]; | ||
36 | s = sprintf('CPU=sun\n#'); | ||
37 | hdr = [hdr s]; | ||
38 | |||
39 | % make it 256 bytes long and write it | ||
40 | hdr256 = zeros(1,256); | ||
41 | hdr256(1:length(hdr)) = hdr; | ||
42 | fwrite(fid, hdr256, 'uchar'); | ||
43 | |||
44 | % now the binary data | ||
45 | fwrite(fid, im', 'float32'); | ||
46 | fclose(fid) | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/savepgm.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/savepgm.m new file mode 100755 index 0000000..0cee75d --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/savepgm.m | |||
@@ -0,0 +1,22 @@ | |||
1 | %SAVEPGM Write a PGM format file | ||
2 | % | ||
3 | % SAVEPGM(filename, im) | ||
4 | % | ||
5 | % Saves the specified image array in a binary (P5) format PGM image file. | ||
6 | % | ||
7 | % SEE ALSO: loadpgm | ||
8 | % | ||
9 | % Copyright (c) Peter Corke, 1999 Machine Vision Toolbox for Matlab | ||
10 | |||
11 | |||
12 | % Peter Corke 1994 | ||
13 | |||
14 | function savepgm(fname, im) | ||
15 | |||
16 | fid = fopen(fname, 'w'); | ||
17 | [r,c] = size(im'); | ||
18 | fprintf(fid, 'P5\n'); | ||
19 | fprintf(fid, '%d %d\n', r, c); | ||
20 | fprintf(fid, '255\n'); | ||
21 | fwrite(fid, im', 'uchar'); | ||
22 | fclose(fid); | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/saveppm.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/saveppm.m new file mode 100755 index 0000000..ece092b --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/saveppm.m | |||
@@ -0,0 +1,45 @@ | |||
1 | %SAVEPPM Write a PPM format file | ||
2 | % | ||
3 | % SAVEPPM(filename, I) | ||
4 | % | ||
5 | % Saves the specified red, green and blue planes in a binary (P6) | ||
6 | % format PPM image file. | ||
7 | % | ||
8 | % SEE ALSO: loadppm | ||
9 | % | ||
10 | % Copyright (c) Peter Corke, 1999 Machine Vision Toolbox for Matlab | ||
11 | |||
12 | |||
13 | % Peter Corke 1994 | ||
14 | |||
15 | function saveppm(fname, I) | ||
16 | |||
17 | I = double(I); | ||
18 | |||
19 | if size(I,3) == 1, | ||
20 | R = I; | ||
21 | G = I; | ||
22 | B = I; | ||
23 | else | ||
24 | R = I(:,:,1); | ||
25 | G = I(:,:,2); | ||
26 | B = I(:,:,3); | ||
27 | end; | ||
28 | |||
29 | %keyboard; | ||
30 | |||
31 | fid = fopen(fname, 'w'); | ||
32 | [r,c] = size(R'); | ||
33 | fprintf(fid, 'P6\n'); | ||
34 | fprintf(fid, '%d %d\n', r, c); | ||
35 | fprintf(fid, '255\n'); | ||
36 | R = R'; | ||
37 | G = G'; | ||
38 | B = B'; | ||
39 | im = [R(:) G(:) B(:)]; | ||
40 | %im = reshape(im,r,c*3); | ||
41 | im = im'; | ||
42 | %im = im(:); | ||
43 | fwrite(fid, im, 'uchar'); | ||
44 | fclose(fid); | ||
45 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/saving_calib.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/saving_calib.m new file mode 100755 index 0000000..3f98a8b --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/saving_calib.m | |||
@@ -0,0 +1,95 @@ | |||
1 | |||
2 | if ~exist('n_ima')|~exist('fc'), | ||
3 | fprintf(1,'No calibration data available.\n'); | ||
4 | return; | ||
5 | end; | ||
6 | |||
7 | check_active_images; | ||
8 | |||
9 | if ~exist('solution_init'), solution_init = []; end; | ||
10 | |||
11 | for kk = 1:n_ima, | ||
12 | if ~exist(['dX_' num2str(kk)]), eval(['dX_' num2str(kk) '= dX;']); end; | ||
13 | if ~exist(['dY_' num2str(kk)]), eval(['dY_' num2str(kk) '= dY;']); end; | ||
14 | end; | ||
15 | |||
16 | if ~exist('param_list'), | ||
17 | param_list = solution; | ||
18 | end; | ||
19 | |||
20 | if ~exist('wintx'), | ||
21 | wintx = []; | ||
22 | winty = []; | ||
23 | end; | ||
24 | |||
25 | if ~exist('dX_default'), | ||
26 | dX_default = []; | ||
27 | dY_default = []; | ||
28 | end; | ||
29 | |||
30 | if ~exist('alpha_c'), | ||
31 | alpha_c = 0; | ||
32 | end; | ||
33 | |||
34 | for kk = 1:n_ima, | ||
35 | if ~exist(['y_' num2str(kk)]), | ||
36 | eval(['y_' num2str(kk) ' = NaN*ones(2,1);']); | ||
37 | end; | ||
38 | if ~exist(['n_sq_x_' num2str(kk)]), | ||
39 | eval(['n_sq_x_' num2str(kk) ' = NaN;']); | ||
40 | eval(['n_sq_y_' num2str(kk) ' = NaN;']); | ||
41 | end; | ||
42 | if ~exist(['wintx_' num2str(kk)]), | ||
43 | eval(['wintx_' num2str(kk) ' = NaN;']); | ||
44 | eval(['winty_' num2str(kk) ' = NaN;']); | ||
45 | end; | ||
46 | end; | ||
47 | |||
48 | save_name = 'Calib_Results'; | ||
49 | |||
50 | if exist([ save_name '.mat'])==2, | ||
51 | disp('WARNING: File Calib_Results.mat already exists'); | ||
52 | pfn = -1; | ||
53 | cont = 1; | ||
54 | while cont, | ||
55 | pfn = pfn + 1; | ||
56 | postfix = ['_old'num2str(pfn)]; | ||
57 | save_name = [ 'Calib_Results' postfix]; | ||
58 | cont = (exist([ save_name '.mat'])==2); | ||
59 | end; | ||
60 | copyfile('Calib_Results.mat',[save_name '.mat']); | ||
61 | disp(['Copying the current Calib_Results.mat file to ' save_name '.mat']); | ||
62 | end; | ||
63 | |||
64 | |||
65 | save_name = 'Calib_Results'; | ||
66 | |||
67 | if exist('calib_name'), | ||
68 | |||
69 | fprintf(1,['\nSaving calibration results under ' save_name '.mat\n']); | ||
70 | |||
71 | string_save = ['save ' save_name ' center_optim param_list active_images ind_active center_optim est_alpha est_dist fc kc cc alpha_c ex x y solution solution_init wintx winty n_ima type_numbering N_slots small_calib_image first_num image_numbers format_image calib_name Hcal Wcal nx ny map dX_default dY_default KK inv_KK dX dY']; | ||
72 | |||
73 | for kk = 1:n_ima, | ||
74 | string_save = [string_save ' X_' num2str(kk) ' x_' num2str(kk) ' y_' num2str(kk) ' ex_' num2str(kk) ' omc_' num2str(kk) ' Rc_' num2str(kk) ' Tc_' num2str(kk) ' H_' num2str(kk) ' n_sq_x_' num2str(kk) ' n_sq_y_' num2str(kk) ' wintx_' num2str(kk) ' winty_' num2str(kk) ' dX_' num2str(kk) ' dY_' num2str(kk)]; | ||
75 | end; | ||
76 | |||
77 | else | ||
78 | |||
79 | fprintf(1,['\nSaving calibration results under ' save_name '.mat (no image version)\n']); | ||
80 | |||
81 | string_save = ['save ' save_name ' center_optim param_list active_images ind_active center_optim est_alpha est_dist fc kc cc alpha_c ex x y solution solution_init wintx winty n_ima nx ny dX_default dY_default KK inv_KK dX dY']; | ||
82 | |||
83 | for kk = 1:n_ima, | ||
84 | string_save = [string_save ' X_' num2str(kk) ' x_' num2str(kk) ' y_' num2str(kk) ' ex_' num2str(kk) ' omc_' num2str(kk) ' Rc_' num2str(kk) ' Tc_' num2str(kk) ' H_' num2str(kk) ' n_sq_x_' num2str(kk) ' n_sq_y_' num2str(kk) ' wintx_' num2str(kk) ' winty_' num2str(kk) ' dX_' num2str(kk) ' dY_' num2str(kk)]; | ||
85 | end; | ||
86 | |||
87 | end; | ||
88 | |||
89 | |||
90 | |||
91 | %fprintf(1,'To load later click on Load\n'); | ||
92 | |||
93 | eval(string_save); | ||
94 | |||
95 | fprintf(1,'done\n'); \ No newline at end of file | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/script_fit_distortion.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/script_fit_distortion.m new file mode 100755 index 0000000..c5e5430 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/script_fit_distortion.m | |||
@@ -0,0 +1,39 @@ | |||
1 | |||
2 | satis_distort = 0; | ||
3 | |||
4 | disp(['Estimated focal: ' num2str(f_g) ' pixels']); | ||
5 | |||
6 | while ~satis_distort, | ||
7 | |||
8 | k_g = input('Guess for distortion factor kc ([]=0): '); | ||
9 | |||
10 | if isempty(k_g), k_g = 0; end; | ||
11 | |||
12 | xy_corners_undist = comp_distortion2([x' - c_g(1);y'-c_g(2)]/f_g,k_g); | ||
13 | |||
14 | xu = xy_corners_undist(1,:)'; | ||
15 | yu = xy_corners_undist(2,:)'; | ||
16 | |||
17 | [XXu] = projectedGrid ( [xu(1);yu(1)], [xu(2);yu(2)],[xu(3);yu(3)], [xu(4);yu(4)],n_sq_x+1,n_sq_y+1); % The full grid | ||
18 | |||
19 | XX = (ones(2,1)*(1 + k_g * sum(XXu.^2))) .* XXu; | ||
20 | XX(1,:) = f_g*XX(1,:)+c_g(1); | ||
21 | XX(2,:) = f_g*XX(2,:)+c_g(2); | ||
22 | |||
23 | figure(2); | ||
24 | image(I); | ||
25 | colormap(map); | ||
26 | zoom on; | ||
27 | hold on; | ||
28 | %plot(f_g*XXu(1,:)+c_g(1),f_g*XXu(2,:)+c_g(2),'ro'); | ||
29 | plot(XX(1,:),XX(2,:),'r+'); | ||
30 | title('The red crosses should be on the grid corners...'); | ||
31 | hold off; | ||
32 | |||
33 | satis_distort = input('Satisfied with distortion? ([]=no, other=yes) '); | ||
34 | |||
35 | satis_distort = ~isempty(satis_distort); | ||
36 | |||
37 | |||
38 | end; | ||
39 | \ No newline at end of file | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/startup.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/startup.m new file mode 100755 index 0000000..aad0fa4 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/startup.m | |||
@@ -0,0 +1,9 @@ | |||
1 | % Main camera calibration toolbox: | ||
2 | |||
3 | calib_gui; | ||
4 | |||
5 | %calib_gui; | ||
6 | |||
7 | path(pwd,path); | ||
8 | |||
9 | format compact | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/undistort_image.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/undistort_image.m new file mode 100755 index 0000000..d9a7574 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/undistort_image.m | |||
@@ -0,0 +1,193 @@ | |||
1 | %%% INPUT THE IMAGE FILE NAME: | ||
2 | |||
3 | if ~exist('fc')|~exist('cc')|~exist('kc')|~exist('alpha_c'), | ||
4 | fprintf(1,'No intrinsic camera parameters available.\n'); | ||
5 | return; | ||
6 | end; | ||
7 | |||
8 | KK = [fc(1) alpha_c*fc(1) cc(1);0 fc(2) cc(2) ; 0 0 1]; | ||
9 | |||
10 | disp('Program that undistorts images'); | ||
11 | disp('The intrinsic camera parameters are assumed to be known (previously computed)'); | ||
12 | |||
13 | fprintf(1,'\n'); | ||
14 | |||
15 | quest = input('Do you want to undistort all the calibration images ([],0) or a new image (1)? '); | ||
16 | |||
17 | if isempty(quest), | ||
18 | quest = 0; | ||
19 | end; | ||
20 | |||
21 | if ~quest, | ||
22 | |||
23 | if ~exist(['I_' num2str(ind_active(1))]), | ||
24 | ima_read_calib; | ||
25 | end; | ||
26 | |||
27 | check_active_images; | ||
28 | |||
29 | format_image2 = format_image; | ||
30 | if format_image2(1) == 'j', | ||
31 | format_image2 = 'bmp'; | ||
32 | end; | ||
33 | |||
34 | for kk = 1:n_ima, | ||
35 | |||
36 | if exist(['I_' num2str(kk)]), | ||
37 | |||
38 | eval(['I = I_' num2str(kk) ';']); | ||
39 | [I2] = rect(I,eye(3),fc,cc,kc,KK); | ||
40 | |||
41 | if ~type_numbering, | ||
42 | number_ext = num2str(image_numbers(kk)); | ||
43 | else | ||
44 | number_ext = sprintf(['%.' num2str(N_slots) 'd'],image_numbers(kk)); | ||
45 | end; | ||
46 | |||
47 | ima_name2 = [calib_name '_rect' number_ext '.' format_image2]; | ||
48 | |||
49 | fprintf(1,['Saving undistorted image under ' ima_name2 '...\n']); | ||
50 | |||
51 | |||
52 | if format_image2(1) == 'p', | ||
53 | if format_images2(2) == 'p', | ||
54 | saveppm(ima_name2,uint8(round(I2))); | ||
55 | else | ||
56 | savepgm(ima_name2,uint8(round(I2))); | ||
57 | end; | ||
58 | else | ||
59 | if format_image2(1) == 'r', | ||
60 | writeras(ima_name2,round(I2),gray(256)); | ||
61 | else | ||
62 | imwrite(uint8(round(I2)),gray(256),ima_name2,format_image2); | ||
63 | end; | ||
64 | end; | ||
65 | |||
66 | |||
67 | end; | ||
68 | |||
69 | end; | ||
70 | |||
71 | fprintf(1,'done\n'); | ||
72 | |||
73 | else | ||
74 | |||
75 | dir; | ||
76 | fprintf(1,'\n'); | ||
77 | |||
78 | image_name = input('Image name (full name without extension): ','s'); | ||
79 | |||
80 | format_image2 = '0'; | ||
81 | |||
82 | while format_image2 == '0', | ||
83 | |||
84 | format_image2 = input('Image format: ([]=''r''=''ras'', ''b''=''bmp'', ''t''=''tif'', ''p''=''pgm'', ''j''=''jpg'', ''m''=''ppm'') ','s'); | ||
85 | |||
86 | if isempty(format_image2), | ||
87 | format_image2 = 'ras'; | ||
88 | end; | ||
89 | |||
90 | if lower(format_image2(1)) == 'm', | ||
91 | format_image2 = 'ppm'; | ||
92 | else | ||
93 | if lower(format_image2(1)) == 'b', | ||
94 | format_image2 = 'bmp'; | ||
95 | else | ||
96 | if lower(format_image2(1)) == 't', | ||
97 | format_image2 = 'tif'; | ||
98 | else | ||
99 | if lower(format_image2(1)) == 'p', | ||
100 | format_image2 = 'pgm'; | ||
101 | else | ||
102 | if lower(format_image2(1)) == 'j', | ||
103 | format_image2 = 'jpg'; | ||
104 | else | ||
105 | if lower(format_image2(1)) == 'r', | ||
106 | format_image2 = 'ras'; | ||
107 | else | ||
108 | disp('Invalid image format'); | ||
109 | format_image2 = '0'; % Ask for format once again | ||
110 | end; | ||
111 | end; | ||
112 | end; | ||
113 | end; | ||
114 | end; | ||
115 | end; | ||
116 | end; | ||
117 | |||
118 | ima_name = [image_name '.' format_image2]; | ||
119 | |||
120 | |||
121 | %%% READ IN IMAGE: | ||
122 | |||
123 | if format_image2(1) == 'p', | ||
124 | if format_image2(2) == 'p', | ||
125 | I = double(loadppm(ima_name)); | ||
126 | else | ||
127 | I = double(loadpgm(ima_name)); | ||
128 | end; | ||
129 | else | ||
130 | if format_image2(1) == 'r', | ||
131 | I = readras(ima_name); | ||
132 | else | ||
133 | I = double(imread(ima_name)); | ||
134 | end; | ||
135 | end; | ||
136 | |||
137 | if size(I,3)>1, | ||
138 | I = I(:,:,2); | ||
139 | end; | ||
140 | |||
141 | |||
142 | if (size(I,1)>ny)|(size(I,2)>nx), | ||
143 | I = I(1:ny,1:nx); | ||
144 | end; | ||
145 | |||
146 | |||
147 | %% SHOW THE ORIGINAL IMAGE: | ||
148 | |||
149 | figure(2); | ||
150 | image(I); | ||
151 | colormap(gray(256)); | ||
152 | title('Original image (with distortion) - Stored in array I'); | ||
153 | drawnow; | ||
154 | |||
155 | |||
156 | %% UNDISTORT THE IMAGE: | ||
157 | |||
158 | fprintf(1,'Computing the undistorted image...') | ||
159 | |||
160 | [I2] = rect(I,eye(3),fc,cc,kc,alpha_c,KK); | ||
161 | |||
162 | fprintf(1,'done\n'); | ||
163 | |||
164 | figure(3); | ||
165 | image(I2); | ||
166 | colormap(gray(256)); | ||
167 | title('Undistorted image - Stored in array I2'); | ||
168 | drawnow; | ||
169 | |||
170 | |||
171 | %% SAVE THE IMAGE IN FILE: | ||
172 | |||
173 | ima_name2 = [image_name '_rect.' format_image2]; | ||
174 | |||
175 | fprintf(1,['Saving undistorted image under ' ima_name2 '...']); | ||
176 | |||
177 | if format_image2(1) == 'p', | ||
178 | if format_images2(2) == 'p', | ||
179 | saveppm(ima_name2,uint8(round(I2))); | ||
180 | else | ||
181 | savepgm(ima_name2,uint8(round(I2))); | ||
182 | end; | ||
183 | else | ||
184 | if format_image2(1) == 'r', | ||
185 | writeras(ima_name2,round(I2),gray(256)); | ||
186 | else | ||
187 | imwrite(uint8(round(I2)),gray(256),ima_name2,format_image2); | ||
188 | end; | ||
189 | end; | ||
190 | |||
191 | fprintf(1,'done\n'); | ||
192 | |||
193 | end; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/willson_convert.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/willson_convert.m new file mode 100755 index 0000000..8946349 --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/willson_convert.m | |||
@@ -0,0 +1,89 @@ | |||
1 | function [fc,cc,kc,Rc,Tc,omc,nx,ny] = willson_convert(Ncx,Nfx,dx,dy,dpx,dpy,Cx,Cy,sx,f,kappa1,Tx,Ty,Tz,Rx,Ry,Rz,p1,p2); | ||
2 | |||
3 | %Conversion from Reg Willson's calibration format to my format | ||
4 | |||
5 | % Conversion: | ||
6 | |||
7 | % Focal length: | ||
8 | fc = [sx/dpx ; 1/dpy]*f; | ||
9 | |||
10 | % Principal point; | ||
11 | cc = [Cx;Cy]; | ||
12 | |||
13 | % Extrinsic parameters: | ||
14 | Rx = rodrigues([Rx;0;0]); | ||
15 | Ry = rodrigues([0;Ry;0]); | ||
16 | Rz = rodrigues([0;0;Rz]); | ||
17 | |||
18 | Rc = Rz * Ry * Rx; | ||
19 | |||
20 | omc = rodrigues(Rc); | ||
21 | |||
22 | Tc = [Tx;Ty;Tz]; | ||
23 | |||
24 | |||
25 | % More tricky: Take care of the distorsion: | ||
26 | |||
27 | Nfy = round(Nfx * 3/4); | ||
28 | |||
29 | nx = Nfx; | ||
30 | ny = Nfy; | ||
31 | |||
32 | % Select a set of DISTORTED coordinates uniformely distributed across the image: | ||
33 | |||
34 | [xp_dist,yp_dist] = meshgrid(0:Nfx-1,0:Nfy); | ||
35 | |||
36 | xp_dist = xp_dist(:)'; | ||
37 | yp_dist = yp_dist(:)'; | ||
38 | |||
39 | |||
40 | % Apply UNDISTORTION according to Willson: | ||
41 | |||
42 | xp_sensor_dist = dpx*(xp_dist - Cx)/sx; | ||
43 | yp_sensor_dist = dpy*(yp_dist - Cy); | ||
44 | |||
45 | dist_fact = 1 + kappa1*(xp_sensor_dist.^2 + yp_sensor_dist.^2); | ||
46 | |||
47 | xp_sensor = xp_sensor_dist .* dist_fact; | ||
48 | yp_sensor = yp_sensor_dist .* dist_fact; | ||
49 | |||
50 | xp = xp_sensor * sx / dpx + Cx; | ||
51 | yp = yp_sensor / dpy + Cy; | ||
52 | |||
53 | ind= find((xp > 0) & (xp < Nfx-1) & (yp > 0) & (yp < Nfy-1)); | ||
54 | |||
55 | xp = xp(ind); | ||
56 | yp = yp(ind); | ||
57 | xp_dist = xp_dist(ind); | ||
58 | yp_dist = yp_dist(ind); | ||
59 | |||
60 | |||
61 | % Now, find my own set of parameters: | ||
62 | |||
63 | x_dist = [(xp_dist - cc(1))/fc(1);(yp_dist - cc(2))/fc(2)]; | ||
64 | x = [(xp - cc(1))/fc(1);(yp - cc(2))/fc(2)]; | ||
65 | |||
66 | k = [0;0;0;0]; | ||
67 | |||
68 | for kk = 1:5, | ||
69 | |||
70 | [xd,dxddk] = apply_distortion(x,k); | ||
71 | |||
72 | err = x_dist - xd; | ||
73 | |||
74 | %norm(err) | ||
75 | |||
76 | k_step = inv(dxddk'*dxddk)*(dxddk')*err(:); | ||
77 | |||
78 | k = k + k_step; %inv(dxddk'*dxddk)*(dxddk')*err(:); | ||
79 | |||
80 | %norm(k_step)/norm(k) | ||
81 | |||
82 | if norm(k_step)/norm(k) < 10e-10, | ||
83 | break; | ||
84 | end; | ||
85 | |||
86 | end; | ||
87 | |||
88 | |||
89 | kc = k; | ||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/willson_read.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/willson_read.m new file mode 100755 index 0000000..bbde63c --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/willson_read.m | |||
@@ -0,0 +1,59 @@ | |||
1 | % Read in Reg Willson's data file, and convert it into my data format: | ||
2 | |||
3 | %dir; | ||
4 | |||
5 | %calib_file = input('Reg Willson calibration file name: ','s'); | ||
6 | |||
7 | if exist(calib_file), | ||
8 | |||
9 | |||
10 | load(calib_file); | ||
11 | |||
12 | inddot = find(calib_file == '.'); | ||
13 | |||
14 | if isempty(inddot), | ||
15 | varname = calib_file; | ||
16 | else | ||
17 | varname = calib_file(1:inddot(1)-1); | ||
18 | end; | ||
19 | |||
20 | eval(['calib_params = ' varname ';']) | ||
21 | |||
22 | Ncx = calib_params(1); | ||
23 | Nfx = calib_params(2); | ||
24 | dx = calib_params(3); | ||
25 | dy = calib_params(4); | ||
26 | dpx = calib_params(5); | ||
27 | dpy = calib_params(6); | ||
28 | Cx = calib_params(7); | ||
29 | Cy = calib_params(8); | ||
30 | sx = calib_params(9); | ||
31 | f = calib_params(10); | ||
32 | kappa1 = calib_params(11); | ||
33 | Tx = calib_params(12); | ||
34 | Ty = calib_params(13); | ||
35 | Tz = calib_params(14); | ||
36 | Rx = calib_params(15); | ||
37 | Ry = calib_params(16); | ||
38 | Rz = calib_params(17); | ||
39 | p1 = calib_params(18); | ||
40 | p2 = calib_params(19); | ||
41 | |||
42 | % Conversion: | ||
43 | [fc,cc,kc,Rc_1,Tc_1,omc_1,nx,ny] = willson_convert(Ncx,Nfx,dx,dy,dpx,dpy,Cx,Cy,sx,f,kappa1,Tx,Ty,Tz,Rx,Ry,Rz,p1,p2); | ||
44 | |||
45 | KK = [fc(1) 0 cc(1);0 fc(2) cc(2) ; 0 0 1]; | ||
46 | |||
47 | n_ima = 1; | ||
48 | |||
49 | X_1 = [NaN;NaN;NaN]; | ||
50 | x_1 = [NaN;NaN]; | ||
51 | |||
52 | map = gray(256); | ||
53 | |||
54 | else | ||
55 | |||
56 | disp(['WARNING: Calibration file ' calib_file ' not found']); | ||
57 | |||
58 | end; | ||
59 | |||
diff --git a/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/writeras.m b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/writeras.m new file mode 100755 index 0000000..c7eb7bc --- /dev/null +++ b/SD-VBS/common/toolbox/toolbox_basic/TOOLBOX_calib/writeras.m | |||
@@ -0,0 +1,105 @@ | |||
1 | function writeras(filename, image, map); | ||
2 | %WRITERAS Write an image file in sun raster format. | ||
3 | % WRITERAS('imagefile.ras', image_matrix, map) writes a | ||
4 | % "sun.raster" image file. | ||
5 | |||
6 | % Written by Thomas K. Leung 3/30/93. | ||
7 | % @ California Institute of Technology. | ||
8 | |||
9 | |||
10 | % PC and UNIX version of writeras - Jean-Yves Bouguet - Dec. 1998 | ||
11 | |||
12 | dot = max(find(filename == '.')); | ||
13 | suffix = filename(dot+1:dot+3); | ||
14 | |||
15 | if nargin < 3, | ||
16 | map = []; | ||
17 | end; | ||
18 | |||
19 | if(strcmp(suffix, 'ras')) | ||
20 | %Write header | ||
21 | |||
22 | fp = fopen(filename, 'wb'); | ||
23 | if(fp < 0) error(['Cannot open ' filename '.']), end | ||
24 | |||
25 | [height, width] = size(image); | ||
26 | image = image - 1; | ||
27 | mapsize = size(map, 1)*size(map,2); | ||
28 | %fwrite(fp, ... | ||
29 | % [1504078485, width, height, 8, height*width, 1, 1, mapsize], ... | ||
30 | % 'long'); | ||
31 | |||
32 | |||
33 | zero_str = '00000000'; | ||
34 | |||
35 | % MAGIC NUMBER: | ||
36 | |||
37 | |||
38 | fwrite(fp,89,'uchar'); | ||
39 | fwrite(fp,166,'uchar'); | ||
40 | fwrite(fp,106,'uchar'); | ||
41 | fwrite(fp,149,'uchar'); | ||
42 | |||
43 | width_str = dec2hex(width); | ||
44 | width_str = [zero_str(1:8-length(width_str)) width_str]; | ||
45 | |||
46 | for ii = 1:2:7, | ||
47 | fwrite(fp,hex2dec(width_str(ii:ii+1)),'uchar'); | ||
48 | end; | ||
49 | |||
50 | |||
51 | height_str = dec2hex(height); | ||
52 | height_str = [zero_str(1:8-length(height_str)) height_str]; | ||
53 | |||
54 | for ii = 1:2:7, | ||
55 | fwrite(fp,hex2dec(height_str(ii:ii+1)),'uchar'); | ||
56 | end; | ||
57 | |||
58 | fwrite(fp,0,'uchar'); | ||
59 | fwrite(fp,0,'uchar'); | ||
60 | fwrite(fp,0,'uchar'); | ||
61 | fwrite(fp,8,'uchar'); | ||
62 | |||
63 | ll = height*width; | ||
64 | ll_str = dec2hex(ll); | ||
65 | ll_str = [zero_str(1:8-length(ll_str)) ll_str]; | ||
66 | |||
67 | for ii = 1:2:7, | ||
68 | fwrite(fp,hex2dec(ll_str(ii:ii+1)),'uchar'); | ||
69 | end; | ||
70 | |||
71 | fwrite(fp,0,'uchar'); | ||
72 | fwrite(fp,0,'uchar'); | ||
73 | fwrite(fp,0,'uchar'); | ||
74 | fwrite(fp,1,'uchar'); | ||
75 | fwrite(fp,0,'uchar'); | ||
76 | fwrite(fp,0,'uchar'); | ||
77 | fwrite(fp,0,'uchar'); | ||
78 | fwrite(fp,~~mapsize,'uchar'); | ||
79 | |||
80 | mapsize_str = dec2hex(mapsize); | ||
81 | mapsize_str = [zero_str(1:8-length(mapsize_str)) mapsize_str]; | ||
82 | |||
83 | %keyboard; | ||
84 | |||
85 | for ii = 1:2:7, | ||
86 | fwrite(fp,hex2dec(mapsize_str(ii:ii+1)),'uchar'); | ||
87 | end; | ||
88 | |||
89 | |||
90 | if mapsize ~= 0 | ||
91 | map = min(255, fix(255*map)); | ||
92 | fwrite(fp, map, 'uchar'); | ||
93 | end | ||
94 | if rem(width,2) == 1 | ||
95 | image = [image'; zeros(1, height)]'; | ||
96 | top = 255 * ones(size(image)); | ||
97 | fwrite(fp, min(top,image)', 'uchar'); | ||
98 | else | ||
99 | top = 255 * ones(size(image)); | ||
100 | fwrite(fp, min(top,image)', 'uchar'); | ||
101 | end | ||
102 | fclose(fp); | ||
103 | else | ||
104 | error('Image file name must end in either ''ras'' or ''rast''.'); | ||
105 | end | ||