PageRenderTime 360ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/Exercises/undistort/main.cpp

https://github.com/twelly/OpenCV
C++ | 250 lines | 222 code | 0 blank | 28 comment | 25 complexity | d89effa8f23c360934df2767061d65c2 MD5 | raw file
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <math.h>
  4. #include <cv.h>
  5. #include <highgui.h>
  6. #include <X11/Xlibint.h>
  7. #define CLIP2(minv, maxv, value) (min(maxv, max(minv, value)))
  8. CvMat* cvmGetCol(CvMat * src, int iCol){
  9. int i;
  10. int nRow = src->rows;
  11. CvMat *curCol = cvCreateMat(nRow,1,src->type);
  12. for (i=0; i<nRow; i++)
  13. cvmSet(curCol, i, 0, cvmGet(src, i, iCol));
  14. return curCol;
  15. }
  16. int main(int argc, char *argv[])
  17. {
  18. IplImage *img_in = 0, *img_affine = 0, *img_scene = 0, *img_interp = 0;;
  19. int height, width, step, channels;
  20. uchar *data_in, *data_affine, *data_scene, *data_interp;
  21. int i,j,k;
  22. double distp_x, distp_y;
  23. double tmpxp[50], tmpyp[50];
  24. int curpi, curpj;
  25. if (argc<2)
  26. {
  27. printf("Usage: main <image-file-name>\n\7");
  28. exit(0);
  29. }
  30. // X_c is the camera image, X_a is the affinely rectified image, X is the true
  31. // X_a = H_1*X_c X_a = H_2*X
  32. // load the distorted image X_c
  33. img_in = cvLoadImage(argv[1]);
  34. if (!img_in)
  35. {
  36. printf("Could not load image file: %s\n",argv[1]);
  37. exit(0);
  38. }
  39. height = img_in->height;
  40. width = img_in->width;
  41. step = img_in->widthStep;
  42. channels = img_in->nChannels;
  43. data_in = (uchar *)img_in->imageData;
  44. printf("Processing a %d x %d image with %d channels\n",height,width,channels);
  45. CvMat *check = cvCreateMat(height, width, CV_64FC1);
  46. cvZero(check);
  47. // allocate the output image and initialize
  48. img_affine = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, channels);
  49. img_scene = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, channels);
  50. cvZero(img_affine);
  51. cvZero(img_scene);
  52. data_affine = (uchar *)img_affine->imageData;
  53. data_scene = (uchar *)img_scene->imageData;
  54. // remove projective distortion
  55. CvMat * vetex = cvCreateMat(3,4,CV_64FC1);
  56. // get the coordinate values of four vetexes of a square
  57. // up-left, up-right, down-left, down-right
  58. for (i=0; i<4; i++)
  59. {
  60. printf("input the %d th point's coordinates (x',y') ", i);
  61. scanf("%f %f", &distp_x, &distp_y);
  62. distp_x = tmpxp[i];
  63. distp_y = tmpyp[i];
  64. cvmSet(vetex,0,i,distp_x);
  65. cvmSet(vetex,1,i,distp_y);
  66. cvmSet(vetex,2,i,1);
  67. printf("\n");
  68. }
  69. //************** Affine Rectification *****************
  70. CvMat *l1 = cvCreateMat(3,1,CV_64FC1);
  71. CvMat *l2 = cvCreateMat(3,1,CV_64FC1);
  72. CvMat *m1 = cvCreateMat(3,1,CV_64FC1);
  73. CvMat *m2 = cvCreateMat(3,1,CV_64FC1);
  74. CvMat *v1 = cvCreateMat(3,1,CV_64FC1);
  75. CvMat *v2 = cvCreateMat(3,1,CV_64FC1);
  76. CvMat *vanishL = cvCreateMat(3,1,CV_64FC1);
  77. cvCrossProduct(cvmGetCol(vetex,0), cvmGetCol(vetex,1), l1);
  78. cvCrossProduct(cvmGetCol(vetex,2), cvmGetCol(vetex,3), l2);
  79. cvCrossProduct(cvmGetCol(vetex,0), cvmGetCol(vetex,2), m1);
  80. cvCrossProduct(cvmGetCol(vetex,1), cvmGetCol(vetex,3), m2);
  81. cvCrossProduct(l1, l2, v1);
  82. cvCrossProduct(m1, m2, v2);
  83. cvCrossProduct(v1, v2, vanishL);
  84. // normalize vanishing line
  85. // in order to map the distorted image back to the image window
  86. double scale = 1.0;
  87. cvmSet(vanishL,0,0,cvmGet(vanishL,0,0)/cvmGet(vanishL,2,0)*scale);
  88. cvmSet(vanishL,1,0,cvmGet(vanishL,1,0)/cvmGet(vanishL,2,0)*scale);
  89. cvmSet(vanishL,2,0,1.0*scale);
  90. double H1data[] =
  91. {1,0,0,0,1,0,cvmGet(vanishL,0,0),cvmGet(vanishL,1,0),cvmGet(vanishL,2,0)};
  92. CvMat H1 = cvMat(3,3,CV_64FC1, H1data);
  93. // transform X_a = H_1*X_c
  94. CvMat * ptx = cvCreateMat(3,1,CV_64FC1);
  95. CvMat * ptxp = cvCreateMat(3,1,CV_64FC1);
  96. cvmSet(&H1,2,2,1.0);
  97. for (i=0; i<height; i++) //y - ver
  98. {
  99. for (j=0; j<width; j++) //x - hor
  100. {
  101. // set X_c
  102. cvmSet(ptxp,0,0,(double)j);
  103. cvmSet(ptxp,1,0,(double)i);
  104. cvmSet(ptxp,2,0,1.0);
  105. // compute X_a
  106. cvMatMul(&H1, ptxp, ptx);
  107. curpi = CLIP2(0, height-1, (int)(cvmGet(ptx,1,0)/cvmGet(ptx,2,0)));
  108. curpj = CLIP2(0, width-1, (int)(cvmGet(ptx,0,0)/cvmGet(ptx,2,0)));
  109. cvSet2D(img_affine,curpi,curpj,cvGet2D(img_in,i,j));
  110. cvmSet(check,curpi,curpj,1);
  111. }
  112. }
  113. // output reconstructed affine image
  114. img_interp = cvCloneImage(img_affine);
  115. data_interp = (uchar *)img_interp->imageData;
  116. //interpolation
  117. double count;
  118. for (i=1; i<height-1; i++) //y - ver
  119. {
  120. for (j=1; j<width-1; j++) //x - hor
  121. {
  122. if (cvmGet(check,i,j) == 0)
  123. {
  124. count = (cvmGet(check,i-1,j)==1)+(cvmGet(check,i+1,j)==1)+
  125. (cvmGet(check,i,j-1)==1)+(cvmGet(check,i,j+1)==1)+
  126. (cvmGet(check,i-1,j-1)==1)+(cvmGet(check,i-
  127. 1,j+1)==1)+
  128. (cvmGet(check,i+1,j-
  129. 1)==1)+(cvmGet(check,i+1,j+1)==1);
  130. if (count != 0)
  131. {
  132. for (k=0; k<channels; k++)
  133. data_interp[i*step+j*channels+k] = (int)
  134. ((data_affine[(i-
  135. 1)*step+j*channels+k]+data_affine[(i+1)*step+j*channels+k]
  136. +data_affine[i*step+(j-
  137. 1)*channels+k]+data_affine[i*step+(j+1)*channels+k]
  138. +data_affine[(i-1)*step+(j-
  139. 1)*channels+k]+data_affine[(i-1)*step+(j+1)*channels+k]
  140. +data_affine[(i+1)*step+(j-
  141. 1)*channels+k]+data_affine[(i+1)*step+(j+1)*channels+k])/count);
  142. }
  143. }
  144. }
  145. }
  146. img_affine = cvCloneImage(img_interp);
  147. if (!cvSaveImage("affine.jpg",img_affine))
  148. printf("Could not save file\n");
  149. //************** Metric Rectification *****************
  150. // transform points by H1
  151. CvMat *pt = cvCreateMat(3,1,CV_64FC1);
  152. for (i=0; i<4; i++)
  153. {
  154. cvMatMul(&H1, cvmGetCol(vetex,i), pt);
  155. cvmSet(vetex,0,i,(int)(cvmGet(pt,0,0)/cvmGet(pt,2,0)));
  156. cvmSet(vetex,1,i,(int)(cvmGet(pt,1,0)/cvmGet(pt,2,0)));
  157. cvmSet(vetex,2,i,1.0);
  158. }
  159. cvCrossProduct(cvmGetCol(vetex,0), cvmGetCol(vetex,1), l1);
  160. cvCrossProduct(cvmGetCol(vetex,0), cvmGetCol(vetex,2), m1);
  161. cvCrossProduct(cvmGetCol(vetex,0), cvmGetCol(vetex,3), l2);
  162. cvCrossProduct(cvmGetCol(vetex,2), cvmGetCol(vetex,1), m2);
  163. double l11, l12, m11, m12, l21, l22, m21, m22;
  164. l11 = cvmGet(l1,0,0); l12 = cvmGet(l1,1,0);
  165. l21 = cvmGet(l2,0,0); l22 = cvmGet(l2,1,0);
  166. m11 = cvmGet(m1,0,0); m12 = cvmGet(m1,1,0);
  167. m21 = cvmGet(m2,0,0); m22 = cvmGet(m2,1,0);
  168. // M*x = b
  169. double Mdata[] = {l11*m11, l11*m12+l12*m11, l21*m21, l21*m22+l22*m21};
  170. double bdata[] = {-l12*m12, -l22*m22};
  171. CvMat M = cvMat(2,2,CV_64FC1,Mdata);
  172. CvMat b = cvMat(2,1,CV_64FC1,bdata);
  173. CvMat *x = cvCreateMat(2,1,CV_64FC1);
  174. cvSolve(&M,&b,x);
  175. // Set matrix S
  176. double Sdata[] = {cvmGet(x,0,0), cvmGet(x,1,0), cvmGet(x,1,0), 1.0};
  177. CvMat S = cvMat(2,2,CV_64FC1, Sdata);
  178. // SVD S=UDV_T
  179. CvMat* U = cvCreateMat(2,2,CV_64FC1);
  180. CvMat* D = cvCreateMat(2,2,CV_64FC1);
  181. CvMat* V = cvCreateMat(2,2,CV_64FC1);
  182. cvSVD(&S, D, U, V, CV_SVD_U_T|CV_SVD_V_T);
  183. //The flags cause U and V to be returned transposed (does not work well
  184. //Therefore, in OpenCV, S = U^T D V
  185. CvMat* U_T = cvCreateMat(2,2,CV_64FC1);
  186. CvMat* sqrtD = cvCreateMat(2,2,CV_64FC1);
  187. CvMat* A = cvCreateMat(2,2,CV_64FC1);
  188. cvPow(D, sqrtD, 0.5);
  189. cvTranspose(U, U_T);
  190. cvMatMul(U_T, sqrtD, A);
  191. cvMatMul(A, V, A);
  192. // Set H2
  193. double t[] = {0, 0};
  194. double H2data[] = {cvmGet(A,0,0),cvmGet(A,0,1),t[0],
  195. cvmGet(A,1,0),cvmGet(A,1,1),t[1], 0,0,1};
  196. CvMat H2 = cvMat(3,3,CV_64FC1, H2data);
  197. CvMat *invH2 = cvCreateMat(3,3,CV_64FC1);
  198. cvInvert(&H2, invH2);
  199. cvZero(check);
  200. for (i=0; i<height; i++) //y - ver
  201. {
  202. for (j=0; j<width; j++) //x - hor
  203. {
  204. // set X_a
  205. cvmSet(ptxp,0,0,(double)j);
  206. cvmSet(ptxp,1,0,(double)i);
  207. cvmSet(ptxp,2,0,1.0);
  208. // compute X
  209. cvMatMul(invH2, ptxp, ptx);
  210. curpi = CLIP2(0, height-1, (int)(cvmGet(ptx,1,0)/cvmGet(ptx,2,0)));
  211. curpj = CLIP2(0, width-1, (int)(cvmGet(ptx,0,0)/cvmGet(ptx,2,0)));
  212. cvSet2D(img_scene,curpi,curpj,cvGet2D(img_affine,i,j));
  213. cvmSet(check,curpi,curpj,1);
  214. }
  215. }
  216. // output reconstructed scene image
  217. img_interp = cvCloneImage(img_scene);
  218. data_interp = (uchar *)img_interp->imageData;
  219. //interpolation
  220. for (i=1; i<height-1; i++) //y - ver
  221. {
  222. for (j=1; j<width-1; j++) //x - hor
  223. {
  224. if (cvmGet(check,i,j) == 0)
  225. {
  226. count = (cvmGet(check,i-
  227. 1,j)==1)+(cvmGet(check,i+1,j)==1)+(cvmGet(check,i,j-
  228. 1)==1)+(cvmGet(check,i,j+1)==1);
  229. if (count != 0 )
  230. {
  231. for (k=0; k<channels; k++)
  232. {
  233. data_interp[i*step+j*channels+k] =
  234. (int)((data_scene[(i-
  235. 1)*step+j*channels+k]+data_scene[(i+1)*step+j*channels+k]+data_scene[i*step+(j-
  236. 1)*channels+k]+data_scene[i*step+(j+1)*channels+k])/count);
  237. }
  238. }
  239. }
  240. }
  241. }
  242. if (!cvSaveImage("scene.jpg",img_interp))
  243. printf("Could not save file\n");
  244. // release the image
  245. cvReleaseImage(&img_in);
  246. cvReleaseImage(&img_affine);
  247. cvReleaseImage(&img_scene);
  248. cvReleaseImage(&img_interp);
  249. return 0;
  250. }