/registration.c

https://github.com/Kinect5/ICP · C · 332 lines · 242 code · 44 blank · 46 comment · 13 complexity · fa6298ad4b914bc81ee7347d554a34d8 MD5 · raw file

  1. //
  2. // Copyright (C) 2009 ViGIR Lab (http://vigir.missouri.edu)
  3. // Written by Guilherme N. DeSouza <desouzag@missouri.edu>
  4. //
  5. //
  6. /*
  7. * June 2001, Johnny Park
  8. *
  9. * June 2003,
  10. *
  11. */
  12. #include "registration.h"
  13. extern int window_main_anc,
  14. window_main_mov;
  15. extern rdata_vis *rd_anc; // array of "anchor" range data
  16. extern rdata_vis *rd_mov; // array of "moving" range data
  17. extern int *corres_rd_anc,
  18. *corres_rd_mov,
  19. *corres_pt_anc,
  20. *corres_pt_mov;
  21. extern int num_rdata_anc,
  22. num_rdata_mov,
  23. num_corres_anc,
  24. num_corres_mov;
  25. extern double new_M[16];
  26. /*
  27. * Peform a course registration using selected corresponding points by user
  28. */
  29. void CourseRegistration(void)
  30. {
  31. register int i;
  32. double Sxx, Sxy, Sxz,
  33. Syx, Syy, Syz,
  34. Szx, Szy, Szz;
  35. double max_eval;
  36. point_xyz *p, *q;
  37. point_xyz mean_corres_p,
  38. mean_corres_q;
  39. int num_corres;
  40. matrix *Q, *R;
  41. vector *max_evec, *t;
  42. // initialize values
  43. Sxx = Sxy = Sxz = Syx = Syy = Syz = Szx = Szy = Szz = 0.0;
  44. mean_corres_p.x = mean_corres_p.y = mean_corres_p.z = 0.0;
  45. mean_corres_q.x = mean_corres_q.y = mean_corres_q.z = 0.0;
  46. // take the smaller one
  47. num_corres = (num_corres_anc<num_corres_mov)?num_corres_anc:num_corres_mov;
  48. // allocate memory
  49. Q = AllocateMatrix(4, 4);
  50. R = AllocateMatrix(3, 3);
  51. max_evec = AllocateVector(4);
  52. t = AllocateVector(3);
  53. p = (point_xyz *) malloc (num_corres * sizeof(point_xyz));
  54. q = (point_xyz *) malloc (num_corres * sizeof(point_xyz));
  55. // transform
  56. for (i=0; i<num_corres; i++) {
  57. p[i].x = (rd_mov[corres_rd_mov[i]].xyz[3*corres_pt_mov[i]] *
  58. rd_mov[corres_rd_mov[i]].M[0]) +
  59. (rd_mov[corres_rd_mov[i]].xyz[3*corres_pt_mov[i]+1] *
  60. rd_mov[corres_rd_mov[i]].M[4]) +
  61. (rd_mov[corres_rd_mov[i]].xyz[3*corres_pt_mov[i]+2] *
  62. rd_mov[corres_rd_mov[i]].M[8]) +
  63. rd_mov[corres_rd_mov[i]].M[12];
  64. p[i].y = (rd_mov[corres_rd_mov[i]].xyz[3*corres_pt_mov[i]] *
  65. rd_mov[corres_rd_mov[i]].M[1]) +
  66. (rd_mov[corres_rd_mov[i]].xyz[3*corres_pt_mov[i]+1] *
  67. rd_mov[corres_rd_mov[i]].M[5]) +
  68. (rd_mov[corres_rd_mov[i]].xyz[3*corres_pt_mov[i]+2] *
  69. rd_mov[corres_rd_mov[i]].M[9]) +
  70. rd_mov[corres_rd_mov[i]].M[13];
  71. p[i].z = (rd_mov[corres_rd_mov[i]].xyz[3*corres_pt_mov[i]] *
  72. rd_mov[corres_rd_mov[i]].M[2]) +
  73. (rd_mov[corres_rd_mov[i]].xyz[3*corres_pt_mov[i]+1] *
  74. rd_mov[corres_rd_mov[i]].M[6]) +
  75. (rd_mov[corres_rd_mov[i]].xyz[3*corres_pt_mov[i]+2] *
  76. rd_mov[corres_rd_mov[i]].M[10]) +
  77. rd_mov[corres_rd_mov[i]].M[14];
  78. q[i].x = (rd_anc[corres_rd_anc[i]].xyz[3*corres_pt_anc[i]] *
  79. rd_anc[corres_rd_anc[i]].M[0]) +
  80. (rd_anc[corres_rd_anc[i]].xyz[3*corres_pt_anc[i]+1] *
  81. rd_anc[corres_rd_anc[i]].M[4]) +
  82. (rd_anc[corres_rd_anc[i]].xyz[3*corres_pt_anc[i]+2] *
  83. rd_anc[corres_rd_anc[i]].M[8]) +
  84. rd_anc[corres_rd_anc[i]].M[12];
  85. q[i].y = (rd_anc[corres_rd_anc[i]].xyz[3*corres_pt_anc[i]] *
  86. rd_anc[corres_rd_anc[i]].M[1]) +
  87. (rd_anc[corres_rd_anc[i]].xyz[3*corres_pt_anc[i]+1] *
  88. rd_anc[corres_rd_anc[i]].M[5]) +
  89. (rd_anc[corres_rd_anc[i]].xyz[3*corres_pt_anc[i]+2] *
  90. rd_anc[corres_rd_anc[i]].M[9]) +
  91. rd_anc[corres_rd_anc[i]].M[13];
  92. q[i].z = (rd_anc[corres_rd_anc[i]].xyz[3*corres_pt_anc[i]] *
  93. rd_anc[corres_rd_anc[i]].M[2]) +
  94. (rd_anc[corres_rd_anc[i]].xyz[3*corres_pt_anc[i]+1] *
  95. rd_anc[corres_rd_anc[i]].M[6]) +
  96. (rd_anc[corres_rd_anc[i]].xyz[3*corres_pt_anc[i]+2] *
  97. rd_anc[corres_rd_anc[i]].M[10]) +
  98. rd_anc[corres_rd_anc[i]].M[14];
  99. //printf("%d: %f %f %f\n", i, q[i].x, q[i].y, q[i].z);
  100. }
  101. for (i=0; i<num_corres; i++) {
  102. mean_corres_p.x += p[i].x;
  103. mean_corres_p.y += p[i].y;
  104. mean_corres_p.z += p[i].z;
  105. mean_corres_q.x += q[i].x;
  106. mean_corres_q.y += q[i].y;
  107. mean_corres_q.z += q[i].z;
  108. }
  109. mean_corres_p.x /= (double)num_corres;
  110. mean_corres_p.y /= (double)num_corres;
  111. mean_corres_p.z /= (double)num_corres;
  112. mean_corres_q.x /= (double)num_corres;
  113. mean_corres_q.y /= (double)num_corres;
  114. mean_corres_q.z /= (double)num_corres;
  115. for (i=0; i<num_corres; i++) {
  116. Sxx += p[i].x * q[i].x;
  117. Sxy += p[i].x * q[i].y;
  118. Sxz += p[i].x * q[i].z;
  119. Syx += p[i].y * q[i].x;
  120. Syy += p[i].y * q[i].y;
  121. Syz += p[i].y * q[i].z;
  122. Szx += p[i].z * q[i].x;
  123. Szy += p[i].z * q[i].y;
  124. Szz += p[i].z * q[i].z;
  125. }
  126. Sxx = Sxx / (double)num_corres - (mean_corres_p.x * mean_corres_q.x);
  127. Sxy = Sxy / (double)num_corres - (mean_corres_p.x * mean_corres_q.y);
  128. Sxz = Sxz / (double)num_corres - (mean_corres_p.x * mean_corres_q.z);
  129. Syx = Syx / (double)num_corres - (mean_corres_p.y * mean_corres_q.x);
  130. Syy = Syy / (double)num_corres - (mean_corres_p.y * mean_corres_q.y);
  131. Syz = Syz / (double)num_corres - (mean_corres_p.y * mean_corres_q.z);
  132. Szx = Szx / (double)num_corres - (mean_corres_p.z * mean_corres_q.x);
  133. Szy = Szy / (double)num_corres - (mean_corres_p.z * mean_corres_q.y);
  134. Szz = Szz / (double)num_corres - (mean_corres_p.z * mean_corres_q.z);
  135. // construct N
  136. Q->entry[0][0] = Sxx + Syy + Szz;
  137. Q->entry[1][0] = Q->entry[0][1] = Syz - Szy;
  138. Q->entry[2][0] = Q->entry[0][2] = Szx - Sxz;
  139. Q->entry[3][0] = Q->entry[0][3] = Sxy - Syx;
  140. Q->entry[1][1] = Sxx - Syy - Szz;
  141. Q->entry[1][2] = Q->entry[2][1] = Sxy + Syx;
  142. Q->entry[1][3] = Q->entry[3][1] = Szx + Sxz;
  143. Q->entry[2][2] = -Sxx + Syy - Szz;
  144. Q->entry[2][3] = Q->entry[3][2] = Syz + Szy;
  145. Q->entry[3][3] = -Sxx - Syy + Szz;
  146. // --- compute largest eigenvalues and eigenvectors of Q ---
  147. SymmetricLargestEigens(Q, max_evec, &max_eval);
  148. // make sure max_evec[0] > 0
  149. if (max_evec->entry[0] < 0) {
  150. for (i=0; i<4; i++) max_evec->entry[i] *= -1.0;
  151. }
  152. // --- compute rotation matrix ---
  153. RotationQuaternion(max_evec, R);
  154. // --- compute translation vector ---
  155. t->entry[0] = mean_corres_q.x -
  156. R->entry[0][0] * mean_corres_p.x -
  157. R->entry[0][1] * mean_corres_p.y -
  158. R->entry[0][2] * mean_corres_p.z;
  159. t->entry[1] = mean_corres_q.y -
  160. R->entry[1][0] * mean_corres_p.x -
  161. R->entry[1][1] * mean_corres_p.y -
  162. R->entry[1][2] * mean_corres_p.z;
  163. t->entry[2] = mean_corres_q.z -
  164. R->entry[2][0] * mean_corres_p.x -
  165. R->entry[2][1] * mean_corres_p.y -
  166. R->entry[2][2] * mean_corres_p.z;
  167. //PrintMatrix(R);
  168. //PrintVector(t);
  169. new_M[0] = R->entry[0][0]; new_M[4] = R->entry[0][1]; new_M[8] = R->entry[0][2];
  170. new_M[1] = R->entry[1][0]; new_M[5] = R->entry[1][1]; new_M[9] = R->entry[1][2];
  171. new_M[2] = R->entry[2][0]; new_M[6] = R->entry[2][1]; new_M[10] = R->entry[2][2];
  172. new_M[12] = t->entry[0]; new_M[13] = t->entry[1]; new_M[14] = t->entry[2];
  173. new_M[3] = new_M[7] = new_M[11] = 0; new_M[15] = 1;
  174. // free memory
  175. FreeMatrix(Q); FreeMatrix(R);
  176. FreeVector(max_evec); FreeVector(t);
  177. free(p); free(q);
  178. }
  179. /*
  180. * Perfrom a fine registration using the ICP algorithm
  181. */
  182. void FineRegistration(void)
  183. {
  184. int i, j, count;
  185. int num_p, num_q;
  186. point_xyz *p, *q, cp;
  187. matrix *R;
  188. vector *t;
  189. double Mf[16];
  190. // compute total number of points
  191. num_p = num_q = 0;
  192. for (i=0; i<num_rdata_anc; i++) num_q += rd_anc[i].num_pt;
  193. for (i=0; i<num_rdata_mov; i++) num_p += rd_mov[i].num_pt;
  194. // allocate memory
  195. R = AllocateMatrix(3, 3);
  196. t = AllocateVector(3);
  197. p = (point_xyz *) malloc (num_p * sizeof(point_xyz));
  198. q = (point_xyz *) malloc (num_q * sizeof(point_xyz));
  199. // copy xyz values
  200. count = 0;
  201. for (i=0; i<num_rdata_anc; i++) {
  202. for (j=0; j<rd_anc[i].num_pt; j++) {
  203. cp.x = rd_anc[i].xyz[3*j];
  204. cp.y = rd_anc[i].xyz[3*j+1];
  205. cp.z = rd_anc[i].xyz[3*j+2];
  206. // transform with its modeling transformation matrix
  207. q[count].x = cp.x * rd_anc[i].M[0] + cp.y * rd_anc[i].M[4] +
  208. cp.z * rd_anc[i].M[8] + rd_anc[i].M[12];
  209. q[count].y = cp.x * rd_anc[i].M[1] + cp.y * rd_anc[i].M[5] +
  210. cp.z * rd_anc[i].M[9] + rd_anc[i].M[13];
  211. q[count].z = cp.x * rd_anc[i].M[2] + cp.y * rd_anc[i].M[6] +
  212. cp.z * rd_anc[i].M[10] + rd_anc[i].M[14];
  213. count++;
  214. }
  215. }
  216. count = 0;
  217. for (i=0; i<num_rdata_mov; i++) {
  218. // use modelview just for matrix multiplication
  219. glMatrixMode(GL_MODELVIEW);
  220. glPushMatrix();
  221. glLoadIdentity();
  222. glMultMatrixd(new_M);
  223. glMultMatrixd(rd_mov[i].M);
  224. glGetDoublev(GL_MODELVIEW_MATRIX, Mf);
  225. glPopMatrix();
  226. for (j=0; j<rd_mov[i].num_pt; j++) {
  227. // transform
  228. cp.x = rd_mov[i].xyz[3*j];
  229. cp.y = rd_mov[i].xyz[3*j+1];
  230. cp.z = rd_mov[i].xyz[3*j+2];
  231. p[count].x = cp.x*Mf[0] + cp.y*Mf[4] + cp.z*Mf[8] + Mf[12];
  232. p[count].y = cp.x*Mf[1] + cp.y*Mf[5] + cp.z*Mf[9] + Mf[13];
  233. p[count].z = cp.x*Mf[2] + cp.y*Mf[6] + cp.z*Mf[10] + Mf[14];
  234. count++;
  235. }
  236. }
  237. // perform ICP
  238. //ICPalgorithm(R, t, p, num_p, q, num_q, 5, 5.0, 100, 0.10, 0.0005);
  239. ICPalgorithm(R, t, p, num_p, q, num_q, 5, 5.0, 1000, 0.010, 0.000005);
  240. Mf[0] = R->entry[0][0]; Mf[4] = R->entry[0][1]; Mf[8] = R->entry[0][2];
  241. Mf[1] = R->entry[1][0]; Mf[5] = R->entry[1][1]; Mf[9] = R->entry[1][2];
  242. Mf[2] = R->entry[2][0]; Mf[6] = R->entry[2][1]; Mf[10] = R->entry[2][2];
  243. Mf[12] = t->entry[0]; Mf[13] = t->entry[1]; Mf[14] = t->entry[2];
  244. Mf[3] = Mf[7] = Mf[11] = 0; Mf[15] = 1;
  245. // update new_M
  246. glMatrixMode(GL_MODELVIEW);
  247. glPushMatrix();
  248. glLoadIdentity();
  249. glMultMatrixd(Mf);
  250. glMultMatrixd(new_M);
  251. glGetDoublev(GL_MODELVIEW_MATRIX, new_M);
  252. glPopMatrix();
  253. // free memory
  254. FreeMatrix(R); FreeVector(t);
  255. free(p); free(q);
  256. }
  257. /*
  258. * Save registration result
  259. */
  260. void SaveRegistration(void)
  261. {
  262. FILE *fp;
  263. char outfile[256];
  264. int i;
  265. glutSetWindow(window_main_mov);
  266. glMatrixMode(GL_MODELVIEW);
  267. for (i=0; i<num_rdata_mov; i++) {
  268. // update modeling matrix
  269. glPushMatrix();
  270. glLoadIdentity();
  271. glMultMatrixd(new_M);
  272. glMultMatrixd(rd_mov[i].M);
  273. glGetDoublev(GL_MODELVIEW_MATRIX, rd_mov[i].M);
  274. glPopMatrix();
  275. // write to .Rt file
  276. sprintf(outfile, "%s.Rt", rd_mov[i].filename);
  277. fp = fopen(outfile, "w");
  278. fprintf(fp, "%f %f %f\n", rd_mov[i].M[0], rd_mov[i].M[4], rd_mov[i].M[8]);
  279. fprintf(fp, "%f %f %f\n", rd_mov[i].M[1], rd_mov[i].M[5], rd_mov[i].M[9]);
  280. fprintf(fp, "%f %f %f\n", rd_mov[i].M[2], rd_mov[i].M[6], rd_mov[i].M[10]);
  281. fprintf(fp, "%f %f %f\n", rd_mov[i].M[12], rd_mov[i].M[13],
  282. rd_mov[i].M[14]);
  283. fclose(fp);
  284. }
  285. // set new_M to a identity matrix
  286. for (i=0; i<16; i++) new_M[i] = 0;
  287. new_M[0] = new_M[5] = new_M[10] = new_M[15] = 1;
  288. }