张正友标定-OpenCV程序

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/dcrmg/article/details/52929669

注: 程序所用的OpenCV版本是 2.4.10 ,3.0以上的版本可能会有不同

先贴一下完整的工程代码:



   
   
  1. #include "opencv2/core/core.hpp"
  2. #include "opencv2/imgproc/imgproc.hpp"
  3. #include "opencv2/calib3d/calib3d.hpp"
  4. #include "opencv2/highgui/highgui.hpp"
  5. #include <iostream>
  6. #include <fstream>
  7. using namespace cv;
  8. using namespace std;
  9. void main()
  10. {
  11. ifstream fin("calibdata.txt"); /* 标定所用图像文件的路径 */
  12. ofstream fout("caliberation_result.txt"); /* 保存标定结果的文件 */
  13. //读取每一幅图像,从中提取出角点,然后对角点进行亚像素精确化
  14. cout<< "开始提取角点………………";
  15. int image_count= 0; /* 图像数量 */
  16. Size image_size; /* 图像的尺寸 */
  17. Size board_size = Size( 4, 6); /* 标定板上每行、列的角点数 */
  18. vector<Point2f> image_points_buf; /* 缓存每幅图像上检测到的角点 */
  19. vector< vector<Point2f>> image_points_seq; /* 保存检测到的所有角点 */
  20. string filename;
  21. int count= -1 ; //用于存储角点个数。
  22. while (getline(fin,filename))
  23. {
  24. image_count++;
  25. // 用于观察检验输出
  26. cout<< "image_count = "<<image_count<< endl;
  27. /* 输出检验*/
  28. cout<< "-->count = "<<count;
  29. Mat imageInput=imread(filename);
  30. if (image_count == 1) //读入第一张图片时获取图像宽高信息
  31. {
  32. image_size.width = imageInput.cols;
  33. image_size.height =imageInput.rows;
  34. cout<< "image_size.width = "<<image_size.width<< endl;
  35. cout<< "image_size.height = "<<image_size.height<< endl;
  36. }
  37. /* 提取角点 */
  38. if ( 0 == findChessboardCorners(imageInput,board_size,image_points_buf))
  39. {
  40. cout<< "can not find chessboard corners!\n"; //找不到角点
  41. exit( 1);
  42. }
  43. else
  44. {
  45. Mat view_gray;
  46. cvtColor(imageInput,view_gray,CV_RGB2GRAY);
  47. /* 亚像素精确化 */
  48. find4QuadCornerSubpix(view_gray,image_points_buf,Size( 11, 11)); //对粗提取的角点进行精确化
  49. image_points_seq.push_back(image_points_buf); //保存亚像素角点
  50. /* 在图像上显示角点位置 */
  51. drawChessboardCorners(view_gray,board_size,image_points_buf, true); //用于在图片中标记角点
  52. imshow( "Camera Calibration",view_gray); //显示图片
  53. waitKey( 500); //暂停0.5S
  54. }
  55. }
  56. int total = image_points_seq.size();
  57. cout<< "total = "<<total<< endl;
  58. int CornerNum=board_size.width*board_size.height; //每张图片上总的角点数
  59. for ( int ii= 0 ; ii<total ;ii++)
  60. {
  61. if ( 0 == ii%CornerNum) // 24 是每幅图片的角点个数。此判断语句是为了输出 图片号,便于控制台观看
  62. {
  63. int i = -1;
  64. i = ii/CornerNum;
  65. int j=i+ 1;
  66. cout<< "--> 第 "<<j << "图片的数据 --> : "<< endl;
  67. }
  68. if ( 0 == ii% 3) // 此判断语句,格式化输出,便于控制台查看
  69. {
  70. cout<< endl;
  71. }
  72. else
  73. {
  74. cout.width( 10);
  75. }
  76. //输出所有的角点
  77. cout<< " -->"<<image_points_seq[ii][ 0].x;
  78. cout<< " -->"<<image_points_seq[ii][ 0].y;
  79. }
  80. cout<< "角点提取完成!\n";
  81. //以下是摄像机标定
  82. cout<< "开始标定………………";
  83. /*棋盘三维信息*/
  84. Size square_size = Size( 10, 10); /* 实际测量得到的标定板上每个棋盘格的大小 */
  85. vector< vector<Point3f>> object_points; /* 保存标定板上角点的三维坐标 */
  86. /*内外参数*/
  87. Mat cameraMatrix=Mat( 3, 3,CV_32FC1,Scalar::all( 0)); /* 摄像机内参数矩阵 */
  88. vector< int> point_counts; // 每幅图像中角点的数量
  89. Mat distCoeffs=Mat( 1, 5,CV_32FC1,Scalar::all( 0)); /* 摄像机的5个畸变系数:k1,k2,p1,p2,k3 */
  90. vector<Mat> tvecsMat; /* 每幅图像的旋转向量 */
  91. vector<Mat> rvecsMat; /* 每幅图像的平移向量 */
  92. /* 初始化标定板上角点的三维坐标 */
  93. int i,j,t;
  94. for (t= 0;t<image_count;t++)
  95. {
  96. vector<Point3f> tempPointSet;
  97. for (i= 0;i<board_size.height;i++)
  98. {
  99. for (j= 0;j<board_size.width;j++)
  100. {
  101. Point3f realPoint;
  102. /* 假设标定板放在世界坐标系中z=0的平面上 */
  103. realPoint.x = i*square_size.width;
  104. realPoint.y = j*square_size.height;
  105. realPoint.z = 0;
  106. tempPointSet.push_back(realPoint);
  107. }
  108. }
  109. object_points.push_back(tempPointSet);
  110. }
  111. /* 初始化每幅图像中的角点数量,假定每幅图像中都可以看到完整的标定板 */
  112. for (i= 0;i<image_count;i++)
  113. {
  114. point_counts.push_back(board_size.width*board_size.height);
  115. }
  116. /* 开始标定 */
  117. calibrateCamera(object_points,image_points_seq,image_size,cameraMatrix,distCoeffs,rvecsMat,tvecsMat, 0);
  118. cout<< "标定完成!\n";
  119. //对标定结果进行评价
  120. cout<< "开始评价标定结果………………\n";
  121. double total_err = 0.0; /* 所有图像的平均误差的总和 */
  122. double err = 0.0; /* 每幅图像的平均误差 */
  123. vector<Point2f> image_points2; /* 保存重新计算得到的投影点 */
  124. cout<< "\t每幅图像的标定误差:\n";
  125. fout<< "每幅图像的标定误差:\n";
  126. for (i= 0;i<image_count;i++)
  127. {
  128. vector<Point3f> tempPointSet=object_points[i];
  129. /* 通过得到的摄像机内外参数,对空间的三维点进行重新投影计算,得到新的投影点 */
  130. projectPoints(tempPointSet,rvecsMat[i],tvecsMat[i],cameraMatrix,distCoeffs,image_points2);
  131. /* 计算新的投影点和旧的投影点之间的误差*/
  132. vector<Point2f> tempImagePoint = image_points_seq[i];
  133. Mat tempImagePointMat = Mat( 1,tempImagePoint.size(),CV_32FC2);
  134. Mat image_points2Mat = Mat( 1,image_points2.size(), CV_32FC2);
  135. for ( int j = 0 ; j < tempImagePoint.size(); j++)
  136. {
  137. image_points2Mat.at<Vec2f>( 0,j) = Vec2f(image_points2[j].x, image_points2[j].y);
  138. tempImagePointMat.at<Vec2f>( 0,j) = Vec2f(tempImagePoint[j].x, tempImagePoint[j].y);
  139. }
  140. err = norm(image_points2Mat, tempImagePointMat, NORM_L2);
  141. total_err += err/= point_counts[i];
  142. std:: cout<< "第"<<i+ 1<< "幅图像的平均误差:"<<err<< "像素"<< endl;
  143. fout<< "第"<<i+ 1<< "幅图像的平均误差:"<<err<< "像素"<< endl;
  144. }
  145. std:: cout<< "总体平均误差:"<<total_err/image_count<< "像素"<< endl;
  146. fout<< "总体平均误差:"<<total_err/image_count<< "像素"<< endl<< endl;
  147. std:: cout<< "评价完成!"<< endl;
  148. //保存定标结果
  149. std:: cout<< "开始保存定标结果………………"<< endl;
  150. Mat rotation_matrix = Mat( 3, 3,CV_32FC1, Scalar::all( 0)); /* 保存每幅图像的旋转矩阵 */
  151. fout<< "相机内参数矩阵:"<< endl;
  152. fout<<cameraMatrix<< endl<< endl;
  153. fout<< "畸变系数:\n";
  154. fout<<distCoeffs<< endl<< endl<< endl;
  155. for ( int i= 0; i<image_count; i++)
  156. {
  157. fout<< "第"<<i+ 1<< "幅图像的旋转向量:"<< endl;
  158. fout<<tvecsMat[i]<< endl;
  159. /* 将旋转向量转换为相对应的旋转矩阵 */
  160. Rodrigues(tvecsMat[i],rotation_matrix);
  161. fout<< "第"<<i+ 1<< "幅图像的旋转矩阵:"<< endl;
  162. fout<<rotation_matrix<< endl;
  163. fout<< "第"<<i+ 1<< "幅图像的平移向量:"<< endl;
  164. fout<<rvecsMat[i]<< endl<< endl;
  165. }
  166. std:: cout<< "完成保存"<< endl;
  167. fout<< endl;
  168. system( "pause");
  169. return ;
  170. }

运行前需要先准备标定图片和记录标定图片列表的文本文件,并放入程序所在目录下,如下图所示:




文本文件的内容如下:




运行效果图1:


图2:


图3:


图4:



最后在程序所在目录下生成“caliberation_result.txt”文件,记录了标定的误差、相机内外参数信息:




感谢无名前辈提供的测试图例!


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值