基于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