基于matlab标定数据,使用opencv实现双目立体摄像头的标定(源代码)

来源:互联网 发布:时间旅行者 知乎 编辑:程序博客网 时间:2024/04/30 03:21

我参考了这几位大牛的博客,受益匪浅:

http://blog.csdn.net/sunanger_wang/article/details/7744025

http://www.opencv.org.cn/forum.php?mod=viewthread&tid=12963

http://blog.csdn.net/scyscyao/article/details/5562024

http://blog.csdn.net/chenyusiyuan/article/details/5967291

最后那位有连续三篇的内容进行了详细的介绍,非常棒。


由于看到那些博客下面的一些问题都没人回答,那些算是细节,但大家知道有时候就是这么一点小时会卡很久。

再好的解释也没源代码和示例图来的快,小弟就把这几天摸索的内容放上来。

我的平台:2个罗技C170摄像头


嘿嘿。。比较简陋



matlab标定:

    相信仔细看过原理以及上面的博客就能用matlab计算出双目的结果,这儿有一点要注意,就是要计算双目参数,左右两个摄像头必须同时拍摄棋盘格,一共20张!我一开始是单独拍摄,后来发现单目的数据可以标定出来,双目的就会报错,,想想原理也是,双目标定必须是同时拍摄的才行呀。这儿贴一段自己写的同时采集图像的代码,按下c,就能保存图像。

[cpp] view plain copy
  1. #include <opencv2/opencv.hpp>    
  2. #include <iostream>    
  3. using namespace std;    
  4.   
  5. int pic_num = 13;  
  6. char* name_l = (char*)malloc(sizeof(char)*200);  
  7. char* name_r = (char*)malloc(sizeof(char)*200);  
  8. int main()    
  9. {    
  10.     cout << "测试两个摄像头同时读取数据" << endl;    
  11.   
  12.     CvCapture* cap_left;    
  13.     CvCapture* cap_right;    
  14.   
  15.     IplImage *img0 , *img1;    
  16.     IplImage *img_left, *img_right;    
  17.     IplImage *img_left_Change, *img_right_Change;    
  18.     cvNamedWindow("camera_left");    
  19.     cvNamedWindow("camera_right");    
  20.   
  21.   
  22.     cap_left = cvCreateCameraCapture(1);    
  23.     assert(cap_left != NULL);    
  24.     cap_right = cvCreateCameraCapture(0);    
  25.     assert(cap_right != NULL);    
  26.   
  27.     while(1)    
  28.     {    
  29.         cvGrabFrame(cap_left);  
  30.         cvGrabFrame(cap_right);  
  31.   
  32.         img0 = cvRetrieveFrame(cap_left);//img0 1 只是指针,这个可以在单独的采图线程里刷新  
  33.         img1 = cvRetrieveFrame(cap_right);  
  34.   
  35.         if( !img0 || !img1)  
  36.         {    
  37.             cout << "camera0 error" << endl;    
  38.             break;    
  39.         }    
  40.   
  41.         img_left = cvCloneImage(img0);  
  42.         img_right = cvCloneImage(img1);  
  43.   
  44.         cvShowImage("camera_left", img_left);    
  45.         cvShowImage("camera_right", img_right);    
  46.   
  47.         char c = cvWaitKey(33);    
  48.   
  49.         if(c == 27)     
  50.             break;    
  51.         if(c == 'c')  
  52.         {  
  53.             sprintf(name_l, "leftPic%d.jpg", pic_num);  
  54.             sprintf(name_r, "rightPic%d.jpg", pic_num);  
  55.             pic_num++;  
  56.   
  57.             cvSaveImage(name_l, img_left);  
  58.             cvSaveImage(name_r, img_right);  
  59.   
  60.         }  
  61.         cvReleaseImage(&img_left);  
  62.         cvReleaseImage(&img_right);  
  63.     }    
  64.     cvReleaseCapture(&cap_left);    
  65.     cvReleaseCapture(&cap_right);    
  66.    
  67.     cvDestroyWindow("camera_left");    
  68.     cvDestroyWindow("camera_right");    
  69.    
  70.     return 0;    
  71.   
  72. }    
顺便唠叨一句,在循环里cvReleaseImage(&img_left);cvReleaseImage(&img_right);必须执行,否则会出现内存泄露。。不信的话就打开资源管理器,注释掉这两句程序运行时就看得到占用内存在不断上升!


OpenCV上场:

因为大多数人都推荐使用matlab标定箱,那下一步就是将标定的数据存到xml文件里。xml不了解的请自行百度。

由于有些人一直在问怎么写文件,我这儿就把所有要自己写的文件都贴出来:

Intrinsics_Camera_Left.xml:

[html] view plain copy
  1. <?xml version="1.0"?>  
  2. <opencv_storage>  
  3. <Intrinsics_Camera_Left type_id="opencv-matrix">  
  4.   <rows>3</rows>  
  5.   <cols>3</cols>  
  6.   <dt>d</dt>  
  7.   <data>  
  8.   690.09102   0.         325.38988   
  9.   0.          686.25294  286.9196   
  10.   0.          0.         1.  
  11. </data>  
  12. </Intrinsics_Camera_Left>  
  13. </opencv_storage>  

Intrinsics_Camera_Right.xml:
[html] view plain copy
  1. <?xml version="1.0"?>  
  2. <opencv_storage>  
  3. <Intrinsics_Camera_Right type_id="opencv-matrix">  
  4.   <rows>3</rows>  
  5.   <cols>3</cols>  
  6.   <dt>d</dt>  
  7.   <data>  
  8.   691.94410   0.          342.74569   
  9.   0.          685.94161   231.16984   
  10.   0.          0.          1.  
  11.   </data>  
  12. </Intrinsics_Camera_Right>  
  13. </opencv_storage>  

Distortion_Camera_Left.xml:
[html] view plain copy
  1. <?xml version="1.0"?>  
  2. <opencv_storage>  
  3. <Distortion type_id="opencv-matrix">  
  4.   <rows>5</rows>  
  5.   <cols>1</cols>  
  6.   <dt>d</dt>  
  7.   <data>  
  8.     -0.02240   -0.05900   0.00894   -0.00590  0.00000  
  9. </data>  
  10. </Distortion>  
  11. </opencv_storage>  

Distortion_Camera_Right.xml:
[html] view plain copy
  1. <?xml version="1.0"?>  
  2. <opencv_storage>  
  3. <Distortion type_id="opencv-matrix">  
  4.   <rows>5</rows>  
  5.   <cols>1</cols>  
  6.   <dt>d</dt>  
  7.   <data>  
  8.     0.05543   -0.29862   -0.00669   0.01307  0.00000  
  9. </data>  
  10. </Distortion>  
  11. </opencv_storage>  

Translation.xml
[html] view plain copy
  1. <?xml version="1.0"?>  
  2. <opencv_storage>  
  3. <Translation type_id="opencv-matrix">  
  4.   <rows>3</rows>  
  5.   <cols>1</cols>  
  6.   <dt>d</dt>  
  7.   <data>  
  8.    -194.10083   6.39147  -11.45062  
  9. </data>  
  10. </Translation>  
  11. </opencv_storage>  

RotRodrigues.xml
[html] view plain copy
  1. <?xml version="1.0"?>  
  2. <opencv_storage>  
  3. <RotRodrigues type_id="opencv-matrix">  
  4.   <rows>3</rows>  
  5.   <cols>1</cols>  
  6.   <dt>d</dt>  
  7.   <data>  
  8.    -0.06416   -0.11879  -0.07601  
  9. </data>  
  10. </RotRodrigues>  
  11. </opencv_storage>  


将这些分别保存下来,里面的内容是根据matlab的结果写进去的。


下一步就是立体图像矫正了。具体原理请看之前的博客,非常详细!

小弟这儿就贴一下代码,让各位能更好地理解:

[cpp] view plain copy
  1. #include <opencv2/opencv.hpp>    
  2. #include <iostream>    
  3.   
  4. using namespace std;    
  5.   
  6. int main()    
  7. {    
  8.     cout << "测试两个摄像头同时读取数据" << endl;    
  9.   
  10.     //读取内部参数  
  11.     CvMat *Intrinsics_Camera_Left = (CvMat *)cvLoad("Intrinsics_Camera_Left.xml");  
  12.     CvMat *Intrinsics_Camera_Right = (CvMat *)cvLoad("Intrinsics_Camera_Right.xml");  
  13.     CvMat *Distortion_Camera_Left = (CvMat *)cvLoad("Distortion_Camera_Left.xml");  
  14.         CvMat *Distortion_Camera_Right = (CvMat *)cvLoad("Distortion_Camera_Right.xml");  
  15.     CvMat *Translation_matlab = (CvMat *)cvLoad("Translation.xml");  
  16.     CvMat *RotRodrigues_matlab = (CvMat *)cvLoad("RotRodrigues.xml");  
  17.     CvMat *R_opencv = cvCreateMat(3, 3, CV_64F);  
  18.     cvRodrigues2(RotRodrigues_matlab, R_opencv);  
  19.   
  20.     //创建映射阵  
  21.     IplImage *Left_Mapx = cvCreateImage(cvSize(640,480), IPL_DEPTH_32F, 1);  
  22.     IplImage *Left_Mapy = cvCreateImage(cvSize(640,480), IPL_DEPTH_32F, 1);  
  23.     IplImage *Right_Mapx = cvCreateImage(cvSize(640,480), IPL_DEPTH_32F, 1);  
  24.     IplImage *Right_Mapy = cvCreateImage(cvSize(640,480), IPL_DEPTH_32F, 1);  
  25.     CvMat *Rl = cvCreateMat(3, 3, CV_64F);  
  26.     CvMat *Rr = cvCreateMat(3, 3, CV_64F);  
  27.     CvMat *Pl = cvCreateMat(3, 4, CV_64F);  
  28.     CvMat *Pr = cvCreateMat(3, 4, CV_64F);  
  29.     //cvStereoRectify(Intrinsics_Camera_Left, Intrinsics_Camera_Right, \  
  30.                     Distortion_Camera_Left, Distortion_Camera_Right, \  
  31.                     cvSize(640, 480), R_opencv, Translation_matlab,  \  
  32.                     Rl, Rr, Pl, Pr);  
  33.     cvStereoRectify(Intrinsics_Camera_Left, Intrinsics_Camera_Right, \  
  34.         Distortion_Camera_Left, Distortion_Camera_Right, \  
  35.         cvSize(640, 480), R_opencv, Translation_matlab,  \  
  36.         Rl, Rr, Pl, Pr, 0, 1024, 0);//增加图像缩放,去除死区  
  37.     cvInitUndistortRectifyMap(Intrinsics_Camera_Left, Distortion_Camera_Left, Rl, Pl, \  
  38.                               Left_Mapx, Left_Mapy);  
  39.     cvInitUndistortRectifyMap(Intrinsics_Camera_Right, Distortion_Camera_Right, Rr, Pr, \  
  40.                               Right_Mapx, Right_Mapy);  
  41.   
  42.     CvCapture* cap_left;    
  43.     CvCapture* cap_right;    
  44.   
  45.     IplImage *img0 , *img1;    
  46.     IplImage *img_left, *img_right;    
  47.     IplImage *img_left_Change, *img_right_Change;    
  48.     cvNamedWindow("camera_left");    
  49.     cvNamedWindow("camera_right");    
  50.   
  51.     cap_left = cvCreateCameraCapture(1);    
  52.     assert(cap_left != NULL);    
  53.     cap_right = cvCreateCameraCapture(0);    
  54.     assert(cap_right != NULL);    
  55.   
  56.     while(1)    
  57.     {    
  58.         cvGrabFrame(cap_left);  
  59.         cvGrabFrame(cap_right);  
  60.   
  61.         img0 = cvRetrieveFrame(cap_left);  
  62.         img1 = cvRetrieveFrame(cap_right);  
  63.   
  64.         if( !img0 || !img1)  
  65.         {    
  66.             cout << "camera0 error" << endl;    
  67.             break;    
  68.         }    
  69.   
  70.         img_left = cvCloneImage(img0);  
  71.         img_right = cvCloneImage(img1);  
  72.         img_left_Change = cvCloneImage(img0);  
  73.         img_right_Change = cvCloneImage(img1);  
  74.         cvRemap(img_left, img_left_Change, Left_Mapx, Left_Mapy);  
  75.         cvRemap(img_right, img_right_Change, Right_Mapx, Right_Mapy);  
  76.   
  77.         cvLine(img_left_Change, cvPoint(0,48), cvPoint(640-1, 48), cvScalar(255, 0, 0));  
  78.         cvLine(img_left_Change, cvPoint(0,48*2), cvPoint(640-1, 48*2), cvScalar(255, 0, 0));  
  79.         cvLine(img_left_Change, cvPoint(0,48*3), cvPoint(640-1, 48*3), cvScalar(255, 0, 0));  
  80.         cvLine(img_left_Change, cvPoint(0,48*4), cvPoint(640-1, 48*4), cvScalar(255, 0, 0));  
  81.         cvLine(img_left_Change, cvPoint(0,48*5), cvPoint(640-1, 48*5), cvScalar(255, 0, 0));  
  82.         cvLine(img_left_Change, cvPoint(0,48*6), cvPoint(640-1, 48*6), cvScalar(255, 0, 0));  
  83.         cvLine(img_left_Change, cvPoint(0,48*7), cvPoint(640-1, 48*7), cvScalar(255, 0, 0));  
  84.         cvLine(img_left_Change, cvPoint(0,48*8), cvPoint(640-1, 48*8), cvScalar(255, 0, 0));  
  85.         cvLine(img_left_Change, cvPoint(0,48*9), cvPoint(640-1, 48*9), cvScalar(255, 0, 0));  
  86.         cvLine(img_right_Change, cvPoint(0,48), cvPoint(640-1, 48), cvScalar(255, 0, 0));  
  87.         cvLine(img_right_Change, cvPoint(0,48*2), cvPoint(640-1, 48*2), cvScalar(255, 0, 0));  
  88.         cvLine(img_right_Change, cvPoint(0,48*3), cvPoint(640-1, 48*3), cvScalar(255, 0, 0));  
  89.         cvLine(img_right_Change, cvPoint(0,48*4), cvPoint(640-1, 48*4), cvScalar(255, 0, 0));  
  90.         cvLine(img_right_Change, cvPoint(0,48*5), cvPoint(640-1, 48*5), cvScalar(255, 0, 0));  
  91.         cvLine(img_right_Change, cvPoint(0,48*6), cvPoint(640-1, 48*6), cvScalar(255, 0, 0));  
  92.         cvLine(img_right_Change, cvPoint(0,48*7), cvPoint(640-1, 48*7), cvScalar(255, 0, 0));  
  93.         cvLine(img_right_Change, cvPoint(0,48*8), cvPoint(640-1, 48*8), cvScalar(255, 0, 0));  
  94.         cvLine(img_right_Change, cvPoint(0,48*9), cvPoint(640-1, 48*9), cvScalar(255, 0, 0));  
  95.   
  96.         cvShowImage("camera_left", img_left);    
  97.         cvShowImage("camera_right", img_right);    
  98.         cvShowImage("camera_left_Change", img_left_Change);    
  99.         cvShowImage("camera_right_Change", img_right_Change);    
  100.   
  101.         char c = cvWaitKey(33);    
  102.         if(c == 27)     
  103.             break;    
  104.   
  105.         cvReleaseImage(&img_left);  
  106.         cvReleaseImage(&img_right);  
  107.         cvReleaseImage(&img_left_Change);  
  108.         cvReleaseImage(&img_right_Change);  
  109.   
  110.     }    
  111.   
  112.     cvReleaseCapture(&cap_left);    
  113.     cvReleaseCapture(&cap_right);    
  114.     cvDestroyWindow("camera_left");    
  115.     cvDestroyWindow("camera_right");    
  116.    
  117.     return 0;    
  118.   
  119. }    


cvStereoRectify可以在最后加上参数,去除黑色的死区。





有些博客里提到位移向量为什么是负的,并且说要修改为正数,比如我这儿是<pre name="code" class="html"> -194.10083   6.39147  -11.45062

第一项要改为194.10083 ,我不是很理解,程序里没有修改,但是结果还是正确的。

最后再次感谢上面提到的各位博主!


原文地址:http://blog.csdn.net/u010566411/article/details/44150361

0 0
原创粉丝点击