PageRenderTime 150ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/slam6d/trunk-external/src/scanner/david_scanner.cc

https://github.com/AsherBond/MondocosmOS
C++ | 628 lines | 457 code | 82 blank | 89 comment | 66 complexity | c67da63ce137fa473e9d035c20dd6e81 MD5 | raw file
  1. /*
  2. * david_scanner.cc
  3. * Program takes as an input path to the config file which needs to have all the necessary information for the program.
  4. * Config file has to have (each on a new line, 9 lines in total):
  5. *
  6. * Path to the directory where frames from the video are stored
  7. * The first frame that has to be used
  8. * The last frame that has to be used
  9. * The empty frame without the laser
  10. * Path to the file with intrinsics of the camera
  11. * Path to the rotation of the left board
  12. * Path to the rotation of the right board
  13. * Path to the translation of the left board
  14. * Path to the translation of the right board
  15. *
  16. * Program computes the 3 point cloud of the object and stores it in the file scan000.3d, each point in the cloud is represented by the line in the file:
  17. * x y z r g b
  18. *
  19. *
  20. * Created on: Oct 4, 2010
  21. * Author: Vladislav Perelman v.perelman@jacobs-university.de
  22. */
  23. #include <iostream>
  24. #include <string>
  25. #include <fstream>
  26. #include <cv.h>
  27. #include <highgui.h>
  28. #include <cvaux.h>
  29. #include <cxcore.h>
  30. #include <math.h>
  31. #include <vector>
  32. #define PI 3.14159265
  33. using namespace std;
  34. int main(int argc, char** argv){
  35. if (argc!=2){
  36. cout<<"USAGE: david_scanner config_file\nConfig file should contain path_to_frames first_valid_frame last_valid_frame empty_frame path_to_intrinsics"
  37. "path_to_rotation_left path_to_rotation_right path_to_translation_left and path_to_translation_right each on a new line!"<<endl;
  38. return -1;
  39. }
  40. //******Reading Input********
  41. ifstream indata;
  42. indata.open(argv[1]);
  43. if (!indata){
  44. cout<<"Config file could not be opened"<<endl;
  45. return -1;
  46. }
  47. string line;
  48. int numlines=0;
  49. while( getline(indata, line) ) numlines++;
  50. if (numlines != 9) {
  51. cout<<"Invalid number of lines in a config file!\nConfig file should contain path_to_frames first_valid_frame last_valid_frame empty_frame path_to_intrinsics"
  52. "path_to_rotation_left path_to_rotation_right path_to_translation_left and path_to_translation_right each on a new line!";
  53. return -1;
  54. }
  55. indata.clear();
  56. indata.seekg(0);
  57. char path[200];
  58. indata.getline(path,200);
  59. char first_c[10];
  60. char last_c[10];
  61. char empty_c[10];
  62. indata.getline(first_c,10);
  63. indata.getline(last_c,10);
  64. indata.getline(empty_c,10);
  65. int first = atoi(first_c);
  66. int last = atoi(last_c);
  67. int empty = atoi(empty_c);
  68. char intrinsics_path[200];
  69. char rot_left[200];
  70. char rot_right[200];
  71. char tran_left[200];
  72. char tran_right[200];
  73. indata.getline(intrinsics_path,200);
  74. indata.getline(rot_left,200);
  75. indata.getline(rot_right,200);
  76. indata.getline(tran_left,200);
  77. indata.getline(tran_right,200);
  78. //*********done************
  79. //loading an empty frame
  80. IplImage* image_empty;
  81. IplImage* image;
  82. char empty_name[100];
  83. sprintf(empty_name,"%s/%08d.ppm",path,empty);
  84. if ((image_empty=cvLoadImage(empty_name,1))==NULL){
  85. cout<<"Cannot load empty frame...check input name"<<endl;
  86. return -1;
  87. }
  88. //*******LOADING CAMERA PARAMETERS + CREATING MATRICES FOR FUTURE USE*********
  89. CvMat *intrinsic = cvCreateMat(3,3,CV_32F);
  90. if ((intrinsic = (CvMat*)cvLoad( intrinsics_path ))==NULL){
  91. cout<<"Cannot load intrinsic parameters...check input path and file name"<<endl;
  92. return -1;
  93. }
  94. //loading R1
  95. CvMat* rotation_left = cvCreateMat(3,1,CV_32F);
  96. if ((rotation_left = (CvMat*)cvLoad( rot_left ))==NULL){
  97. cout<<"Cannot load rotation of the left board...check input"<<endl;
  98. return -1;
  99. }
  100. //loading T1
  101. CvMat* translation_left = cvCreateMat(3,1,CV_32F);
  102. if ((translation_left= (CvMat*)cvLoad( tran_left ))==NULL){
  103. cout<<"Cannot load translation of the left board...check input"<<endl;
  104. return -1;
  105. }
  106. CvMat* rotation_matrix_left = cvCreateMat( 3, 3, CV_32F );
  107. cvRodrigues2(rotation_left, rotation_matrix_left);
  108. //loading R2
  109. CvMat* rotation_right = cvCreateMat(3,1,CV_32F);
  110. if ((rotation_right = (CvMat*)cvLoad( rot_right ))==NULL){
  111. cout<<"Cannot load rotation of the right board...check input"<<endl;
  112. return -1;
  113. }
  114. //loading T2
  115. CvMat* translation_right = cvCreateMat(3,1,CV_32F);
  116. if((translation_right=(CvMat*)cvLoad( tran_right ))==NULL){
  117. cout<<"Cannot load translation of the right board...check input"<<endl;
  118. return -1;
  119. }
  120. CvMat* rotation_matrix_right = cvCreateMat( 3, 3, CV_32F );
  121. cvRodrigues2(rotation_right, rotation_matrix_right);
  122. //creating [R1|T1]
  123. CvMat* r1t1 = cvCreateMat( 3, 4, CV_32F );
  124. for (int i = 0; i < 3; i++){
  125. CV_MAT_ELEM( *r1t1, float, i, 0) = CV_MAT_ELEM( *rotation_matrix_left, float, i, 0);
  126. CV_MAT_ELEM( *r1t1, float, i, 1) = CV_MAT_ELEM( *rotation_matrix_left, float, i, 1);
  127. CV_MAT_ELEM( *r1t1, float, i, 2) = CV_MAT_ELEM( *rotation_matrix_left, float, i, 2);
  128. CV_MAT_ELEM( *r1t1, float, i, 3) = CV_MAT_ELEM( *translation_left, float, i, 0);
  129. }
  130. //creating [R2|T2]
  131. CvMat* r2t2 = cvCreateMat( 3, 4, CV_32F );
  132. for (int i = 0; i < 3; i++){
  133. CV_MAT_ELEM( *r2t2, float, i, 0) = CV_MAT_ELEM( *rotation_matrix_right, float, i, 0);
  134. CV_MAT_ELEM( *r2t2, float, i, 1) = CV_MAT_ELEM( *rotation_matrix_right, float, i, 1);
  135. CV_MAT_ELEM( *r2t2, float, i, 2) = CV_MAT_ELEM( *rotation_matrix_right, float, i, 2);
  136. CV_MAT_ELEM( *r2t2, float, i, 3) = CV_MAT_ELEM( *translation_right, float, i, 0);
  137. }
  138. //creating R1.i()
  139. CvMat* r1inv = cvCreateMat( 3, 3, CV_32F );
  140. cvInvert(rotation_matrix_left, r1inv);
  141. //creating A.i()
  142. CvMat* intrinsicinv = cvCreateMat( 3, 3, CV_32F );
  143. cvInvert(intrinsic, intrinsicinv);
  144. //creating R1.i()*A.i()
  145. CvMat* R1iAi = cvCreateMat( 3, 3, CV_32F );
  146. cvMatMul(r1inv, intrinsicinv, R1iAi);
  147. //creating R2.i()
  148. CvMat* r2inv = cvCreateMat( 3, 3, CV_32F );
  149. cvInvert(rotation_matrix_right, r2inv, CV_LU);
  150. //creating R2.i()*A.i()
  151. CvMat* R2iAi = cvCreateMat( 3, 3, CV_32F );
  152. cvMatMul(r2inv, intrinsicinv, R2iAi);
  153. //creating R1.i()*T1
  154. CvMat* a1 = cvCreateMat(3, 1, CV_32F);
  155. cvMatMul(r1inv, translation_left, a1);
  156. //creating R2.i()*T2
  157. CvMat* a2 = cvCreateMat(3, 1, CV_32F);
  158. cvMatMul(r2inv, translation_right, a2);
  159. //*****************DONE********************
  160. //open file for writing
  161. ofstream scanfile;
  162. char scanname[10];
  163. sprintf(scanname,"scan000.3d");
  164. scanfile.open(scanname);
  165. //for loop going through each frame in the provided folder between first_valid_frame and last_valid_frame
  166. for (int m=first; m<last; m++){
  167. char name[100];
  168. sprintf(name, "%s/%08d.ppm", path,m);
  169. cout<<name<<endl;
  170. if ((image =cvLoadImage(name))==NULL){
  171. cout<<"cannot load image: "<<name<<endl;
  172. continue;
  173. }
  174. //do difference between current frame and the empty frame with no laser
  175. IplImage* diff = cvCloneImage(image);
  176. cvAbsDiff(image_empty, image, diff);
  177. //focus on the red pixels, make others black
  178. unsigned char* pixels = (unsigned char*)diff->imageData;
  179. for (int row = 0; row < diff->height; row++){
  180. for (int col = 0; col < diff->width; col++){
  181. int R;
  182. R = pixels[ row * diff->widthStep + col * 3 + 2 ];
  183. if (R>30) {
  184. pixels[ row * diff->widthStep + col * 3 + 0 ] = 0;
  185. pixels[ row * diff->widthStep + col * 3 + 1 ] = 0;
  186. pixels[ row * diff->widthStep + col * 3 + 2 ] = 255;
  187. } else {
  188. pixels[ row * diff->widthStep + col * 3 + 0 ] = 0;
  189. pixels[ row * diff->widthStep + col * 3 + 1 ] = 0;
  190. pixels[ row * diff->widthStep + col * 3 + 2 ] = 0;
  191. }
  192. }
  193. }
  194. //remove pixels that don't have at least 2 red neighbors
  195. for (int row = 1; row < diff->height-1; row++){
  196. for (int col = 1; col < diff->width-1; col++){
  197. int R = pixels[ row * diff->widthStep + col * 3 + 2 ];
  198. if (R == 255){
  199. int r1 = pixels[ (row-1)*diff->widthStep + col * 3 + 2];
  200. int r2 = pixels[ (row-1)*diff->widthStep + (col-1) * 3 + 2];
  201. int r3 = pixels[ (row-1)*diff->widthStep + (col+1) * 3 + 2];
  202. int r4 = pixels[ (row+1)*diff->widthStep + col * 3 + 2];
  203. int r5 = pixels[ (row+1)*diff->widthStep + (col-1) * 3 + 2];
  204. int r6 = pixels[ (row+1)*diff->widthStep + (col+1) * 3 + 2];
  205. int r7 = pixels[ (row)*diff->widthStep + (col-1) * 3 + 2];
  206. int r8 = pixels[ (row)*diff->widthStep + (col+1) * 3 + 2];
  207. if (r1+r2+r3+r4+r5+r6+r7+r8<=255) pixels[ row * diff->widthStep + col * 3 + 2 ]=0;
  208. }
  209. }
  210. }
  211. //*****finding 2 lines on the image*****
  212. bool good = false;
  213. int threshold = 50; //original threshold for Hough transform, incremented if too many groups of lines found
  214. IplImage* color_dst;
  215. IplImage* tmpImage;
  216. int minX1, minX2, maxX1, maxX2;
  217. CvSeq* lines = 0;
  218. CvPoint* line1;
  219. CvPoint* line2;
  220. int count_groups;
  221. //incrementing thresholds until only 2 groups of lines can be found
  222. while(!good){
  223. good = true;
  224. count_groups = 0; //counter for number of line groups. Line group is defined by the slope
  225. int epsilon = 1.5; //error margin for the slope
  226. color_dst = cvCreateImage( cvGetSize(diff), 8, 3 );
  227. color_dst = cvCloneImage(diff);
  228. tmpImage = cvCreateImage(cvGetSize(diff), IPL_DEPTH_8U, 1);
  229. cvCvtColor(diff, tmpImage, CV_RGB2GRAY);
  230. IplImage* dst = cvCreateImage( cvGetSize(diff), 8, 1 );
  231. cvCanny(tmpImage, dst, 20, 60, 3 );
  232. CvMemStorage* storage = cvCreateMemStorage(0);
  233. //find all lines using Hough transform
  234. lines = cvHoughLines2( dst, storage, CV_HOUGH_PROBABILISTIC, 1, CV_PI/180,threshold, 150, 100 );
  235. double first_group, second_group;
  236. for(int i = 0; i < lines->total; i++ ){
  237. //get the slope of the line, check if it belongs to an already existing group
  238. CvPoint* line = (CvPoint*)cvGetSeqElem(lines,i);
  239. double angle = atan((double)(line[1].x-line[0].x)/(double)(line[1].y-line[0].y))*180/PI;
  240. //starting first group
  241. if (count_groups==0){
  242. first_group = angle;
  243. line1 = line;
  244. minX1 = line[0].x;
  245. maxX1 = line[1].x;
  246. count_groups++;
  247. } else {
  248. if (angle-first_group<epsilon && angle-first_group>(epsilon*-1)){
  249. //line belongs to the first group of line..that's good
  250. if (line[0].x<minX1)minX1=line[0].x;
  251. if (line[1].x>maxX1)maxX1=line[1].x;
  252. } else {
  253. //check if belongs to the second group
  254. if ( count_groups == 2 ){
  255. if (angle-second_group<epsilon && angle - second_group>(epsilon*-1)){
  256. if (line[0].x<minX2)minX2=line[0].x;
  257. if (line[1].x>maxX2)maxX2=line[1].x;
  258. }else{
  259. //if not then try again with a higher threshold
  260. good = false;
  261. threshold+=20;
  262. cout<<"Increased threshold: "<<threshold<<" ";
  263. cvReleaseImage(&color_dst);
  264. cvReleaseImage(&tmpImage);
  265. cvReleaseImage(&dst);
  266. break; //get out of here and increase the threshold since too many lines were found
  267. }
  268. } else { //starting second group
  269. second_group = angle;
  270. minX2 = line[0].x;
  271. maxX2 = line[1].x;
  272. line2 = line;
  273. count_groups++;
  274. }
  275. }
  276. }
  277. }
  278. //freeing some memory along the way
  279. cvReleaseMemStorage(&storage);
  280. cvReleaseImage(&dst);
  281. }
  282. //at this point we have found at most 2 groups of lines, we need to take only 1 line from each group
  283. //basically finding the left-most and right-most point of each group and draw a line between those points, removing all the other lines.
  284. //starting and ending points of 2 lines
  285. CvPoint point1;
  286. CvPoint point2;
  287. CvPoint point3;
  288. CvPoint point4;
  289. if (count_groups==2){
  290. int x1 = line1[0].x;
  291. int x2 = line1[1].x;
  292. int y1 = line1[0].y;
  293. int y2 = line1[1].y;
  294. double c1 = (double)(x1 - minX1)/(double)(x2 - minX1);
  295. double c2 = (double)(maxX1 - x1)/(double)(maxX1 - x2);
  296. int ymax, ymin;
  297. ymin = (c1*y2 - y1)/(c1-1);
  298. ymax = (c2*y2 - y1)/(c2-1);
  299. if (maxX1 == x2) ymax = y2;
  300. if (minX1 == x1) ymin = y1;
  301. //getting start and end of the first line
  302. point1 = cvPoint(minX1, ymin);
  303. point2 = cvPoint(maxX1, ymax);
  304. //points around all the lines in a group so that a black rectangle can be drawn above them
  305. CvPoint points[4];
  306. points[0]=cvPoint(minX1, max(0,ymin-10));
  307. points[1]=cvPoint(minX1, min(color_dst->height,ymin+10));
  308. points[2]=cvPoint(maxX1, min(color_dst->height,ymax+10));
  309. points[3]=cvPoint(maxX1, max(0,ymax-10));
  310. CvPoint* pts[1];
  311. pts[0]=points;
  312. int npts[1];
  313. npts[0]=4;
  314. cvPolyLine(color_dst, pts, npts,1,1, CV_RGB(0,0,0), 20, 8 );//removing the group
  315. x1 = line2[0].x;
  316. x2 = line2[1].x;
  317. y1 = line2[0].y;
  318. y2 = line2[1].y;
  319. c1 = (double)(x1 - minX2)/(double)(x2 - minX2);
  320. c2 = (double)(maxX2 - x1)/(double)(maxX2 - x2);
  321. ymin = (c1*y2 - y1)/(c1-1);
  322. ymax = (c2*y2 - y1)/(c2-1);
  323. if (maxX2 == x2) ymax = y2;
  324. if (minX2 == x1) ymin = y1;
  325. //getting start and end of the second line
  326. point3 = cvPoint(minX2, ymin);
  327. point4 = cvPoint(maxX2, ymax);
  328. points[0]=cvPoint(minX2, max(0,ymin-10));
  329. points[1]=cvPoint(minX2, min(color_dst->height,ymin+10));
  330. points[2]=cvPoint(maxX2, min(color_dst->height,ymax+10));
  331. points[3]=cvPoint(maxX2, max(0,ymax-10));
  332. pts[0]=points;
  333. cvPolyLine(color_dst, pts, npts,1,1, CV_RGB(0,0,0), 20, 8 );//removing the group
  334. cvLine(color_dst, point3, point4,CV_RGB(0,255,0),3, 8 ); //draw the second line!
  335. cvLine(color_dst, point1, point2,CV_RGB(0,255,0),3, 8 ); //draw the first line!
  336. //removing everything to the left of the left line and to the right of the right line
  337. if (point4.x > point2.x){
  338. if (color_dst->width > point4.x){
  339. cvRectangle(color_dst,cvPoint(point4.x,0),cvPoint(color_dst->width,color_dst->height),CV_RGB(0,0,0),CV_FILLED);
  340. }
  341. if (point1.x > 0){
  342. cvRectangle(color_dst,cvPoint(point1.x,0),cvPoint(0,color_dst->height),CV_RGB(0,0,0),CV_FILLED);
  343. }
  344. }
  345. if (point4.x < point2.x){
  346. if (color_dst->width > point2.x){
  347. cvRectangle(color_dst,cvPoint(point2.x,0),cvPoint(color_dst->width,color_dst->height),CV_RGB(0,0,0),CV_FILLED);
  348. }
  349. if (point3.x > 0){
  350. cvRectangle(color_dst,cvPoint(point3.x,0),cvPoint(0,color_dst->height),CV_RGB(0,0,0),CV_FILLED);
  351. }
  352. }
  353. //at this point we have to lines which we drew in green...which means all the red pixels that remain on the image
  354. //are supposed to be laying on the object. Make them blue (for no particular reason..just looked nicer :) )
  355. unsigned char* pixels = (unsigned char*)color_dst->imageData;
  356. for (int row = 1; row < color_dst->height-1; row++){
  357. for (int col = 1; col < color_dst->width-1; col++){
  358. int R = pixels[ row * color_dst->widthStep + col * 3 + 2 ];
  359. if (R == 255){
  360. pixels[ row * color_dst->widthStep + col * 3 + 0 ]=255;
  361. pixels[ row * color_dst->widthStep + col * 3 + 1 ]=0;
  362. pixels[ row * color_dst->widthStep + col * 3 + 2 ]=0;
  363. }
  364. }
  365. }
  366. } else continue;
  367. //take points on planes
  368. CvPoint left1, left2, right1;
  369. if (point1.x < point3.x){
  370. left1 = point1;
  371. left2 = point2;
  372. right1 = point3;
  373. } else {
  374. left1 = point3;
  375. left2 = point4;
  376. right1 = point1;
  377. }
  378. //find 3d coordinate of the 2 points on the line on the left plane
  379. //(x,y,z).t() = s*R.i()*A.i()*(u,v,1).t() - R.i()*T
  380. CvMat* imagepoint1 = cvCreateMat( 3, 1, CV_32F );
  381. CV_MAT_ELEM(*imagepoint1, float, 0, 0) = left1.x;
  382. CV_MAT_ELEM(*imagepoint1, float, 1, 0) = left1.y;
  383. CV_MAT_ELEM(*imagepoint1, float, 2, 0) = 1;
  384. CvMat* b1 = cvCreateMat(3, 1, CV_32F);
  385. cvMatMul(R1iAi, imagepoint1, b1);
  386. //calculate scalar s based on the fact that point we take is on the wall => z coordinate is 0
  387. float s1 = CV_MAT_ELEM(*a1, float, 2, 0)/CV_MAT_ELEM(*b1, float, 2, 0);
  388. CvMat* identity = cvCreateMat(3,3,CV_32F);
  389. cvSetIdentity(identity);
  390. for (int i = 0; i < 3; i++){
  391. CV_MAT_ELEM(*identity, float, i, i)=s1;
  392. }
  393. CvMat* temp = cvCreateMat(3,1,CV_32F);
  394. cvMatMul(identity,b1, temp);
  395. CvMat* dpoint1 = cvCreateMat(3,1,CV_32F);
  396. cvSub(temp, a1, dpoint1); //first 3d point on the left plane
  397. //same thing for the second point
  398. CvMat* imagepoint2 = cvCreateMat( 3, 1, CV_32F );
  399. CV_MAT_ELEM(*imagepoint2, float, 0, 0) = left2.x;
  400. CV_MAT_ELEM(*imagepoint2, float, 1, 0) = left2.y;
  401. CV_MAT_ELEM(*imagepoint2, float, 2, 0) = 1;
  402. CvMat* b2 = cvCreateMat(3, 1, CV_32F);
  403. cvMatMul(R1iAi, imagepoint2, b2);
  404. float s2 = CV_MAT_ELEM(*a1, float, 2, 0)/CV_MAT_ELEM(*b2, float, 2, 0);
  405. cvSetIdentity(identity, cvRealScalar(s2));
  406. cvMatMul(identity,b2, b2);
  407. CvMat* dpoint2 = cvCreateMat(3,1,CV_32F);
  408. cvSub(b2, a1, dpoint2); //second 3d point on the left plane
  409. //same for the point on the right plane
  410. CvMat* imagepoint3 = cvCreateMat( 3, 1, CV_32F );
  411. CV_MAT_ELEM(*imagepoint3, float, 0, 0) = right1.x;
  412. CV_MAT_ELEM(*imagepoint3, float, 1, 0) = right1.y;
  413. CV_MAT_ELEM(*imagepoint3, float, 2, 0) = 1;
  414. CvMat* b3 = cvCreateMat(3, 1, CV_32F);
  415. cvMatMul(R2iAi, imagepoint3, b3);
  416. float s3 = CV_MAT_ELEM(*a2, float, 2, 0)/CV_MAT_ELEM(*b3, float, 2, 0);
  417. cvSetIdentity(identity, cvRealScalar(s3));
  418. cvMatMul(identity,b3, b3);
  419. CvMat* dpoint3 = cvCreateMat(3,1,CV_32F);
  420. cvSub(b3, a2, dpoint3); //point on the right plane
  421. //convert point from the right plane into the coord. system of the left plane
  422. //p1 = R1.i()*[R2|T2]*p2 - R1.i()*T1
  423. CvMat* dpoint3left = cvCreateMat(3,1,CV_32F);
  424. CvMat* pw = cvCreateMat(4,1,CV_32F);
  425. for (int i = 0; i<3; i++){
  426. CV_MAT_ELEM(*pw, float, i, 0) = CV_MAT_ELEM(*dpoint3, float, i, 0);
  427. }
  428. CV_MAT_ELEM(*pw, float, 3, 0) = 1.0;
  429. CvMat* r2t2pw = cvCreateMat(3,1,CV_32F);
  430. cvMatMul(r2t2, pw, r2t2pw);
  431. CvMat* r1invr2t2pw = cvCreateMat(3,1,CV_32F);
  432. cvMatMul(r1inv, r2t2pw, r1invr2t2pw);
  433. cvSub(r1invr2t2pw, a1, dpoint3left);
  434. //now that we have 3 non-colinear point in the same coordinate system we can find the equation of the plane
  435. /*
  436. A = y1 (z2 - z3) + y2 (z3 - z1) + y3 (z1 - z2)
  437. B = z1 (x2 - x3) + z2 (x3 - x1) + z3 (x1 - x2)
  438. C = x1 (y2 - y3) + x2 (y3 - y1) + x3 (y1 - y2)
  439. - D = x1 (y2 z3 - y3 z2) + x2 (y3 z1 - y1 z3) + x3 (y1 z2 - y2 z1)
  440. */
  441. float x1 = CV_MAT_ELEM(*dpoint1, float,0,0);
  442. float y1 = CV_MAT_ELEM(*dpoint1, float,1,0);
  443. float z1 = CV_MAT_ELEM(*dpoint1, float,2,0);
  444. float x2 = CV_MAT_ELEM(*dpoint2, float,0,0);
  445. float y2 = CV_MAT_ELEM(*dpoint2, float,1,0);
  446. float z2 = CV_MAT_ELEM(*dpoint2, float,2,0);
  447. float x3 = CV_MAT_ELEM(*dpoint3left, float,0,0);
  448. float y3 = CV_MAT_ELEM(*dpoint3left, float,1,0);
  449. float z3 = CV_MAT_ELEM(*dpoint3left, float,2,0);
  450. float planeA = (y1 * (z2 - z3)) + (y2 * (z3 - z1)) + (y3 * (z1 - z2));
  451. float planeB = (z1 * (x2 - x3)) + (z2 * (x3 - x1)) + (z3 * (x1 - x2));
  452. float planeC = (x1 * (y2 - y3)) + (x2 * (y3 - y1)) + (x3 * (y1 - y2));
  453. float planeD = -((x1 * (y2 * z3 - y3 * z2)) + (x2 * (y3 * z1 - y1 * z3)) + (x3 * (y1 * z2 - y2 * z1)));
  454. //calculate normal to the lazer plane
  455. CvMat* planeNormal = cvCreateMat(3, 1, CV_32F);
  456. CV_MAT_ELEM(*planeNormal, float,0,0) = planeA;
  457. CV_MAT_ELEM(*planeNormal, float,1,0) = planeB;
  458. CV_MAT_ELEM(*planeNormal, float,2,0) = planeC;
  459. pixels = (unsigned char*)color_dst->imageData;
  460. unsigned char* color_pixels = (unsigned char*)image_empty->imageData;
  461. //go through all the pixels on the object and calculate the 3d coordinate
  462. for (int row = 1; row < color_dst->height-1; row++){
  463. for (int col = 1; col < color_dst->width-1; col++){
  464. int B = pixels[ row * color_dst->widthStep + col * 3];
  465. if (B == 255){
  466. //get RGB of the pixel on the original image
  467. int realB = color_pixels[ row * color_dst->widthStep + col * 3];
  468. int realG = color_pixels[ row * color_dst->widthStep + col * 3 + 1];
  469. int realR = color_pixels[ row * color_dst->widthStep + col * 3 + 2];
  470. //Used http://www.cs.princeton.edu/courses/archive/fall00/cs426/lectures/raycast/sld017.htm for reference
  471. //on how to find intersection of ray and a plane
  472. float p0dotN = cvDotProduct(a1,planeNormal);
  473. CvMat* vtmp = cvCreateMat(3,1,CV_32F);
  474. CV_MAT_ELEM(*vtmp, float,0,0) = col;
  475. CV_MAT_ELEM(*vtmp, float,1,0) = row;
  476. CV_MAT_ELEM(*vtmp, float,2,0) = 1;
  477. CvMat* v = cvCreateMat(3,1,CV_32F);
  478. cvMatMul(R1iAi, vtmp, v);
  479. float vdotN = cvDotProduct(v,planeNormal);
  480. float t = (p0dotN - planeD)/vdotN;
  481. cvSetIdentity(identity, cvRealScalar(t));
  482. cvMatMul(identity,v,v);
  483. CvMat* final = cvCreateMat(3,1,CV_32F);
  484. cvSub(v,a1,final); //final point is still in the coordinate system of the left plane.
  485. CvMat* final_rotated = cvCreateMat(3,1,CV_32F); //translate it into the coordinate system of the camera
  486. cvMatMul(rotation_matrix_left,final,final_rotated);
  487. cvAdd(final_rotated,translation_left, final_rotated);
  488. //add point to the file (minus next to the y coordinate is there to compensate for the left-handed coordinate system of slam6d, otherwise
  489. //dwarf is shown upside-down.
  490. scanfile<<CV_MAT_ELEM(*final_rotated,float,0,0)<<" "<<-CV_MAT_ELEM(*final_rotated,float,1,0)<<" "<<CV_MAT_ELEM(*final_rotated,float,2,0)<<
  491. " "<< realR<<" "<<realG<<" "<<realB<<"\n";
  492. cvReleaseMat(&vtmp);
  493. cvReleaseMat(&v);
  494. cvReleaseMat(&final);
  495. cvReleaseMat(&final_rotated);
  496. }
  497. }
  498. }
  499. //save the image of the lines and points of the object
  500. char name2[100];
  501. sprintf(name2, "%s/%08d_diff.ppm", path,m);
  502. cvSaveImage(name2, color_dst);
  503. //free memory
  504. cvReleaseImage(&image);
  505. cvReleaseImage(&diff);
  506. cvReleaseImage(&color_dst);
  507. cvReleaseImage(&tmpImage);
  508. cvReleaseMat(&imagepoint1);
  509. cvReleaseMat(&imagepoint2);
  510. cvReleaseMat(&imagepoint3);
  511. cvReleaseMat(&b1);
  512. cvReleaseMat(&b2);
  513. cvReleaseMat(&b3);
  514. cvReleaseMat(&temp);
  515. cvReleaseMat(&dpoint1);
  516. cvReleaseMat(&dpoint2);
  517. cvReleaseMat(&dpoint3);
  518. cvReleaseMat(&dpoint3left);
  519. cvReleaseMat(&identity);
  520. cvReleaseMat(&pw);
  521. cvReleaseMat(&r2t2pw);
  522. cvReleaseMat(&r1invr2t2pw);
  523. cvReleaseMat(&planeNormal);
  524. }
  525. //free more memory
  526. cvReleaseImage(&image_empty);
  527. cvReleaseMat(&intrinsic);
  528. cvReleaseMat(&intrinsicinv);
  529. cvReleaseMat(&rotation_left);
  530. cvReleaseMat(&rotation_matrix_left);
  531. cvReleaseMat(&rotation_right);
  532. cvReleaseMat(&rotation_matrix_right);
  533. cvReleaseMat(&translation_left);
  534. cvReleaseMat(&translation_right);
  535. cvReleaseMat(&r1inv);
  536. cvReleaseMat(&r2inv);
  537. cvReleaseMat(&R1iAi);
  538. cvReleaseMat(&R2iAi);
  539. cvReleaseMat(&r1t1);
  540. cvReleaseMat(&r2t2);
  541. cvReleaseMat(&a1);
  542. cvReleaseMat(&a2);
  543. //close file
  544. scanfile.close();
  545. return 0;
  546. }