OpenCV 相机标定

目录 Content
[hide]

每个相机都有唯一的参数,例如:焦距,主点,以及透镜的畸变模型。通过相机标定可以计算出相机的内部参数和畸变向量。

内部参数通常为3×3的矩阵,下文用 cameraMatrix 表示;畸变参数指径向畸变,为一个5×1矩阵,下文用 distCoeffs 表示。

一、成像模型

 

二、数学表达

 

三、OpenCV 实现

1.  准备校准图片

定义图像点位以及物理点位

  • vector<vector<Point2f>> imagePoints :N组图像点位集合,每个集合有M组图像坐标
  • vector<vector<Point3f>> objectPoints: N组物理点位集合,每个集合有M组物理坐标
    //prepare images
    vector<string> files;
    glob("../../chessboards2",files);

    vector<vector<Point2f>> imagePoints;
    vector<vector<Point3f>> objectPoints;
    TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::MAX_ITER,30,0.1);

    int numCornersHor = 23;
    int numCornersVer = 13;
    int numSquares = 10;
    Size boardSize(numCornersHor,numCornersVer);
    vector<Point3f> obj;
    for (int x=0; x < numCornersVer;++x) {
        for (int y= 0; y < numCornersHor; ++y) {
            obj.push_back(Point3f( x * numSquares, y * numSquares, 0.0f));
        }
    }

 

2. 查找交点

    //find corners
    Size imageSize;
    vector<string>::iterator filesIt;
    for (filesIt = files.begin();filesIt != files.end(); ++filesIt) {
        qDebug() << "image file: " << (*filesIt).c_str();
        Mat image = imread(*filesIt);
        imageSize = image.size();
        Mat gray;
        cvtColor(image,gray,COLOR_BGR2GRAY);
        vector<Point2f> corners;
        bool ret = findChessboardCorners(gray,boardSize,corners);
        if(ret){
            cornerSubPix(gray,corners,Size(5,5),Size(-1,-1),criteria);
            drawChessboardCorners(image,boardSize,corners,ret);
            imagePoints.push_back(corners);
            objectPoints.push_back(obj);
            namedWindow("calibration-demo",cv::WINDOW_KEEPRATIO);
            imshow("calibration-demo",image);
            waitKey(1);
        }
    }

 

3. 标定相机

    //calibrate camera
    Mat cameraMatrix = Mat(3,3,CV_32FC1);
    Mat distCoeffs;
    vector<Mat> rvecs;
    vector<Mat> tvecs;
    qDebug() << "begin calibration";
    QTime time;
    time.start();
    calibrateCamera(objectPoints,imagePoints,imageSize,cameraMatrix,distCoeffs,rvecs,tvecs);
    qDebug() << "end calibration, time (ms): " << time.elapsed();

 

4. 矫正畸变

    //Undistort image
    Mat map1,map2;
    time.start();
    initUndistortRectifyMap(cameraMatrix,distCoeffs,Mat(),Mat(),imageSize,CV_32FC1,map1,map2);
    qDebug() << "initUndistortRectifyMap, time (ms): " << time.elapsed();

    Mat dst;
    int timeElapsed;
    for (filesIt = files.begin();filesIt != files.end(); ++filesIt) {
        Mat image = imread(*filesIt);
        //
        time.restart();
        remap(image,dst,map1,map2,INTER_LINEAR);
        timeElapsed = time.elapsed();
        qDebug() << "remap time (ms): " << timeElapsed;
        //
        namedWindow("image ",cv::WINDOW_KEEPRATIO);
        imshow("image ", image);
        namedWindow("undistort image ",cv::WINDOW_KEEPRATIO);
        imshow("undistort image ", dst);
        waitKey(1);


    }

特意测试了处理时间,一开始在debug模式,remap耗时500毫秒,严重不能接受。

begin calibration
end calibration, time (ms):  1217
initUndistortRectifyMap, time (ms):  374
remap time (ms):  557
remap time (ms):  542
remap time (ms):  548
remap time (ms):  538
remap time (ms):  535
remap time (ms):  539
remap time (ms):  559

后来意识到版本不对,调整为release模式,remap耗时为10毫秒,可以接受了。

begin calibration
end calibration, time (ms):  93
initUndistortRectifyMap, time (ms):  6
remap time (ms):  12
remap time (ms):  12
remap time (ms):  10
remap time (ms):  12
remap time (ms):  10
remap time (ms):  10
remap time (ms):  10

四、重新标定

下面内容摘自 https://mp.weixin.qq.com/s/WLm5AcKJOXeLS9jnkvv8vA

标定其实是找出图像坐标系和相机坐标系的对应关系,相机拍摄平面改变,需要重新标定。

小孔成像模型包含了三个坐标系之间的转换,三维的世界坐标,三维的相机坐标,还有二维的像素坐标系。相机标定的结果是内参和外参。外参反映了相机在世界坐标系(通常是固定在靶标平面上)中的相对位置,它的作用是把世界坐标系的点坐标转换相机坐标系,是一个刚体变换。内参的作用是把相机坐标系中的点转换到二维像素坐标系,包含相机镜头焦距,光轴穿过像平面的坐标,每个像素的长宽,镜头畸变参数等。所以相机移动了或者靶标平面移动了之后外参就改变了。如果目的就是想知道相机和靶标的相对位姿(也就是外参),这个时候可以通过解pnp问题,来获得新的相对位姿。

 

参考

  • OpenCV相机标定与畸变校正
    https://mp.weixin.qq.com/s/Ue0Sv9h6JZssfJtg4N8hFg

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.