• 相机的校正感悟


     在你看到这篇博文的时候,希望你能先看下我的上一篇博文,对相关的知识点有所了解后再看这篇博文

      下面的几个函数就是实现相机校正的关键

    • addChessboardPoints() 函数 - 用于读入一系列的棋盘图像并检测角点;
    • calibrate() 函数 - 用于进行相机校正,得到相机的参数矩阵和畸变系数;
    • remap() 函数 - 用于根据相机校正结果修复图像的畸变;//主要靠这个函数实现校正initUndistortRectifyMap
    • addPoints() 函数 - addChessboardPoints() 在检测完角点后会调用这个函数。也可自己手动调用这个函数添加已知的角点位置和对应的空间坐标点。
    main.c 
    1
    #include <QCoreApplication> 2 #include <iostream> 3 #include <iomanip> 4 #include <vector> 5 #include <opencv2/core/core.hpp> 6 #include <opencv2/imgproc/imgproc.hpp> 7 #include <opencv2/highgui/highgui.hpp> 8 #include <opencv2/features2d/features2d.hpp> 9 10 #include "CameraCalibrator.h" 11 12 int main() 13 { 14 15 cv::namedWindow("Image"); 16 cv::Mat image; 17 std::vector<std::string> filelist; 18 19 // generate list of chessboard image filename 20 for (int i=1; i<=20; i++) { 21 22 std::stringstream str; 23 str << "/home/bi/pic/chessboards/chessboard" << std::setw(2) << std::setfill('0') << i << ".jpg"; 24 std::cout << str.str() << std::endl; 25 26 filelist.push_back(str.str()); 27 image= cv::imread(str.str(),0);//直接变为灰度图 28 //cvtColor(image,image,CV_BGR2GRAY); 29 cv::imshow("Image",image); 30 31 cv::waitKey(1000); 32 } 33 34 // Create calibrator object 35 CameraCalibrator cameraCalibrator; 36 // add the corners from the chessboard 37 cv::Size boardSize(6,4); 38 cameraCalibrator.addChessboardPoints( 39 filelist, // filenames of chessboard image 40 boardSize); // size of chessboard 41 // calibrate the camera 42 // cameraCalibrator.setCalibrationFlag(true,true); 43 cameraCalibrator.calibrate(image.size()); 44 45 // Image Undistortion 46 image = cv::imread(filelist[6]); 47 cv::Mat uImage= cameraCalibrator.remap(image); 48 49 // display camera matrix 50 cv::Mat cameraMatrix= cameraCalibrator.getCameraMatrix(); 51 std::cout << " Camera intrinsic: " << cameraMatrix.rows << "x" << cameraMatrix.cols << std::endl; 52 std::cout << cameraMatrix.at<double>(0,0) << " " << cameraMatrix.at<double>(0,1) << " " << cameraMatrix.at<double>(0,2) << std::endl; 53 std::cout << cameraMatrix.at<double>(1,0) << " " << cameraMatrix.at<double>(1,1) << " " << cameraMatrix.at<double>(1,2) << std::endl; 54 std::cout << cameraMatrix.at<double>(2,0) << " " << cameraMatrix.at<double>(2,1) << " " << cameraMatrix.at<double>(2,2) << std::endl; 55 56 imshow("Original Image", image); 57 imshow("Undistorted Image", uImage); 58 59 cv::waitKey(); 60 return 0; 61 }

    CameraCalibrator.h 

    • addChessboardPoints() 函数 - 用于读入一系列的棋盘图像并检测角点;
    • calibrate() 函数 - 用于进行相机校正,得到相机的参数矩阵和畸变系数;
    • remap() 函数 - 用于根据相机校正结果修复图像的畸变;//主要靠这个函数实现校正initUndistortRectifyMap
    • addPoints() 函数addChessboardPoints() 在检测完角点后会调用这个函数。也可自己手动调用这个函数添加已知的角点位置和对应的空间坐标点。
     1 #ifndef CAMERACALIBRATOR_H
     2 #define CAMERACALIBRATOR_H
     3 
     4 #include <vector>
     5 #include <iostream>
     6 
     7 #include <opencv2/core/core.hpp>
     8 #include "opencv2/imgproc/imgproc.hpp"
     9 #include "opencv2/calib3d/calib3d.hpp"
    10 #include <opencv2/highgui/highgui.hpp>
    11 
    12 class CameraCalibrator {
    13 
    14     // input points
    15     std::vector<std::vector<cv::Point3f>> objectPoints;
    16     std::vector<std::vector<cv::Point2f>> imagePoints;
    17     // output Matrices
    18     cv::Mat cameraMatrix;
    19     cv::Mat distCoeffs;
    20     // flag to specify how calibration is done
    21     int flag;
    22     // used in image undistortion 
    23     cv::Mat map1,map2; 
    24     bool mustInitUndistort;
    25 
    26   public:
    27     CameraCalibrator() : flag(0), mustInitUndistort(true) {};
    28 
    29     // Open the chessboard images and extract corner points
    30     int addChessboardPoints(const std::vector<std::string>& filelist, cv::Size & boardSize);
    31     // Add scene points and corresponding image points
    32     void addPoints(const std::vector<cv::Point2f>& imageCorners, const std::vector<cv::Point3f>& objectCorners);
    33     // Calibrate the camera
    34     double calibrate(cv::Size &imageSize);
    35     // Set the calibration flag
    36     void setCalibrationFlag(bool radial8CoeffEnabled=false, bool tangentialParamEnabled=false);
    37     // Remove distortion in an image (after calibration)
    38     cv::Mat CameraCalibrator::remap(const cv::Mat &image);
    39 
    40     // Getters
    41     cv::Mat getCameraMatrix() { return cameraMatrix; }
    42     cv::Mat getDistCoeffs()   { return distCoeffs; }
    43 };
    44 
    45 #endif // CAMERACALIBRATOR_H
    View Code

     CameraCalibrator.cpp

      1 #include "CameraCalibrator.h"
      2 
      3 // Open chessboard images and extract corner points
      4 int CameraCalibrator::addChessboardPoints(
      5          const std::vector<std::string>& filelist, 
      6          cv::Size & boardSize) {
      7 
      8     // the points on the chessboard
      9     std::vector<cv::Point2f> imageCorners;
     10     std::vector<cv::Point3f> objectCorners;
     11 
     12     // 3D Scene Points:
     13     // Initialize the chessboard corners 
     14     // in the chessboard reference frame
     15     // The corners are at 3D location (X,Y,Z)= (i,j,0)
     16     for (int i=0; i<boardSize.height; i++) {
     17         for (int j=0; j<boardSize.width; j++) {
     18 
     19             objectCorners.push_back(cv::Point3f(i, j, 0.0f));
     20         }
     21     }
     22 
     23     // 2D Image points:
     24     cv::Mat image; // to contain chessboard image
     25     int successes = 0;
     26     // for all viewpoints
     27     for (int i=0; i<filelist.size(); i++) {
     28 
     29         // Open the image
     30         image = cv::imread(filelist[i],0);
     31 
     32         // Get the chessboard corners
     33         bool found = cv::findChessboardCorners(
     34                         image, boardSize, imageCorners);
     35 
     36         // Get subpixel accuracy on the corners
     37         cv::cornerSubPix(image, imageCorners, 
     38                   cv::Size(5,5), 
     39                   cv::Size(-1,-1), 
     40             cv::TermCriteria(cv::TermCriteria::MAX_ITER +
     41                           cv::TermCriteria::EPS, 
     42              30,        // max number of iterations 
     43              0.1));     // min accuracy
     44 
     45           // If we have a good board, add it to our data
     46           if (imageCorners.size() == boardSize.area()) {
     47 
     48             // Add image and scene points from one view
     49             addPoints(imageCorners, objectCorners);
     50             successes++;
     51           }
     52 
     53         //Draw the corners
     54         cv::drawChessboardCorners(image, boardSize, imageCorners, found);
     55         cv::imshow("Corners on Chessboard", image);
     56         cv::waitKey(100);
     57     }
     58 
     59     return successes;
     60 }
     61 
     62 // Add scene points and corresponding image points
     63 void CameraCalibrator::addPoints(const std::vector<cv::Point2f>& imageCorners, const std::vector<cv::Point3f>& objectCorners) {
     64 
     65     // 2D image points from one view
     66     imagePoints.push_back(imageCorners);          
     67     // corresponding 3D scene points
     68     objectPoints.push_back(objectCorners);
     69 }
     70 
     71 // Calibrate the camera
     72 // returns the re-projection error
     73 double CameraCalibrator::calibrate(cv::Size &imageSize)
     74 {
     75     // undistorter must be reinitialized
     76     mustInitUndistort= true;
     77 
     78     //Output rotations and translations
     79     std::vector<cv::Mat> rvecs, tvecs;
     80 
     81     // start calibration
     82     return 
     83      calibrateCamera(objectPoints, // the 3D points
     84                     imagePoints,  // the image points
     85                     imageSize,    // image size
     86                     cameraMatrix, // output camera matrix
     87                     distCoeffs,   // output distortion matrix
     88                     rvecs, tvecs, // Rs, Ts 
     89                     flag);        // set options
     90 //                    ,CV_CALIB_USE_INTRINSIC_GUESS);
     91 
     92 }
     93 
     94 // remove distortion in an image (after calibration)
     95 cv::Mat CameraCalibrator::remap(const cv::Mat &image) {
     96 
     97     cv::Mat undistorted;
     98 
     99     if (mustInitUndistort) { // called once per calibration
    100     
    101         cv::initUndistortRectifyMap(
    102             cameraMatrix,  // computed camera matrix
    103             distCoeffs,    // computed distortion matrix
    104             cv::Mat(),     // optional rectification (none) 
    105             cv::Mat(),     // camera matrix to generate undistorted
    106             cv::Size(640,480),
    107 //            image.size(),  // size of undistorted
    108             CV_32FC1,      // type of output map
    109             map1, map2);   // the x and y mapping functions
    110 
    111         mustInitUndistort= false;
    112     }
    113 
    114     // Apply mapping functions
    115     cv::remap(image, undistorted, map1, map2, 
    116         cv::INTER_LINEAR); // interpolation type
    117 
    118     return undistorted;
    119 }
    120 
    121 
    122 // Set the calibration options
    123 // 8radialCoeffEnabled should be true if 8 radial coefficients are required (5 is default)
    124 // tangentialParamEnabled should be true if tangeantial distortion is present
    125 void CameraCalibrator::setCalibrationFlag(bool radial8CoeffEnabled, bool tangentialParamEnabled) {
    126 
    127     // Set the flag used in cv::calibrateCamera()
    128     flag = 0;
    129     if (!tangentialParamEnabled) flag += CV_CALIB_ZERO_TANGENT_DIST;
    130     if (radial8CoeffEnabled) flag += CV_CALIB_RATIONAL_MODEL;
    131 }
    View Code

    findChessboardCorners

    Finds the positions of internal corners of the chessboard.
    C++: bool findChessboardCorners(InputArray image, Size patternSize, OutputArray corners, int
    flags=CV_CALIB_CB_ADAPTIVE_THRESH+CV_CALIB_CB_NORMALIZE_IMAGE
    )//如果找到了棋盘内部的角点,会返回true这个时候正好对应绘制角点的patternWasFound

    Parameters
    image – Source chessboard view. It must be an 8-bit grayscale or color image.
    patternSize – Number of inner corners per a chessboard row and column ( patternSize
    = cvSize(points_per_row,points_per_colum) = cvSize(columns,rows) ).
    corners – Output array of detected corners.
    flags – Various operation flags that can be zero or a combination of the following values:
    – CV_CALIB_CB_ADAPTIVE_THRESH Use adaptive thresholding to convert the image
    to black and white, rather than a fixed threshold level (computed from the average
    image brightness).
    – CV_CALIB_CB_NORMALIZE_IMAGE Normalize the image gamma with
    equalizeHist() before applying fixed or adaptive thresholding.
    – CV_CALIB_CB_FILTER_QUADS Use additional criteria (like contour area, perimeter,
    square-like shape) to filter out false quads extracted at the contour retrieval stage.
    – CALIB_CB_FAST_CHECK Run a fast check on the image that looks for chessboard
    corners, and shortcut the call if none is found. This can drastically speed up the call in
    the degenerate condition when no chessboard is observed.

    drawChessboardCorners
    Renders the detected chessboard corners.
    C++: void drawChessboardCorners(InputOutputArray image, Size patternSize, InputArray corners, bool
    patternWasFound)
    Python: cv2.drawChessboardCorners(image, patternSize, corners, patternWasFound)! None
    C: void cvDrawChessboardCorners(CvArr* image, CvSize patternSize, CvPoint2D32f* corners, int
    count, int patternWasFound)
    Python: cv.DrawChessboardCorners(image, patternSize, corners, patternWasFound)! None
    Parameters
    image – Destination image. It must be an 8-bit color image.
    patternSize – Number of inner corners per a chessboard row and column (patternSize =
    cv::Size(points_per_row,points_per_column)).//注意这里表示的是棋盘的大小,别弄错了
    corners – Array of detected corners, the output of findChessboardCorners.
    patternWasFound – Parameter indicating whether the complete board was found or not.
    The return value of findChessboardCorners() should be passed here.
    The function draws individual chessboard corners detected either as red circles if the board was not found, or as
    colored corners connected with lines if the board was found.

    initUndistortRectifyMap
    Computes the undistortion and rectification transformation map.
    C++: void initUndistortRectifyMap(InputArray cameraMatrix, InputArray distCoeffs, InputArray R,
    InputArray newCameraMatrix, Size size, int m1type, OutputArray
    map1, OutputArray map2)

    Parameters 

    cameraMatrix – Input camera matrix A =

    cameraMatrix //不用解释了吧 相机的内参矩阵

    distCoeffs畸变矩阵 – Input vector of distortion coefficients (k1; k2; p1; p2[; k3[; k4; k5; k6]]) of 4,

    5, or 8 elements. If the vector is NULL/empty, the zero distortion coefficients are assumed.

    R代表的是旋转矩阵

    R – Optional rectification transformation in the object space (3x3 matrix). R1 or R2 , computed
    by stereoRectify() can be passed here. If the matrix is empty, the identity transformation
    is assumed. In cvInitUndistortMap R assumed to be an identity matrix.


    newCameraMatrix – New camera matrix A0 =

    size – Undistorted image size.
    m1type – Type of the first output map that can be CV_32FC1 or CV_16SC2 . See
    convertMaps() for details.
    map1 – The first output map.//即是 u

    map2 – The second output map.//即是 v

  • 相关阅读:
    sql 存储过程 in 的两种写法
    C# 开发Chrome内核浏览器(WebKit.net)
    IE6、IE7、IE8、Firefox兼容性
    360浏览器兼容模式 不能$.post (不是a 连接 onclick的问题!!)
    jquery树形表格实现方法
    C#递归累计到父行
    树形结构 DropDownList
    ASP.NET 防止重复提交提示层
    JavaScriptSerializer 时间格式化
    去标签获取网页内容
  • 原文地址:https://www.cnblogs.com/haoxing990/p/4589461.html
Copyright © 2020-2023  润新知