opencv相机标定

来源:互联网 发布:布鲁克大学 知乎 编辑:程序博客网 时间:2024/06/10 07:08

主要是参照opencv2那本书,注视写的都很详细,方便以后查找!
CameraCalibrator.h头文件

#include <iostream>#include <opencv2/core/core.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/calib3d/calib3d.hpp>class CameraCalibrator {private:    // 输入点    //位于世界坐标的点    std::vector<std::vector<cv::Point3f>> objectPoints;    //像素坐标的点    std::vector<std::vector<cv::Point2f>> imagePoints;    std::vector<cv::Mat> rvecs, tvecs;    // 输出矩阵,内参数阵和畸变系数真    cv::Mat cameraMatrix;    cv::Mat distCoeffs;    cv::Mat cameraRotation ;//保存外参数矩阵    cv::Mat cameraTranslation ;//保存平移量    // 标定的方式    int flag;    // 用于图像去畸变    cv::Mat map1,map2;     bool mustInitUndistort;public:    CameraCalibrator() : flag(0), mustInitUndistort(true) {};    // 打开棋盘图像并提取角点    int addChessboardPoints(const std::vector<std::string>& filelist, cv::Size & boardSize);    void addPoints(const std::vector<cv::Point2f>& imageCorners, const std::vector<cv::Point3f>& objectCorners);    double calibrate(cv::Size &imageSize);    void setCalibrationFlag(bool radial8CoeffEnabled=false, bool tangentialParamEnabled=false);    cv::Mat CameraCalibrator::remap(const cv::Mat &image);    //获取指定棋盘格的外方位矩阵    void CalExtrinx(int i) ;      //获得相机的内参数矩阵    cv::Mat getCameraExtrinsic(){return cameraRotation ;}    void saveRotation(std::string str) ;    //获取相机的内参数矩阵    cv::Mat getCameraMatrix() { return cameraMatrix; }    //保存相机的内参数矩阵    void saveCameraMatrix(std::string str) ;    //获得指定棋盘格的平移量    cv::Mat getTranslations(){ return cameraTranslation ;}     //保存平移量    void saveTranslations(std::string str) ;    //获取相机的畸变系数    cv::Mat getDistCoeffs()   { return distCoeffs; }    void printMatrix(const cv::Mat matrix) ;    //读取棋盘格列表    void readImagelist(const char* path , std::vector<std::string> &filelist) ;    //获取棋盘格角点物理坐标    std::vector<std::vector<cv::Point3f>> getObjectPoints() const {return objectPoints ;}    //获取棋盘格角点像点坐标    std::vector<std::vector<cv::Point2f>> getImagepoints() const {return imagePoints ;}};#endif // CAMERACALIBRATOR_H

CameraCalibrator.cpp源文件

#include "CameraCalibrator.h"#include <fstream>#include <algorithm>const int squraewidth = 26 ;/************************************************************************//* 函数说明            打开棋盘图像并且提取角点 * @Input              filelist图像列表 * @Input              boardSize棋盘尺寸 @ 返回                检测棋盘格图像的数量*//************************************************************************/int CameraCalibrator::addChessboardPoints(    const std::vector<std::string>& filelist,     cv::Size & boardSize) {    // 棋盘上点的两种坐标    std::vector<cv::Point2f> imageCorners;    std::vector<cv::Point3f> objectCorners;    // 3D 场景中得点    // 在棋盘坐标系中初始化棋盘角点    // 这些点位于(X,Y,Z)=(i,j,0)    for (int i=0; i<boardSize.height; i++)     {        for (int j=0; j<boardSize.width; j++)         {            objectCorners.push_back(cv::Point3f(i * squraewidth , j * squraewidth , 0.0f));        }    }    cv::Mat image; // 为了保存棋盘图像    int successes = 0;    // 所有视图    for (int i=0; i<filelist.size(); i++)    {        // 打开图像        image = cv::imread(filelist[i],0);        // 得到角点        bool found = cv::findChessboardCorners(image, boardSize, imageCorners);        // 获取亚像素级精度        cv::cornerSubPix(image, imageCorners,             cv::Size(5,5),             cv::Size(-1,-1),             cv::TermCriteria(             CV_TERMCRIT_EPS + CV_TERMCRIT_ITER,             40, //maxCount=40            0.001 ));     // 最小精度        // 如果角点数据满足要求,那么将它加入数据(全部角点检测出)        if (imageCorners.size() == boardSize.area())         {            // 添加一个视角中得图像点及场景点            addPoints(imageCorners, objectCorners);            successes++;        }        cv::drawChessboardCorners(image, boardSize, imageCorners, found);        cv::imshow("Corners on Chessboard", image);        cv::waitKey(100);    }    return successes;}/************************************************************************//* 函数说明:       添加场景点与对应的图像点    * @Input           imageCorners图像点 * @Input           objectCorners场景点*//************************************************************************/void CameraCalibrator::addPoints(const std::vector<cv::Point2f>& imageCorners, const std::vector<cv::Point3f>& objectCorners) {    // 2D 图像点    imagePoints.push_back(imageCorners);              // 对应3D场景中得点    objectPoints.push_back(objectCorners);}/************************************************************************//* 函数说明:     进行标定,返回重投影误差     * @Input         imageSize图片尺寸*//************************************************************************/double CameraCalibrator::calibrate(cv::Size &imageSize){    //必须进行去畸变    mustInitUndistort= true;    //输出旋转和平移/*    std::vector<cv::Mat> rvecs, tvecs;*/     calibrateCamera(objectPoints, // 3D点        imagePoints,  // 图像点        imageSize,    // 图像尺寸        cameraMatrix, // 输出的相机矩阵        distCoeffs,   // 输出的畸变矩阵        rvecs, tvecs, // 旋转和平移        flag);        // 额外选项    //                  ,CV_CALIB_USE_INTRINSIC_GUESS);    return 1;}/************************************************************************//* 函数说明:            利用标定结果去除图像的畸变  * 参数:@Input          image输入待矫正的图像 * 返回:@Return         去畸变后的图像 */ /************************************************************************/cv::Mat CameraCalibrator::remap(const cv::Mat &image) {    cv::Mat undistorted;    if (mustInitUndistort)    { //每次标定只需初始化一次           cv::initUndistortRectifyMap(            cameraMatrix,  // 相机内参矩阵            distCoeffs,    // 计算得到的畸变矩阵            cv::Mat(),     // optional rectification (none)             cv::Mat(),     // camera matrix to generate undistorted            //            cv::Size(640,480),            image.size(),  // 无畸变图像的尺寸            CV_32FC1,      // 输出映射图像的类型            map1, map2);   // x坐标和y坐标映射函数        mustInitUndistort= false;    }    // 应用映射函数    cv::remap(image, undistorted, map1, map2,         cv::INTER_LINEAR); // interpolation type    return undistorted;}void CameraCalibrator::setCalibrationFlag(bool radial8CoeffEnabled, bool tangentialParamEnabled) {    // Set the flag used in cv::calibrateCamera()    flag = 0;    if (!tangentialParamEnabled)         flag += CV_CALIB_ZERO_TANGENT_DIST;    if (radial8CoeffEnabled)        flag += CV_CALIB_RATIONAL_MODEL;}/************************************************************************//* 函数说明:   打印矩阵                                                                     *//************************************************************************/void CameraCalibrator::printMatrix(const cv::Mat matrix){    int w = matrix.cols ;    int h = matrix.rows ;    for (int i = 0 ; i < h ; ++i)    {        for (int j = 0 ; j < w ; ++j)        {            std::cout<< matrix.at<double>(i , j)<<"\t" ;        }        std::cout<<"\n" ;    }}/************************************************************************//* 函数说明:      保存相机的内参数矩阵    * 参数:@Input    str 保存路径*//************************************************************************/void CameraCalibrator::saveCameraMatrix(std::string str){    if (cameraMatrix.empty())    {        std::cout<<"相机内参数矩阵为空!\n" ;        return ;    }    int w = cameraMatrix.cols ;    int h = cameraMatrix.rows ;    std::ofstream out(str , std::ios::out) ;    if (!out)    {        std::cout<<"打开失败!\n" ;        return ;    }    for (int i = 0 ; i < h ; ++i)    {        for (int j = 0 ; j < w ; ++j)        {            out<<cameraMatrix.at<double>(i , j)<<"\t" ;        }        out<<"\n" ;    }    out.close() ;}/************************************************************************//* 函数说明:    读取图像列表 * 参数@Input    path 保存图像列表路径 * 参数@Output   filelist保存所有图片路径*//************************************************************************/void CameraCalibrator::readImagelist(const char* path , std::vector<std::string> &filelist){    std::ifstream in(path , std::ios::in) ;    if (!in)    {        return ;    }    std::string str ;    int i = 0 ;    while (!in.eof())    {        in>>str ;        filelist.push_back(str) ;          ++i ;    }    in.close() ;}/************************************************************************//*函数说明:            保存外方位矩阵 *参数 @Input           str 保存路径*//************************************************************************/void CameraCalibrator::saveRotation(std::string str){    if (cameraRotation.empty())    {        std::cout<<"外方位矩阵为空!\n" ;        return ;    }    //获取矩阵的行数和列数    int w = cameraRotation.cols ;    int h = cameraRotation.rows ;    std::ofstream out(str , std::ios::out) ;    if (!out)    {        std::cout<<"保存文件失败!\n" ;        return ;    }    else    {        for (int i = 0 ; i < h ; ++i)        {            for (int j = 0 ; j < w ; ++j)            {                out<<cameraRotation.at<double>(i , j)<<"\t" ;            }            out<<"\n" ;        }    }}/************************************************************************//* 获取指定棋盘格的外方位元素 * Input i 表示第i张图像 *//************************************************************************/ void CameraCalibrator::CalExtrinx(int i){    Rodrigues(rvecs[i] , cameraRotation) ;    cameraTranslation = tvecs[i] ;} /************************************************************************/ /* 函数说明:    保持平移量  * @Input      str 保存文件名称*/ /************************************************************************/ void CameraCalibrator::saveTranslations(std::string str) {     if (cameraTranslation.empty())     {         std::cout<<"相机外参数的平移量量为空!\n" ;         return ;     }     int w = cameraTranslation.cols ;     int h = cameraTranslation.rows ;     std::ofstream out(str , std::ios::out) ;     if (!out)     {         std::cout<<"写入文件失败!\n" ;         return ;     }     for (int i = 0 ; i < w ; ++i)     {         for (int j = 0 ; j < h ; ++j)         {             out<<cameraTranslation.at<double>(i , j)<<"\t" ;         }         out<<"\n" ;     } }

main.cpp文件

#include <iostream>#include <iomanip>#include <vector>#include <opencv2/core/core.hpp>#include <opencv2/imgproc/imgproc.hpp>#include <opencv2/highgui/highgui.hpp>#include <opencv2/features2d/features2d.hpp>#include <fstream>#include "CameraCalibrator.h"int main(){    cv::Mat image;    CameraCalibrator cameraCalibrator;    std::vector<std::string> filelist;    cameraCalibrator.readImagelist("文件.txt" , filelist) ;//读取文件列表    cv::Mat mat ;    cv::Size boardSize(9,6);    cameraCalibrator.addChessboardPoints(filelist , boardSize); // 棋盘尺寸    //  cameraCalibrator.setCalibrationFlag(true,true);    image = cv::imread(filelist[6]);    cameraCalibrator.calibrate(image.size());    image = cv::imread(filelist[6]);    cv::Mat uImage= cameraCalibrator.remap(image);    cv::Mat cameraMatrix= cameraCalibrator.getCameraMatrix();    std::cout << " Camera intrinsic: " << cameraMatrix.rows << "x" << cameraMatrix.cols << std::endl;    cameraCalibrator.printMatrix(cameraMatrix) ;    cameraCalibrator.saveCameraMatrix("neican.txt") ;    std::cout<<"第"<<1<<"张图像的旋转矩阵为:\n" ;    cameraCalibrator.CalExtrinx(1) ;    cv::Mat rotationMatrix = cameraCalibrator.getCameraExtrinsic() ;    cameraCalibrator.printMatrix(rotationMatrix) ;    std::cout<<"第"<<1<<"张图像的平移向量为:\n" ;    cv::Mat translationMatrix = cameraCalibrator.getTranslations() ;    cameraCalibrator.printMatrix(translationMatrix) ;    imshow("Original Image", image);    imshow("Undistorted Image", uImage);    cv::waitKey();    return 0;}
0 0
原创粉丝点击