张正友相机标定,opencv中calibrate函数内部具体实现过程附具体代码(一)-----初始化需要的数据、资源

张正友相机标定,opencv中calibrate函数内部具体实现过程附具体代码(一)-----初始化需要的数据、资源

  • 素材说明
  • 写在前面
  • main函数
  • InintRead_Save函数
  • Init_object_points函数
  • Init_point_counts函数

由于导师锻炼自己写代码能力,需要将张正友相机标定论文实现,要求自己编写calibrate函数,在此记录自己的学习过程,本人将分三个部分讲整个工程介绍,供大家参考,一起学习共同进步~!Ubuntu下C++程序。
转载请注明出处。

(一)初始化需要的数据、资源
(二)calibrate第一步-----求内外参数
(三)calibrate第二步-----利用ceres第一次优化
(四)calibrate第三步-----求畸变系数
(五)calibrate第四步-----第二次优化
(六)利用优化后的内外参、畸变系数矫正整个图像

素材说明

棋盘格图片素材来自opencv库中自带的棋盘格图片,在如下目录自取,共14张图
在这里插入图片描述
例如:
张正友相机标定,opencv中calibrate函数内部具体实现过程附具体代码(一)-----初始化需要的数据、资源_第1张图片

写在前面

如果利用opencv提供的图片求出内外参数,怎么检验求出的结果对不对呢?
两种方法:
1.找这个文件,里面有参数,将自己求得的参数对照下,如果差的像素不多,说明求得的正确,笔者求得差3-10像素。
张正友相机标定,opencv中calibrate函数内部具体实现过程附具体代码(一)-----初始化需要的数据、资源_第2张图片
2.利用自己求得的参数进行重投影,投影到图像上,观察是否和角点位置相差不多。

main函数

为了后面讲解方便,将所有需要用到变量声明

int main(){
    ifstream fin("calibration.txt"); //标定所用图像文件的路径为避免出错最后是绝对路径
    ofstream fout("calibration_result.txt"); //保存标定结果的文件
    int image_count = 0;  // 图像数量
    Size image_size;      // 图像的尺寸
    Size board_size = Size(9, 6); // 标定板上每行、列的角点数
    vector<Point2f> image_points_buf; //缓存每幅图像上检测到的角点
    vector<vector<Point2f> > image_points_seq; //保存检测到的所有角点
    string filename;      // 图片名
    vector<string> filenames;
    vector<vector<Point3f> > object_points;   //标定板上角点的三维坐标
    Mat distCoeffs= Mat(1, 5, CV_32FC1,Scalar::all(0));       //5个畸变系数:k1,k2,p1,p2,k3
    vector<int> point_counts;   //每幅图像中角点的数量
    vector<Mat> tvecsMat;      //每幅图像的旋转向量
    vector<Mat> rvecsMat;      //每幅图像的平移向量
    
    vector<vector<Point2f> > uv;
    vector<vector<Point3f> > uv1;
    vector<vector<Point3f> > xy1;
    vector<vector<Mat> > M_alluv1;
    vector<vector<Mat> > M_allxy1;
    vector<Mat> H;
    Mat cameraMatrix = Mat(3, 3, CV_32FC1, Scalar::all(0));  //内参数矩阵
    float scale;
    vector<Mat> R_r;
    vector<Mat> Jett;
    vector<Mat> tvecsMat1;
    vector<Mat> outcan;
    vector<vector<Point2d> > uuvv;
    vector<vector<Point3d> > object_pointses;
    int CornerNum = board_size.width * board_size.height;
    double incamera[5];
    vector<Mat> outcameraR1;
    vector<Mat> outcameraR2;
    vector<Mat> outcameraT;


InintRead_Save(fin,image_count,image_size,board_size,image_points_buf,image_points_seq,filename,filenames);//初始化角点并存储
Init_object_points(object_points, image_count, board_size);//初始化标定板上角点的三维坐标
Init_point_counts(point_counts, image_count, board_size); //初始化每幅图像中的角点数量
}

InintRead_Save函数

此函数功能是读取图片,获取角点并初始化

void InintRead_Save(ifstream& fin, int& image_count, Size& image_size, Size& board_size,
                    vector<Point2f>& image_points_buf, vector<vector<Point2f> >& image_points_seq,
                    string& filename, vector<string>& filenames)
{
    while (getline(fin, filename))
    {
        ++image_count;
        cout<<"image_count = "<<image_count<<endl;
        cout<<"filename: "<<filename<<endl;
        Mat imageInput = imread(filename);
        filenames.push_back(filename);

        if(image_count == 1)
        {
            image_size.width = imageInput.cols;
            image_size.height = imageInput.rows;
            cout<<"image_size.width = "<<image_size.width<<endl;
            cout<<"image_size.height = "<<image_size.height<<endl;
        }

        // 提取角点 需要使用findChessboardCorners函数提取角点,必须是8位的灰度或者彩色图像
        if (0 == findChessboardCorners(imageInput, board_size, image_points_buf))
        {
            cout << "can not find chessboard corners!\n";  // 找不到角点
            exit(1);
        }
        else
        {
            Mat view_gray;
            cvtColor(imageInput, view_gray, CV_RGB2GRAY);  // 转灰度图
            cornerSubPix(view_gray, image_points_buf, Size(5,5), Size(-1,-1), TermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));//亚像素精确化
            image_points_seq.push_back(image_points_buf);  // 保存亚像素角点
            drawChessboardCorners(view_gray, board_size, image_points_buf, false); // 图片中标记角点
            imshow("Camera Calibration", view_gray);       // 显示图片
            waitKey(0);
        }
    }
}

Init_object_points函数

此函数功能是初始化每张图片上角点对应的三维点坐标

void Init_object_points(vector<vector<Point3f> >& object_points, int& image_count, Size& board_size)
{
    Size square_size = Size(10,10);/* 实际测量得到的标定板上每个棋盘格的大小 */
    for (int t=0; t<image_count; t++) //第几张图片
    {
        vector<Point3f> tempPointSet;
        for (int i=0; i<board_size.height; i++)
        {
            for (int j=0; j<board_size.width; j++)
            {
                Point3f realPoint;
                realPoint.x = j * square_size.width;
                realPoint.y = i * square_size.height;
                realPoint.z = 0;
                tempPointSet.push_back(realPoint);
            }
        }
        object_points.push_back(tempPointSet);
    }
}

Init_point_counts函数

初始化每幅图像中的角点数量

void Init_point_counts(vector<int>& point_counts, int& image_count, Size& board_size)
{
    for (int i=0; i<image_count; i++)
    {
        point_counts.push_back(board_size.width * board_size.height);
    }
}

下一篇博客讲介绍calibrate()函数中第一步------求解内外参数。

转载请注明出处。

你可能感兴趣的:(学习笔记)