calibration.cpp
上传用户:jiayuled
上传日期:2020-03-04
资源大小:9338k
文件大小:9k
源码类别:

OpenCV

开发平台:

C/C++

  1. #include "cvut.h"
  2. #include <iostream>
  3. #include <fstream>
  4. #include <string>
  5. using namespace cvut;
  6. using namespace std;
  7. #pragma comment(lib,"cxcore.lib")
  8. #pragma comment(lib,"cv.lib")
  9. #pragma comment(lib,"highgui.lib")
  10. void main() 
  11. {
  12. ifstream fin("calibdata.txt"); /* 定标所用图像文件的路径 */
  13. ofstream fout("caliberation_result.txt");  /* 保存定标结果的文件 */
  14.     /************************************************************************
  15.        读取每一幅图像,从中提取出角点,然后对角点进行亚像素精确化
  16. *************************************************************************/
  17. cout<<"开始提取角点………………";
  18. int image_count=0;  /* 图像数量 */
  19. CvSize image_size;  /* 图像的尺寸 */
  20. CvSize board_size = cvSize(4,6);    /* 定标板上每行、列的角点数 */
  21. CvPoint2D32f* image_points_buf = new CvPoint2D32f[board_size.width*board_size.height];   /* 缓存每幅图像上检测到的角点 */
  22. Seq<CvPoint2D32f> image_points_seq;  /* 保存检测到的所有角点 */
  23. string filename;
  24. int count= -1 ;//用于存储角点个数。 所有变量定义后必须初始化,这是一个编程优良习惯
  25. while (getline(fin,filename))
  26. {
  27. image_count++;
  28. /************************************************************************/
  29. /* 用于观察检验输出                                                                  */
  30. cout<<"image_count = "<<image_count<<endl;
  31. /************************************************************************/
  32. /************************************************************************/
  33. /* 输出检验*/
  34. cout<<"-->count = "<<count;
  35. /************************************************************************/
  36. Image<uchar> view(filename);
  37. if (image_count == 1) 
  38. {
  39. image_size.width = view.size().width;
  40. image_size.height = view.size().height;
  41. /************************************************************************/
  42. /*                                                                      */
  43. cout<<"image_size.width = "<<image_size.width<<endl;
  44. cout<<"image_size.height = "<<image_size.height<<endl;
  45. /************************************************************************/
  46. }
  47. /* 提取角点 */
  48. if (0 == cvFindChessboardCorners( view.cvimage, board_size,
  49.             image_points_buf, &count, CV_CALIB_CB_ADAPTIVE_THRESH ))
  50. {
  51. /************************************************************************/
  52. /*                                                                      */
  53. cout<<endl<<"board_size.height="<<board_size.height<<endl<<"count="<<count<<endl;
  54. /************************************************************************/
  55. cout<<"can not find chessboard corners!n";
  56. exit(1);
  57. else 
  58. {
  59. Image<uchar> view_gray(view.size(),8,1);
  60. rgb2gray(view,view_gray);
  61. /* 亚像素精确化 */
  62. cvFindCornerSubPix( view_gray.cvimage, image_points_buf, count, cvSize(11,11),
  63. cvSize(-1,-1), cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 ));//对粗提取的角点进行精确化
  64. image_points_seq.push_back(image_points_buf,count);
  65. /* 在图像上显示角点位置 */
  66. cvDrawChessboardCorners( view.cvimage, board_size, image_points_buf, count, 1);//用于在图片中标记角点
  67. view.show("calib");//显示图片
  68. cvWaitKey(500);//用于暂停,单位是毫秒
  69. view.close();
  70. }
  71. }
  72. /************************************************************************/
  73. /* 
  74. //以下是利用包装后的数据结构(seq类)进行操作,比基于openCV的数据结构更方便,结构清晰。
  75.                                                                      */
  76. int total = image_points_seq.length();
  77. cout<<"total = "<<total<<endl;
  78. for (int ii=0 ; ii<total ;ii++)
  79. {
  80. if (0 == ii%24)// 24 是每幅图片的角点个数。此判断语句是为了输出 图片号,便于控制台观看 
  81. {
  82. int i = -1;
  83. i = ii/24;
  84. int j=i+1;
  85. cout<<"--> 第 "<<j <<"图片的数据 --> : "<<endl;
  86. }
  87. if (0 == ii%3) // 此判断语句,格式化输出,便于控制台查看
  88. {
  89. cout<<endl;
  90. }
  91. else
  92. {
  93. cout.width(10);
  94. }
  95. //输出所有的角点
  96. cout<<" -->"<<image_points_seq[ii].x;
  97. cout<<" -->"<<image_points_seq[ii].y;
  98. }
  99. /************************************************************************/
  100. delete []image_points_buf;
  101. cout<<"角点提取完成!n";
  102. /************************************************************************
  103.        摄像机定标
  104. *************************************************************************/
  105. cout<<"开始定标………………";
  106. /*棋盘三维信息*/
  107. CvSize square_size = cvSize(10,10);  /* 实际测量得到的定标板上每个棋盘格的大小 */
  108. Matrix<double> object_points(1,board_size.width*board_size.height*image_count,3); /* 保存定标板上角点的三维坐标 */
  109. Matrix<double> image_points(1,image_points_seq.cvseq->total,2); /* 保存提取的所有角点 */
  110. Matrix<int> point_counts(1,image_count,1); /* 每幅图像中角点的数量 */
  111. /*内外参数*/
  112. Matrix<double> intrinsic_matrix(3,3,1); /* 摄像机内参数矩阵 */
  113. Matrix<double> distortion_coeffs(1,4,1); /* 摄像机的4个畸变系数:k1,k2,p1,p2 */
  114. Matrix<double> rotation_vectors(1,image_count,3); /* 每幅图像的旋转向量 */
  115. Matrix<double> translation_vectors(1,image_count,3); /* 每幅图像的平移向量 */
  116. /* 初始化定标板上角点的三维坐标 */
  117. int i,j,t;
  118. for (t=0;t<image_count;t++) {
  119. for (i=0;i<board_size.height;i++) {
  120. for (j=0;j<board_size.width;j++) {
  121. /* 假设定标板放在世界坐标系中z=0的平面上 */
  122. object_points(0,t*board_size.height*board_size.width+i*board_size.width+j,0) = i*square_size.width;
  123. object_points(0,t*board_size.height*board_size.width+i*board_size.width+j,1) = j*square_size.height;
  124. object_points(0,t*board_size.height*board_size.width+i*board_size.width+j,2) = 0;
  125. }
  126. }
  127. }
  128. /* 将角点的存储结构转换成矩阵形式 */
  129. for (i=0;i<image_points_seq.cvseq->total;i++) {
  130. image_points(0,i,0) = image_points_seq[i].x;
  131. image_points(0,i,1) = image_points_seq[i].y;
  132. }
  133. /* 初始化每幅图像中的角点数量,这里我们假设每幅图像中都可以看到完整的定标板 */
  134. for (i=0;i<image_count;i++)
  135. point_counts(0,i) = board_size.width*board_size.height;
  136. /* 开始定标 */
  137. cvCalibrateCamera2(object_points.cvmat,
  138.    image_points.cvmat,
  139.                        point_counts.cvmat,
  140.    image_size,
  141.                        intrinsic_matrix.cvmat,
  142.    distortion_coeffs.cvmat,
  143.                        rotation_vectors.cvmat,
  144.    translation_vectors.cvmat,
  145.    0);
  146. cout<<"定标完成!n";
  147. /************************************************************************
  148.        对定标结果进行评价
  149. *************************************************************************/
  150. cout<<"开始评价定标结果………………n";
  151. double total_err = 0.0; /* 所有图像的平均误差的总和 */
  152. double err = 0.0; /* 每幅图像的平均误差 */
  153. Matrix<double> image_points2(1,point_counts(0,0,0),2); /* 保存重新计算得到的投影点 */
  154. cout<<"t每幅图像的定标误差:n";
  155. fout<<"每幅图像的定标误差:n";
  156. for (i=0;i<image_count;i++) {
  157. /* 通过得到的摄像机内外参数,对空间的三维点进行重新投影计算,得到新的投影点 */
  158. cvProjectPoints2(object_points.get_cols(i*point_counts(0,0,0),(i+1)*point_counts(0,0,0)-1).cvmat,
  159. rotation_vectors.get_col(i).cvmat,
  160. translation_vectors.get_col(i).cvmat,
  161. intrinsic_matrix.cvmat,
  162. distortion_coeffs.cvmat,
  163. image_points2.cvmat,
  164. 0,0,0,0);
  165. /* 计算新的投影点和旧的投影点之间的误差*/
  166. err = cvNorm(image_points.get_cols(i*point_counts(0,0,0),(i+1)*point_counts(0,0,0)-1).cvmat,
  167. image_points2.cvmat,
  168. CV_L1);
  169. total_err += err/=point_counts(0,0,0);
  170. cout<<"tt第"<<i+1<<"幅图像的平均误差:"<<err<<"像素"<<'n';
  171. fout<<"t第"<<i+1<<"幅图像的平均误差:"<<err<<"像素"<<'n';
  172. }
  173. cout<<"t总体平均误差:"<<total_err/image_count<<"像素"<<'n';
  174. fout<<"总体平均误差:"<<total_err/image_count<<"像素"<<'n'<<'n';
  175. cout<<"评价完成!n";
  176. /************************************************************************
  177.        保存定标结果
  178. *************************************************************************/
  179. cout<<"开始保存定标结果………………";
  180. Matrix<double> rotation_vector(3,1); /* 保存每幅图像的旋转向量 */
  181. Matrix<double> rotation_matrix(3,3); /* 保存每幅图像的旋转矩阵 */
  182. fout<<"相机内参数矩阵:n";
  183. fout<<intrinsic_matrix<<'n';
  184. fout<<"畸变系数:n";
  185. fout<<distortion_coeffs<<'n';
  186. for (i=0;i<image_count;i++) 
  187. {
  188. fout<<"第"<<i+1<<"幅图像的旋转向量:n";
  189. fout<<rotation_vectors.get_col(i);
  190. /* 对旋转向量进行存储格式转换 */
  191. for (j=0;j<3;j++) 
  192. {
  193. rotation_vector(j,0,0) = rotation_vectors(0,i,j);
  194. }
  195. /* 将旋转向量转换为相对应的旋转矩阵 */
  196. cvRodrigues2(rotation_vector.cvmat,rotation_matrix.cvmat);
  197. fout<<"第"<<i+1<<"幅图像的旋转矩阵:n";
  198. fout<<rotation_matrix;
  199. fout<<"第"<<i+1<<"幅图像的平移向量:n";
  200. fout<<translation_vectors.get_col(i)<<'n';
  201. }
  202. cout<<"完成保存n";
  203. }