4回答

0收藏

[原创] 【Khadas VIM试用】双目视觉运行能力测试2

#拆解/开源硬件 #拆解/开源硬件 5445 人阅读 | 4 人回复 | 2018-02-08

(一)
根据上一张帖子标定的结果:
  1. Mat cameraMatrixL = (Mat_<double>(3, 3) << 274.07311, 0, 334.46683,
  2.                      0, 273.77609, 230.80436,
  3.                      0, 0, 1);
  4. Mat distCoeffL = (Mat_<double>(5, 1) << -0.21470, 0.03484, -0.00121, -0.00279, 0.00000);

  5. Mat cameraMatrixR = (Mat_<double>(3, 3) << 284.34939, 0, 283.30332,
  6.                      0, 285.84734, 243.33090,
  7.                      0, 0, 1);
  8. Mat distCoeffR = (Mat_<double>(5, 1) << -0.21396, 0.03400, -0.00154, 0.00204, 0.00000);

  9. Mat T = (Mat_<double>(3, 1) << -90.67152, -2.93721, 16.09332);//T平移向量
  10. Mat rec = (Mat_<double>(3, 1) << 0.02428, 0.15673, -0.00825);//rec旋转向量
  11. Mat R;//R 旋转矩阵
复制代码
带入双目测距程序里面:
  1. /******************************/
  2. /*        立体匹配和测距        */
  3. /******************************/

  4. #include <opencv2/opencv.hpp>
  5. #include <imgproc.hpp>
  6. #include <iostream>
  7. #include <time.h>

  8. using namespace std;
  9. using namespace cv;

  10. const int imageWidth = 640;                             //摄像头的分辨率
  11. const int imageHeight = 480;
  12. Size imageSize = Size(imageWidth, imageHeight);

  13. Mat rgbImageL, grayImageL;
  14. Mat rgbImageR, grayImageR;
  15. Mat rectifyImageL, rectifyImageR;

  16. Rect validROIL;//图像校正之后,会对图像进行裁剪,这里的validROI就是指裁剪之后的区域
  17. Rect validROIR;

  18. Mat mapLx, mapLy, mapRx, mapRy;     //映射表
  19. Mat Rl, Rr, Pl, Pr, Q;              //校正旋转矩阵R,投影矩阵P 重投影矩阵Q
  20. Mat xyz;              //三维坐标

  21. Point origin;         //鼠标按下的起始点
  22. Rect selection;      //定义矩形选框
  23. bool selectObject = false;    //是否选择对象

  24. int blockSize = 0, uniquenessRatio =0, numDisparities=0;
  25. Ptr<StereoBM> bm = StereoBM::create(16, 9);

  26. /*
  27. 事先标定好的相机的参数
  28. fx 0 cx
  29. 0 fy cy
  30. 0 0  1
  31. */
  32. Mat cameraMatrixL = (Mat_<double>(3, 3) << 274.07311, 0, 334.46683,
  33.                      0, 273.77609, 230.80436,
  34.                      0, 0, 1);
  35. Mat distCoeffL = (Mat_<double>(5, 1) << -0.21470, 0.03484, -0.00121, -0.00279, 0.00000);

  36. Mat cameraMatrixR = (Mat_<double>(3, 3) << 284.34939, 0, 283.30332,
  37.                      0, 285.84734, 243.33090,
  38.                      0, 0, 1);
  39. Mat distCoeffR = (Mat_<double>(5, 1) << -0.21396, 0.03400, -0.00154, 0.00204, 0.00000);

  40. Mat T = (Mat_<double>(3, 1) << -90.67152, -2.93721, 16.09332);//T平移向量
  41. Mat rec = (Mat_<double>(3, 1) << 0.02428, 0.15673, -0.00825);//rec旋转向量
  42. Mat R;//R 旋转矩阵


  43. /*Mat cameraMatrixL = (Mat_<double>(3, 3) << 268.0870787552206, 0, 335.7271612649919,
  44.                      0, 268.0500620563969, 228.181598739472,
  45.                      0, 0, 1);
  46. Mat distCoeffL = (Mat_<double>(5, 1) << -0.2320648740970932, 0.04510313360911739, -9.418532128676933e-05, -0.0008271590194063145, 0);

  47. Mat cameraMatrixR = (Mat_<double>(3, 3) << 268.0746191870755, 0, 313.554845275748,
  48.                      0, 267.8032936757982, 237.0287771634367,
  49.                      0, 0, 1);
  50. Mat distCoeffR = (Mat_<double>(5, 1) << -0.2391280628833069, 0.04899490848168394, 7.734678017422217e-05, 7.975132256511924e-05, 0);

  51. Mat T = (Mat_<double>(3, 1) << -90.67152, -2.93721, 16.09332);//T平移向量
  52. Mat rec = (Mat_<double>(3, 1) << 0.02428, 0.15673, -0.00825);//rec旋转向量
  53. Mat R;//R 旋转矩阵*/

  54. /*****立体匹配*****/
  55. void stereo_match(int,void*)
  56. {
  57.     bm->setBlockSize(2*blockSize+5);     //SAD窗口大小,5~21之间为宜
  58.     bm->setROI1(validROIL);
  59.     bm->setROI2(validROIR);
  60.     bm->setPreFilterCap(31);
  61.     bm->setMinDisparity(0);  //最小视差,默认值为0, 可以是负值,int型
  62.     bm->setNumDisparities(numDisparities*16+16);//视差窗口,即最大视差值与最小视差值之差,窗口大小必须是16的整数倍,int型
  63.     bm->setTextureThreshold(10);
  64.     bm->setUniquenessRatio(uniquenessRatio);//uniquenessRatio主要可以防止误匹配
  65.     bm->setSpeckleWindowSize(100);
  66.     bm->setSpeckleRange(32);
  67.     bm->setDisp12MaxDiff(-1);
  68.     Mat disp, disp8;
  69.     bm->compute(rectifyImageL, rectifyImageR, disp);//输入图像必须为灰度图
  70.     disp.convertTo(disp8, CV_8U, 255 / ((numDisparities * 16 + 16)*16.));//计算出的视差是CV_16S格式
  71.     reprojectImageTo3D(disp, xyz, Q, true); //在实际求距离时,ReprojectTo3D出来的X / W, Y / W, Z / W都要乘以16(也就是W除以16),才能得到正确的三维坐标信息。
  72.     xyz = xyz * 16;

  73.     Point p;
  74.     p.x = 400; p.y = 300;
  75.     cout << "in world coordinate: " << xyz.at<Vec3f>(p) << endl;

  76.     imshow("disparity", disp8);
  77. }

  78. /*****描述:鼠标操作回调*****/
  79. static void onMouse(int event, int x, int y, int, void*)
  80. {
  81.     if (selectObject)
  82.     {
  83.         selection.x = MIN(x, origin.x);
  84.         selection.y = MIN(y, origin.y);
  85.         selection.width = std::abs(x - origin.x);
  86.         selection.height = std::abs(y - origin.y);
  87.     }

  88.     switch (event)
  89.     {
  90.     case EVENT_LBUTTONDOWN:   //鼠标左按钮按下的事件
  91.         origin = Point(x, y);
  92.         selection = Rect(x, y, 0, 0);
  93.         selectObject = true;
  94.         cout << origin <<"in world coordinate is: " << xyz.at<Vec3f>(origin) << endl;
  95.         break;
  96.     case EVENT_LBUTTONUP:    //鼠标左按钮释放的事件
  97.         selectObject = false;
  98.         if (selection.width > 0 && selection.height > 0)
  99.         break;
  100.     }
  101. }


  102. /*****主函数*****/
  103. int main()
  104. {
  105.     int counter_frame = 0;

  106.     /*
  107.     立体校正
  108.     */
  109.     Rodrigues(rec, R); //Rodrigues变换
  110.     stereoRectify(cameraMatrixL, distCoeffL, cameraMatrixR, distCoeffR, imageSize, R, T, Rl, Rr, Pl, Pr, Q, CALIB_ZERO_DISPARITY,
  111.         0, imageSize, &validROIL, &validROIR);
  112.     initUndistortRectifyMap(cameraMatrixL, distCoeffL, Rl, Pr, imageSize, CV_32FC1, mapLx, mapLy);
  113.     initUndistortRectifyMap(cameraMatrixR, distCoeffR, Rr, Pr, imageSize, CV_32FC1, mapRx, mapRy);

  114.     VideoCapture left("Left.avi");
  115.     VideoCapture right("Right.avi");

  116.     Mat left_frame,right_frame;

  117.     if(!left.isOpened() || !right.isOpened())
  118.     {
  119.     cout<<"open error"<<endl;
  120.     return -1;
  121.     }

  122.     clock_t start_clock,end_clock;
  123.     start_clock = clock();


  124.     while(1)
  125.     {

  126.         if(counter_frame++ >= 30)
  127.         {
  128.             counter_frame = 0;
  129.             end_clock = clock();
  130.             std::cout << end_clock - start_clock << std::endl;
  131.             start_clock = clock();
  132.         }
  133.         /*
  134.         读取图片
  135.         */
  136.         left >> rgbImageL;
  137.         right >> rgbImageR;

  138.         cvtColor(rgbImageL, grayImageL, CV_BGR2GRAY);
  139.         cvtColor(rgbImageR, grayImageR, CV_BGR2GRAY);

  140.         imshow("ImageL Before Rectify", grayImageL);
  141.         imshow("ImageR Before Rectify", grayImageR);

  142.         /*
  143.         经过remap之后,左右相机的图像已经共面并且行对准了
  144.         */
  145.         remap(grayImageL, rectifyImageL, mapLx, mapLy, INTER_LINEAR);
  146.         remap(grayImageR, rectifyImageR, mapRx, mapRy, INTER_LINEAR);

  147.         /*
  148.         把校正结果显示出来
  149.         */
  150.         Mat rgbRectifyImageL, rgbRectifyImageR;
  151.         cvtColor(rectifyImageL, rgbRectifyImageL, CV_GRAY2BGR);  //伪彩色图
  152.         cvtColor(rectifyImageR, rgbRectifyImageR, CV_GRAY2BGR);

  153.         //单独显示
  154.         //rectangle(rgbRectifyImageL, validROIL, Scalar(0, 0, 255), 3, 8);
  155.         //rectangle(rgbRectifyImageR, validROIR, Scalar(0, 0, 255), 3, 8);
  156.         imshow("ImageL After Rectify", rgbRectifyImageL);
  157.         imshow("ImageR After Rectify", rgbRectifyImageR);

  158.         //显示在同一张图上
  159.         Mat canvas;
  160.         double sf;
  161.         int w, h;
  162.         sf = 600. / MAX(imageSize.width, imageSize.height);
  163.         w = cvRound(imageSize.width * sf);
  164.         h = cvRound(imageSize.height * sf);
  165.         canvas.create(h, w * 2, CV_8UC3);   //注意通道

  166.         //左图像画到画布上
  167.         Mat canvasPart = canvas(Rect(w * 0, 0, w, h));                                //得到画布的一部分
  168.         resize(rgbRectifyImageL, canvasPart, canvasPart.size(), 0, 0, INTER_AREA);     //把图像缩放到跟canvasPart一样大小
  169.         Rect vroiL(cvRound(validROIL.x*sf), cvRound(validROIL.y*sf),                //获得被截取的区域
  170.             cvRound(validROIL.width*sf), cvRound(validROIL.height*sf));
  171.         //rectangle(canvasPart, vroiL, Scalar(0, 0, 255), 3, 8);                      //画上一个矩形
  172.         cout << "Painted ImageL" << endl;

  173.         //右图像画到画布上
  174.         canvasPart = canvas(Rect(w, 0, w, h));                                      //获得画布的另一部分
  175.         resize(rgbRectifyImageR, canvasPart, canvasPart.size(), 0, 0, INTER_LINEAR);
  176.         Rect vroiR(cvRound(validROIR.x * sf), cvRound(validROIR.y*sf),
  177.             cvRound(validROIR.width * sf), cvRound(validROIR.height * sf));
  178.         //rectangle(canvasPart, vroiR, Scalar(0, 0, 255), 3, 8);
  179.         cout << "Painted ImageR" << endl;

  180.         //画上对应的线条
  181.         for (int i = 0; i < canvas.rows; i += 16)
  182.             line(canvas, Point(0, i), Point(canvas.cols, i), Scalar(0, 255, 0), 1, 8);
  183.         imshow("rectified", canvas);

  184.         /*
  185.         立体匹配
  186.         */
  187.         namedWindow("disparity", CV_WINDOW_AUTOSIZE);
  188.         // 创建SAD窗口 Trackbar
  189.         createTrackbar("BlockSize:\n", "disparity",&blockSize, 8, stereo_match);
  190.         // 创建视差唯一性百分比窗口 Trackbar
  191.         createTrackbar("UniquenessRatio:\n", "disparity", &uniquenessRatio, 50, stereo_match);
  192.         // 创建视差窗口 Trackbar
  193.         createTrackbar("NumDisparities:\n", "disparity", &numDisparities, 16, stereo_match);
  194.         //鼠标响应函数setMouseCallback(窗口名称, 鼠标回调函数, 传给回调函数的参数,一般取0)
  195.         setMouseCallback("disparity", onMouse, 0);
  196.         stereo_match(0,0);

  197.         waitKey(30);
  198.     }

  199.     return 0;
  200. }
复制代码
(二)双目视频获取
由于Khadas的usb线宽不足以采集手头两个usb摄像头1280*720的分辨率图片,春节将至,快递都停了,一时间又不好再买新的摄像头,只好用pc采集视频流做成avi再拷贝到开发板代替双目摄像头:

代码:
  1. #include <opencv2/core/core.hpp>
  2. #include <opencv2/highgui/highgui.hpp>

  3. using namespace cv;

  4. int main()
  5. {
  6.     int counter;

  7.     VideoCapture capture_left(0);//如果是笔记本,0打开的是自带的摄像头,1 打开外接的相机
  8.     VideoCapture capture_right(1);

  9.     double rate = 25.0;//视频的帧率
  10.     Size videoSize(640,480);

  11.     VideoWriter writer_left("Left2.avi", CV_FOURCC('M', 'J', 'P', 'G'), rate, videoSize);
  12.     VideoWriter writer_right("Right2.avi", CV_FOURCC('M', 'J', 'P', 'G'), rate, videoSize);

  13.     Mat left,right;

  14.     while (capture_left.isOpened() || capture_right.isOpened())
  15.     {
  16.         capture_left >> left;
  17.         capture_right >> right;

  18.         writer_left << left;
  19.         writer_right << right;

  20.         imshow("video_left2", left);
  21.         imshow("video_right2", right);

  22.         if (waitKey(20) == 27)//27是键盘摁下esc时,计算机接收到的ascii码值
  23.         {
  24.             break;
  25.         }

  26.         if(counter++ >=200)
  27.             break;
  28.     }

  29.     capture_left.release();
  30.     capture_right.release();

  31.     return 0;
  32. }
复制代码
(三)效果



部分结构的log:
  1. in world coordinate: [306.073, 641.233, 2638.34]
  2. Painted ImageL
  3. Painted ImageR
  4. in world coordinate: [215.967, 452.458, 1861.64]
  5. Painted ImageL
  6. Painted ImageR
  7. in world coordinate: [-2888.56, -6051.63, 160000]
  8. Painted ImageL
  9. Painted ImageR
  10. in world coordinate: [-2888.56, -6051.63, 160000]
  11. Painted ImageL
  12. Painted ImageR
  13. in world coordinate: [385.141, 806.884, 3319.92]
  14. Painted ImageL
  15. Painted ImageR
  16. in world coordinate: [-2888.56, -6051.63, 160000]
  17. Painted ImageL
  18. Painted ImageR
  19. in world coordinate: [-2888.56, -6051.63, 160000]
  20. Painted ImageL
  21. Painted ImageR
  22. in world coordinate: [491.67, 1030.07, 4238.19]
  23. Painted ImageL
  24. Painted ImageR
  25. in world coordinate: [248.478, 520.57, 2141.88]
  26. Painted ImageL
  27. Painted ImageR
  28. in world coordinate: [320.951, 672.404, 2766.6]
  29. Painted ImageL
  30. Painted ImageR
  31. in world coordinate: [332.496, 696.591, 2866.11]
  32. Painted ImageL
  33. Painted ImageR
  34. in world coordinate: [378.828, 793.657, 3265.49]
  35. Painted ImageL
  36. Painted ImageR
  37. in world coordinate: [192.571, 403.442, 1659.96]
  38. Painted ImageL
  39. Painted ImageR
  40. in world coordinate: [212.981, 446.203, 1835.9]
  41. Painted ImageL
  42. Painted ImageR
  43. in world coordinate: [249.821, 523.384, 2153.46]
  44. Painted ImageL
  45. Painted ImageR
  46. in world coordinate: [316.555, 663.193, 2728.7]
  47. Painted ImageL
  48. Painted ImageR
  49. in world coordinate: [-2888.56, -6051.63, 160000]
  50. Painted ImageL
  51. Painted ImageR
  52. in world coordinate: [2310.85, 4841.31, 19919.5]
  53. Painted ImageL
  54. Painted ImageR
  55. in world coordinate: [-2888.56, -6051.63, 160000]
  56. Painted ImageL
  57. Painted ImageR
  58. in world coordinate: [-2888.56, -6051.63, 160000]
  59. Painted ImageL
  60. Painted ImageR
  61. in world coordinate: [385.141, 806.884, 3319.92]
  62. Painted ImageL
  63. Painted ImageR
  64. in world coordinate: [-2888.56, -6051.63, 160000]
  65. Painted ImageL
  66. Painted ImageR
  67. in world coordinate: [2567.61, 5379.23, 22132.8]
  68. Painted ImageL
  69. Painted ImageR
  70. in world coordinate: [-2888.56, -6051.63, 160000]
  71. Painted ImageL
  72. Painted ImageR
  73. in world coordinate: [-2888.56, -6051.63, 160000]
  74. Painted ImageL
  75. Painted ImageR
  76. in world coordinate: [inf, inf, inf]
  77. Painted ImageL
  78. Painted ImageR
  79. in world coordinate: [-2888.56, -6051.63, 160000]
  80. 9302492
  81. Painted ImageL
  82. Painted ImageR
  83. in world coordinate: [-2888.56, -6051.63, 160000]
  84. Painted ImageL
  85. Painted ImageR
  86. in world coordinate: [-2888.56, -6051.63, 160000]
  87. Painted ImageL
  88. Painted ImageR
  89. in world coordinate: [2432.47, 5096.11, 20967.9]
  90. Painted ImageL
  91. Painted ImageR
  92. in world coordinate: [249.821, 523.384, 2153.46]
  93. Painted ImageL
  94. Painted ImageR
  95. in world coordinate: [192.571, 403.442, 1659.96]
  96. Painted ImageL
  97. Painted ImageR
  98. in world coordinate: [-2888.56, -6051.63, 160000]
  99. Painted ImageL
  100. Painted ImageR
  101. in world coordinate: [-2888.56, -6051.63, 160000]
  102. Painted ImageL
  103. Painted ImageR
  104. in world coordinate: [253.939, 532.012, 2188.96]
  105. Painted ImageL
  106. Painted ImageR
  107. in world coordinate: [inf, inf, inf]
  108. Painted ImageL
  109. Painted ImageR
  110. in world coordinate: [inf, inf, inf]
  111. Painted ImageL
  112. Painted ImageR
  113. in world coordinate: [711.03, 1489.63, 6129.08]
  114. Painted ImageL
  115. Painted ImageR
  116. in world coordinate: [-2888.56, -6051.63, 160000]
  117. Painted ImageL
  118. Painted ImageR
  119. in world coordinate: [1711.74, 3586.15, 14755.2]
  120. Painted ImageL
  121. Painted ImageR
  122. in world coordinate: [-2888.56, -6051.63, 160000]
  123. Painted ImageL
  124. Painted ImageR
  125. in world coordinate: [872.018, 1826.91, 7516.79]
  126. Painted ImageL
  127. Painted ImageR
  128. in world coordinate: [inf, inf, inf]
  129. Painted ImageL
  130. Painted ImageR
  131. in world coordinate: [inf, inf, inf]
  132. Painted ImageL
  133. Painted ImageR
  134. in world coordinate: [440.162, 922.153, 3794.19]
  135. Painted ImageL
  136. Painted ImageR
  137. in world coordinate: [563.622, 1180.81, 4858.41]
  138. Painted ImageL
  139. Painted ImageR
  140. in world coordinate: [270.275, 566.235, 2329.77]
  141. Painted ImageL
  142. Painted ImageR
  143. in world coordinate: [-2888.56, -6051.63, 160000]
  144. Painted ImageL
  145. Painted ImageR
  146. in world coordinate: [inf, inf, inf]
  147. Painted ImageL
  148. Painted ImageR
  149. in world coordinate: [385.141, 806.884, 3319.92]
  150. Painted ImageL
  151. Painted ImageR
  152. in world coordinate: [-2888.56, -6051.63, 160000]
  153. Painted ImageL
  154. Painted ImageR
  155. in world coordinate: [-2888.56, -6051.63, 160000]
  156. Painted ImageL
  157. Painted ImageR
  158. in world coordinate: [-2888.56, -6051.63, 160000]
  159. Painted ImageL
  160. Painted ImageR
  161. in world coordinate: [-2888.56, -6051.63, 160000]
  162. Painted ImageL
  163. Painted ImageR
  164. in world coordinate: [216.981, 454.583, 1870.38]
  165. Painted ImageL
  166. Painted ImageR
  167. in world coordinate: [-2888.56, -6051.63, 160000]
  168. Painted ImageL
  169. Painted ImageR
  170. in world coordinate: [-2888.56, -6051.63, 160000]
  171. Painted ImageL
  172. Painted ImageR
  173. in world coordinate: [-2888.56, -6051.63, 160000]
  174. 9273217
  175. Painted ImageL
  176. Painted ImageR
复制代码
大部分结构都落在9s左右(30帧9s),而这个在i5 12g 2400ddr配置的pc机上成绩在2s左右。稍后会推出在树莓派上运行的结果,对比pc机肯定是被虐,那么khadas又能不能虐树莓派呢?有点小期待。本来也想在banana pi berry上试一下的,可惜捣鼓了一个星期,系统刷锅好几遍都没能给banana pi装上opencv3.4,大概是因为系统依赖有点问题,只能作罢。
分享到:
回复

使用道具 举报

回答|共 4 个

倒序浏览

沙发

噗噗熊

发表于 2018-2-9 09:46:39 | 只看该作者

你这俩个usb摄像头咋固定在硬纸板上的
板凳

robe.zhang

发表于 2018-2-9 21:07:32 | 只看该作者

本帖最后由 robe.zhang 于 2018-2-9 21:10 编辑

banana pi 是啥系统,能不能用源在线安装,他自己会处理依赖关系
继续加油啊,双目是可以还原出来3D空间的,期待着看树莓派 和 banana pi,
地板

day_day

发表于 2018-2-18 21:26:35 | 只看该作者

噗噗熊 发表于 2018-2-9 09:46
你这俩个usb摄像头咋固定在硬纸板上的

就是用m2的螺丝。孔是用笔芯捅出来的,标定的时候还发现标定板打印的尺寸有点问题,最后的噪声超级大。
5#

day_day

发表于 2018-2-18 21:28:55 | 只看该作者

robe.zhang 发表于 2018-2-9 21:07
banana pi 是啥系统,能不能用源在线安装,他自己会处理依赖关系
继续加油啊,双目是可以还原出来3D空间的 ...

是用ubuntu mate的,总是感觉那个镜像有点问题,他的依赖感觉有点问题,png和jpg的处理库总是莫名其妙找不到,已经努力很久了……把各种库删了又安,重刷啦好多次都不行……
您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /3 下一条