使用OpenCV标定鱼眼镜头(C++)

来源:互联网 发布:缩小手机屏幕的软件 编辑:程序博客网 时间:2024/06/08 20:09

使用OpenCV标定鱼眼镜头(C++)

本人邮箱:sylvester0510@163.com,欢迎交流讨论,
欢迎转载,转载请注明网址http://blog.csdn.net/u010128736/


一、使用的函数

  由于鱼眼镜头和针孔镜头的模型不一样,对于鱼眼镜头的模型在之前的博客中已经做了详细介绍,这里直接使用OpenCV中的cv::fisheye::calibrate()函数进行标定。函数原型如下,需要输入目标点集,图像点集、图像尺寸。函数输出相机内参,畸变系数,旋转矩阵和平移向量,以及反投影误差。

 CV_EXPORTS double calibrate(InputArrayOfArrays objectPoints, InputArrayOfArrays imagePoints, const Size& image_size,        InputOutputArray K, InputOutputArray D, OutputArrayOfArrays rvecs, OutputArrayOfArrays tvecs, int flags = 0,            TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON));

二、采集标定图像

  采集若干拍摄有标定棋盘格的图像,并使棋盘格出现在画面的各个位置,特别是边缘位置。如下图所示:
这里写图片描述

三、标定代码

#include "stdio.h"#include <iostream>#include <fstream>#include <io.h>#include "opencv2/opencv.hpp"#include <opencv2/core/core.hpp>#include "opencv2/calib3d/calib3d.hpp"#include <opencv2/highgui/highgui.hpp>using namespace std;using namespace cv;void getFiles(string path, vector<string>& files){    //文件句柄    intptr_t hFile = 0;    //文件信息    struct _finddata_t fileinfo;    string p;    if ((hFile = _findfirst(p.assign(path).append("\\*").c_str(), &fileinfo)) != -1)    {        do        {            //如果是目录,迭代之            //如果不是,加入列表            if ((fileinfo.attrib &  _A_SUBDIR))            {                if (strcmp(fileinfo.name, ".") != 0 && strcmp(fileinfo.name, "..") != 0)                    getFiles(p.assign(path).append("\\").append(fileinfo.name), files);            }            else            {                files.push_back(p.assign(path).append("\\").append(fileinfo.name));            }        } while (_findnext(hFile, &fileinfo) == 0);        _findclose(hFile);    }}int main(int argc, char** argv){       string filePath = ".\\720PPcalib\\front";    vector<string> files;    ////获取该路径下的所有文件    getFiles(filePath, files);    const int board_w = 6;    const int board_h = 4;    const int NPoints = board_w * board_h;//棋盘格内角点总数    const int boardSize = 30; //mm    Mat image,grayimage;    Size ChessBoardSize = cv::Size(board_w, board_h);    vector<Point2f> tempcorners;    int flag = 0;    flag |= cv::fisheye::CALIB_RECOMPUTE_EXTRINSIC;    //flag |= cv::fisheye::CALIB_CHECK_COND;    flag |= cv::fisheye::CALIB_FIX_SKEW;    //flag |= cv::fisheye::CALIB_USE_INTRINSIC_GUESS;    vector<Point3f> object;    for (int j = 0; j < NPoints; j++)    {        object.push_back(Point3f((j % board_w) * boardSize, (j / board_w) * boardSize, 0));     }    cv::Matx33d intrinsics;//z:相机内参    cv::Vec4d distortion_coeff;//z:相机畸变系数    vector<vector<Point3f> > objectv;    vector<vector<Point2f> > imagev;    Size corrected_size(1280, 720);    Mat mapx, mapy;    Mat corrected;    ofstream intrinsicfile("intrinsics_front1103.txt");    ofstream disfile("dis_coeff_front1103.txt");    int num = 0;    bool bCalib = false;    while (num < files.size())    {        image = imread(files[num]);        if (image.empty())            break;        imshow("corner_image", image);        waitKey(10);        cvtColor(image, grayimage, CV_BGR2GRAY);        IplImage tempgray = grayimage;        bool findchessboard = cvCheckChessboard(&tempgray, ChessBoardSize);        if (findchessboard)        {            bool find_corners_result = findChessboardCorners(grayimage, ChessBoardSize, tempcorners, 3);            if (find_corners_result)            {                cornerSubPix(grayimage, tempcorners, cvSize(5, 5), cvSize(-1, -1), cvTermCriteria(CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 30, 0.1));                drawChessboardCorners(image, ChessBoardSize, tempcorners, find_corners_result);                imshow("corner_image", image);                cvWaitKey(100);                objectv.push_back(object);                imagev.push_back(tempcorners);                cout << "capture " << num << " pictures" << endl;            }        }        tempcorners.clear();        num++;    }    cv::fisheye::calibrate(objectv, imagev, cv::Size(image.cols,image.rows), intrinsics, distortion_coeff, cv::noArray(), cv::noArray(), flag, cv::TermCriteria(3, 20, 1e-6));      fisheye::initUndistortRectifyMap(intrinsics, distortion_coeff, cv::Matx33d::eye(), intrinsics, corrected_size, CV_16SC2, mapx, mapy);    for(int i=0; i<3; ++i)    {        for(int j=0; j<3; ++j)        {            intrinsicfile<<intrinsics(i,j)<<"\t";        }        intrinsicfile<<endl;    }    for(int i=0; i<4; ++i)    {        disfile<<distortion_coeff(i)<<"\t";    }    intrinsicfile.close();    disfile.close();    num = 0;    while (num < files.size())    {        image = imread(files[num++]);        if (image.empty())            break;        remap(image, corrected, mapx, mapy, INTER_LINEAR, BORDER_TRANSPARENT);        imshow("corner_image", image);        imshow("corrected", corrected);        cvWaitKey(200);     }    cv::destroyWindow("corner_image");    cv::destroyWindow("corrected");    image.release();    grayimage.release();    corrected.release();    mapx.release();    mapy.release();    return 0;}

四、标定结果

  使用标定的结果进行畸变校正后的结果如下所示,可以看到,原本弯曲的曲线已经变直。
这里写图片描述

2 0
原创粉丝点击