基于Opencv2.4.9的双目相机标定代码
来源:互联网 发布:苏州网络教育招生简章 编辑:程序博客网 时间:2024/04/30 08:25
现在很多双目相机标定的原理说明。个人看过比较好的链接如下:
http://blog.csdn.net/chenyusiyuan/article/details/5961769
http://blog.csdn.net/chenyusiyuan/article/details/5963256
我学习时,找了许多代码资料,很多不完整,或代码不够简洁。以下代码是我参考别人的代码最终写出的双目相机标定代码。
创建一个双目相机标定类CCalibratnMethod。源文件和头文件内容如下
//.cpp//双目标定函数 输入为CAMERACALIB& cameraCalib在头文件中定义void CCalibratnMethod::CameraCalibration(CAMERACALIB& cameraCalib){ m_cameraCalib = cameraCalib; cvutMatrix::Matrix<double> Rl(3,3); //左边图像的旋转矩阵 cvutMatrix::Matrix<double> Tl(3,1);//左边图像的平移矩阵 cvutMatrix::Matrix<double> Rr(3,3); //右边图像的旋转矩阵 cvutMatrix::Matrix<double> Tr(3,1);//右边图像的平移矩阵 cvutMatrix::Matrix<double> steroR(3,3); cvutMatrix::Matrix<double> steroT(3,1); cvutMatrix::Matrix<double> intrinsic_matrixL(3,3); cvutMatrix::Matrix<double> distortion_coeffsL(4,1); cvutMatrix::Matrix<double> intrinsic_matrixR(3,3); cvutMatrix::Matrix<double> distortion_coeffsR(4,1); ifstream fsImgL(cameraCalib.m_sFilePathL); //左摄像头定标所用图像文件的路径 ifstream fsImgR(cameraCalib.m_sFilePathR); //左相机标定图像角点提取 CornerDetection(fsImgL,m_imagePointSeqL); //右相机标定图像角点提取 CornerDetection(fsImgR,m_imagePointSeqR); //左图角点转换 CvSize square_size = cvSize((int)m_cameraCalib.m_dSquareSize,(int)m_cameraCalib.m_dSquareSize); cvutMatrix::Matrix<double> object_pointsL(bordSize.width*bordSize.height*sucesses,3); cvutMatrix::Matrix<double> image_pointsL(m_imagePointSeqL.cvseq->total,2); cvutMatrix::Matrix<int> point_countsL(sucesses,1); CornerConvert(m_imagePointSeqL,object_pointsL,image_pointsL,point_countsL); //右图角点转换 cvutMatrix::Matrix<double> object_pointsR(bordSize.width*bordSize.height*sucesses,3); cvutMatrix::Matrix<double> image_pointsR(m_imagePointSeqL.cvseq->total,2); cvutMatrix::Matrix<int> point_countsR(sucesses,1); CornerConvert(m_imagePointSeqR,object_pointsR,image_pointsR,point_countsR); //左相机标定 cvutMatrix::Matrix<double> rotation_vectorsL(sucesses,3); cvutMatrix::Matrix<double> translation_vectorsL(sucesses,3); cvCalibrateCamera2(object_pointsL.cvmat,//角点的三维坐标 image_pointsL.cvmat,//角点 point_countsL.cvmat,//每幅图像的角点数量 m_imgSize,//图像大小 intrinsic_matrixL.cvmat, distortion_coeffsL.cvmat, rotation_vectorsL.cvmat, translation_vectorsL.cvmat, 0); //右相机标定 cvutMatrix::Matrix<double> rotation_vectorsR(sucesses,3); cvutMatrix::Matrix<double> translation_vectorsR(sucesses,3); cvCalibrateCamera2(object_pointsR.cvmat,//角点的三维坐标 image_pointsR.cvmat,//角点 point_countsR.cvmat,//每幅图像的角点数量 m_imgSize,//图像大小 intrinsic_matrixR.cvmat, distortion_coeffsR.cvmat, rotation_vectorsR.cvmat, translation_vectorsR.cvmat, 0); //双目标定 cvutMatrix::Matrix<double> E(3,3); cvutMatrix::Matrix<double> F(3,3); cvStereoCalibrate( object_pointsL.cvmat,image_pointsL.cvmat, image_pointsR.cvmat,point_countsL.cvmat, intrinsic_matrixL.cvmat, distortion_coeffsL.cvmat, intrinsic_matrixR.cvmat, distortion_coeffsR.cvmat, m_imgSize, steroR.cvmat, steroT.cvmat, E.cvmat, F.cvmat, cvTermCriteria(CV_TERMCRIT_ITER + CV_TERMCRIT_EPS, 100, 1e-5)); //保存标定结果 ofstream fsCalibResult("caliberation_result.txt"); //保存定标结果的文件 fsCalibResult<<"左相机内参数矩阵:\n"; fsCalibResult<<intrinsic_matrixL<<'\n'; fsCalibResult<<"左相机畸变系数:\n"; fsCalibResult<<distortion_coeffsL<<'\n'; fsCalibResult<<"右相机内参数矩阵:\n"; fsCalibResult<<intrinsic_matrixR<<'\n'; fsCalibResult<<"右相机畸变系数:\n"; fsCalibResult<<distortion_coeffsR<<'\n'; fsCalibResult<<"双目标定旋转矩阵:\n"; fsCalibResult<<steroR<<'\n'; fsCalibResult<<"双目标定平移矩阵:\n"; fsCalibResult<<steroT<<'\n';}//角点提取函数 void CCalibratnMethod::CornerDetection(ifstream& fImg,cvutSeq::Seq<CvPoint2D32f>& imagePointSeq){ int nImgCount = 0;//图像数量 sucesses = 0; bordSize = cvSize(m_cameraCalib.m_nCornerNx,m_cameraCalib.m_nCornerNy);//定标板上每行、列的角点数 int nBordNum = bordSize.width*bordSize.height;//标定板上角点总数 CvPoint2D32f* image_points_buf = new CvPoint2D32f[nBordNum]; //缓存每幅图像上检测到的角点 string filename; int count = -1 ;//用于存储角点个数 while (getline(fImg,filename)) { nImgCount ++; cvutImage::Image<uchar> view(filename); //Image是个类 if (nImgCount == 1) { m_imgSize.width = view.size().width; //传递图像的宽和高 m_imgSize.height = view.size().height; } //提取角点 int found=cvFindChessboardCorners( view.cvimage, bordSize, image_points_buf, &count, CV_CALIB_CB_ADAPTIVE_THRESH); //cvFindChessboardCorners(要检测的棋盘图,图中每行和每列的角点个数,检测到的角点,输出——角点个数,操作标志) //CV_CALIB_CB_ADAPTIVE_THRESH - 使用自适应阈值(通过平均图像亮度计算得到)将图像转换为黑白图,而不是一个固定的阈值。 //CV_CALIB_CB_FILTER_QUADS - 使用其他的准则(如轮廓面积,周长,方形形状)来去除在轮廓检测阶段检测到的错误方块。 //返回值:如果所有角点都被检测到且它们都被以一定顺序排布(一行一行地,每行从左到右),函数返回非零值, //否则在函数不能发现所有角点或者记录它们地情况下,函数返回0 if (found == 0) { int iReturn = AfxMessageBox(_T("未检测到角点"),MB_OK); } else { sucesses++; cvutImage::Image<uchar> view_gray(view.size(),8,1); cvCvtColor(view.cvimage, view_gray.cvimage, CV_BGR2GRAY); //亚像素精确化 cvFindCornerSubPix( view_gray.cvimage, image_points_buf, count, cvSize(11,11), cvSize(-1,-1), cvTermCriteria( CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 30, 0.1 ));//对粗提取的角点进行精确化 imagePointSeq.push_back(image_points_buf,count);//把精确化的角点坐标传递给image_points_seq // 在图像上显示角点位置 cvDrawChessboardCorners( view.cvimage, bordSize, image_points_buf, count, 1); view.show("calib");//显示图片 cvWaitKey(500);//用于暂停,单位是毫秒 view.close(); } }}//角点转换函数 为了使用Opencv的标定函数做出的转换void CCalibratnMethod::CornerConvert(cvutSeq::Seq<CvPoint2D32f>& imagePointSeq, cvutMatrix::Matrix<double>& object_points, cvutMatrix::Matrix<double>& image_points, cvutMatrix::Matrix<int>& point_counts){ CvSize square_size = cvSize((int)m_cameraCalib.m_dSquareSize,(int)m_cameraCalib.m_dSquareSize); for (int t = 0; t < sucesses; t++) { for (int i = 0; i < bordSize.height; i++) { for (int j = 0; j < bordSize.width; j++) { // 假设定标板放在世界坐标系中z=0的平面上 object_points(t * bordSize.height * bordSize.width + i * bordSize.width + j, 0) = i * square_size.width; object_points(t * bordSize.height * bordSize.width + i * bordSize.width + j, 1) = j * square_size.height; object_points(t * bordSize.height * bordSize.width + i * bordSize.width + j, 2) = 0; } } } //将角点的存储结构转换成矩阵形式 for (int i = 0; i < imagePointSeq.cvseq->total; i++) { image_points(i,0) = imagePointSeq[i].x; image_points(i,1) = imagePointSeq[i].y; } //初始化每幅图像中的角点数量,这里我们假设每幅图像中都可以看到完整的定标板 for (int i = 0; i < sucesses; i++) point_counts(i,0) = bordSize.width * bordSize.height;}
//.h#pragma once#include "stdafx.h"#include "MethodBase.h"#include "cvutImage.h"class CCalibratnMethod:public CMethodBase{public: CCalibratnMethod(void); ~CCalibratnMethod(void); struct CAMERACALIB { int m_nCornerNx; //棋盘角点数nx int m_nCornerNy; //棋盘角点数ny double m_dSquareSize; //棋盘方块大小,单位MM bool m_bReadLocalImg; //是否从本地读取标定文件 string m_sFilePathL; //从文件中读左图的路径 string m_sFilePathR; //从文件中读右图的路径 }; cvutSeq::Seq<CvPoint2D32f> m_imagePointSeqL; //左图角点 cvutSeq::Seq<CvPoint2D32f> m_imagePointSeqR; //右图角点 CvSize m_imgSize; //图像size CvSize bordSize; //标定size CAMERACALIB m_cameraCalib; int sucesses ;public: void CCalibratnMethod::CameraCalibration(CAMERACALIB& cameraCalib); void CCalibratnMethod::CornerDetection(ifstream& fImg,cvutSeq::Seq<CvPoint2D32f>& imagePointSeq); void CCalibratnMethod::CornerConvert(cvutSeq::Seq<CvPoint2D32f>& imagePointSeq, cvutMatrix::Matrix<double>& object_points, cvutMatrix::Matrix<double>& image_points, cvutMatrix::Matrix<int>& point_counts);};
//调用双目相机标定类 CCalibratnMethod::CAMERACALIB m_CameraCalib; m_CameraCalib.m_nCornerNx = 6;//棋盘格X方向数 m_CameraCalib.m_nCornerNy = 4;//棋盘格Y方向数 m_CameraCalib.m_dSquareSize = 41;//棋盘格边长大小,单位mm m_CameraCalib.m_bReadLocalImg = true;//从文件中获取图像来源 m_CameraCalib.m_sFilePathL = "calibdata1.txt";//左图标定文件 m_CameraCalib.m_sFilePathR = "calibdata2.txt";//右图标定文件 CCalibratnMethod * m_cCalibratMethod; m_cCalibratMethod = new CCalibratnMethod(); m_cCalibratMethod->CameraCalibration(m_CameraCalib);
本人源代码下载,里面有说明文档和实验图片:
http://download.csdn.net/detail/sybil_w/9293531
0 0
- 基于Opencv2.4.9的双目相机标定代码
- 相机标定(4)---基于halcon的双目立体视觉标定
- 基于OPENCV的相机标定及代码
- 基于opencv的双目标定
- 基于OpenCV的双目摄像机标定
- 基于matlab的双目+IMU标定
- 基于opencv的相机标定
- opencv 双目相机标定 自带例子程序的使用
- 使用OpenCV进行相机标定(基于OpenCV2.4.3)
- 双目标定代码
- 相机标定(3)---基于halcon的面阵相机标定
- 相机标定——基于张正友标定标定法与MFC的单目相机标定
- 【OpenCV】单目相机标定 / 双目相机标定
- 双目视觉的标定
- matlab与opencv双目相机标定对比
- 极简OpenCV的相机标定代码
- 双目相机标定之OpenCV获取左右相机图像+MATLAB单目标定+双目标定
- 基于matlab标定数据,使用opencv实现双目立体摄像头的标定(源代码)
- 接口自动化工具
- Objective-C Runtime 运行时之二:成员变量与属性
- 测试工程师的出路该怎么走,转型成测试开发?too hard
- DLL进程退出时出现死锁问题
- 爬虫搜索基础篇(三)
- 基于Opencv2.4.9的双目相机标定代码
- 二分图(二)——匈牙利算法
- Masonry 学习笔记
- 知乎转载 逻辑回归线性非线性疑问
- Android下ffmpeg、SDL的编译
- Spring配置为内部类 和 引用静态域变量 配置方式
- Spring MVC @ModelAttribute 详解
- 《swift2.0 官方教程中文版》 第1章
- svn propset svn:ignore