zoukankan      html  css  js  c++  java
  • 相机标定问题-实践操作流程

    接上一篇文章讲解的相机标定的基本概念,这篇文章主要阐述一下如何使用Matlab或者Opencv等软件得的Camera内参之后,如何保存调用内参完成对应Camera的标定流程。

    一、Matlab标定鱼眼镜头实践

    1. 这里我使用的Camera是Jetson Nano专用的鱼眼摄像机,具体参数如下所示:

    我使用的畸变较大的鱼眼镜头。

    由于我采用的是红外夜视的Camera,结果在光线稍微不好的时候就会出现图片偏红色的情况(解决方案:微雪Camera-wiki

        如果大家没有必要的夜视应用场景,建议不要使用红外夜视的摄像头,如果在后期处理的过程中还要对畸变图像矫正,建议就不要使用广角鱼眼摄像头了,因为矫正之后的视野区域也会有所减少,这一点可以在后面矫正的程序中看到(在畸变矫正的过程中,也需要消耗部分CPU资源,这样对于嵌入式板卡来说也许就不划算了)

    2. 基于JetsonNano板卡,CSI摄像头的标定图采集Demo程序如下:

     1 import cv2
     2 import sys
     3 import glob
     4 import time
     5 import threading
     6 import numpy as np
     7 
     8 if len(sys.argv) == 1:
     9     print 'Please Choose the CSI-Camera id for image sample.Try again!'
    10     exit(0)
    11 
    12 Camera_ID = int(sys.argv[1])
    13 
    14 def gstreamer_pipeline(
    15     csi_camera_id = 0,
    16     capture_width=1280,
    17     capture_height=720,
    18     display_width=1280,
    19     display_height=720,
    20     framerate=60,
    21     flip_method=0,
    22 ):
    23     return (
    24         "nvarguscamerasrc sensor_id=%d ! "
    25         "video/x-raw(memory:NVMM), "
    26         "width=(int)%d, height=(int)%d, "
    27         "format=(string)NV12, framerate=(fraction)%d/1 ! "
    28         "nvvidconv flip-method=%d ! "
    29         "video/x-raw, width=(int)%d, height=(int)%d, format=(string)BGRx ! "
    30         "videoconvert ! "
    31         "video/x-raw, format=(string)BGR ! appsink"
    32         % (
    33             csi_camera_id,
    34             capture_width,
    35             capture_height,
    36             framerate,
    37             flip_method,
    38             display_width,
    39             display_height,
    40         )
    41     )
    42 
    43 print 'Starting Capture...'
    44 csi_pipeline_str = gstreamer_pipeline(csi_camera_id=Camera_ID,flip_method=0)
    45 print csi_pipeline_str
    46 cap = cv2.VideoCapture(csi_pipeline_str, cv2.CAP_GSTREAMER)
    47 count = 0
    48 while not cap.isOpened():
    49     time.sleep(0.5)
    50     print('Camera is Initialize...')
    51     count += 1
    52     if count == 10:
    53         print 'CSICamera Initial Failed!'
    54         cap.release()
    55         exit(0)
    56 
    57 ret, frame = cap.read()
    58 
    59 Key_val = 0
    60 
    61 def Keybo_Moni():
    62     count = 0
    63     while True:
    64         global Key_val, frame, process_flag, cap
    65         if Key_val == ord('r'):
    66             Key_val= 0
    67             cv2.imwrite('CSICamera' + str(Camera_ID) + '-' + str(count) + '.jpg', frame)
    68             count += 1
    69             print('Get new pic %d' % count)
    70         if Key_val == ord('q'):
    71             break
    72 
    73 try:
    74     Keybo_Moni_Thread = threading.Thread(target=Keybo_Moni, name='Keyboard-Thread')
    75     Keybo_Moni_Thread.start()
    76 except:
    77     print('Error:uqnable to start the thread!')
    78 
    79 while True:
    80     ret, frame = cap.read()
    81     cv2.imshow('Video_Show', frame)
    82     Key_val = cv2.waitKey(1)
    83     if Key_val == ord('q'):
    84         cv2.destroyAllWindows()
    85         cap.release()
    86         print('Pic Sample Finished!')
    87         break
    88 
    89 print('Finished CalibrateCamera Image Sample...')

    程序中涉及到了Gstreamer等多媒体pipeline框架内容,请参考这里,Python脚本的使用方法:

    python CSICAM_Calibraton_Sample.py 1 # 采集CSI-Camera1摄像头的内容
    python CSICAM_Calibraton_Sample.py 0 # 采集CSI-Camera0摄像头的内容

    如果你使用的其他的USB Camera,可以参考使用如下程序:

     1 import cv2
     2 import glob
     3 import time
     4 import threading
     5 import numpy as np
     6 
     7 print('Starting Capture...')
     8 cap = cv2.VideoCapture(2)
     9 while not cap.isOpened():
    10         time.sleep(100)
    11         print('Camera is Initialize...')
    12 
    13 width = int(cap.get(3))
    14 height = int(cap.get(4))
    15 
    16 frame = np.zeros((width,height,3),dtype=np.uint8)
    17 ret, frame = cap.read()
    18 
    19 Key_val = 0
    20 
    21 def Keybo_Moni():
    22         count = 0
    23         while True:
    24                 global Key_val, frame, process_flag, cap
    25                 if Key_val == ord('r'):
    26                         Key_val= 0
    27                         cv2.imwrite('ResPic' + str(count) + '.jpg', frame)
    28                         count += 1
    29                         print('Get new pic %d' % count)
    30                 if Key_val == ord('q'):
    31                         Key_val = 'q'
    32                         break;
    33 
    34 try:
    35         Keybo_Moni_Thread = threading.Thread(target=Keybo_Moni, name='Keyboard-Thread')
    36         Keybo_Moni_Thread.start()
    37 except:
    38         print('Error:uqnable to start the thread!')
    39 
    40 while True:
    41         ret, frame = cap.read()
    42         cv2.imshow('Video_Show', frame)
    43         Key_val = cv2.waitKey(1)
    44         if Key_val == ord('q'):
    45                 cv2.destroyAllWindows()
    46                 cap.release()
    47                 print('Pic Sample Finished!')
    48                 break
    49 
    50 print('Finished CalibrateCamera Image Sample...')
    View Code

    3. 接下来使用采集图像进行Matlab进行标定

    能够看到,矫正之后的图像还是粉粉的...(问题待解决!)

    具体matlab进行相机标定流程请参看我前一篇内容,下面是矫正前后的效果图:

    从两图对比中,我们可以看出,section_a区域的部分以及Section_b的部分都发生了明显的变化,原来应该显示的内容由于图像在矫正的过程中根据内插法消失了,那么我们如何获取Camera的内参呢?

    对于Matlab之前的版本直接参看上一篇教程,由于我使用的是2019b版本的Matlab,使用操作方式有所不同,在这里说明如下:

    a) 点击工具栏位置的 Export Camera Parameters,这样会输出相机的基本内参以及外参到Matlab的工作空间中:

    这样就会将相机参数保存在工作空间,名称为cameraParams。

    在工作区中,可以找到cameraParams变量,单机右键,打开所选内容,如下所示:

    将图中颜色标出的参数保存即可。

    同时这里我们有必要将工作空间中cameraParams mat变量保存下来为下一次矫正的过程使用提供相机的内参数据,单机右键点击另存为,将相机的参数数据保存即可(参考.mat数据保存使用)。

    b) 点击工具栏位置的 Export Camera Parameters下拉箭头,选择Generate Matalab script:

    % Auto-generated by cameraCalibrator app on 15-Apr-2020
    %-------------------------------------------------------
    
    
    % Define images to process
    imageFileNames = {'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-0.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-3.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-4.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-5.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-7.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-8.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-9.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-10.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-11.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-12.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-13.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-14.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-15.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-16.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-17.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-18.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-19.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-20.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-21.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-22.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-23.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-24.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-25.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-26.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-27.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-28.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-29.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-30.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-31.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-32.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-33.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-34.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-35.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-36.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-37.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-40.jpg',...
        'C:UsersAdministratorDesktopImageDataCAM0CSICamera0-41.jpg',...
        };
    % Detect checkerboards in images
    [imagePoints, boardSize, imagesUsed] = detectCheckerboardPoints(imageFileNames);
    imageFileNames = imageFileNames(imagesUsed);
    
    % Read the first image to obtain image size
    originalImage = imread(imageFileNames{1});
    [mrows, ncols, ~] = size(originalImage);
    
    % Generate world coordinates of the corners of the squares
    squareSize = 40;  % in units of 'millimeters'
    worldPoints = generateCheckerboardPoints(boardSize, squareSize);
    
    % Calibrate the camera
    [cameraParams, imagesUsed, estimationErrors] = estimateCameraParameters(imagePoints, worldPoints, ...
        'EstimateSkew', false, 'EstimateTangentialDistortion', false, ...
        'NumRadialDistortionCoefficients', 2, 'WorldUnits', 'millimeters', ...
        'InitialIntrinsicMatrix', [], 'InitialRadialDistortion', [], ...
        'ImageSize', [mrows, ncols]);
    
    % View reprojection errors
    h1=figure; showReprojectionErrors(cameraParams);
    
    % Visualize pattern locations
    h2=figure; showExtrinsics(cameraParams, 'CameraCentric');
    
    % Display parameter estimation errors
    displayErrors(estimationErrors, cameraParams);
    
    % For example, you can use the calibration data to remove effects of lens distortion.
    undistortedImage = undistortImage(originalImage, cameraParams);
    
    % See additional examples of how to use the calibration data.  At the prompt type:
    % showdemo('MeasuringPlanarObjectsExample')
    % showdemo('StructureFromMotionExample')
    View Code

    运行刚刚生成保存的代码,得到如下的结果:

                Standard Errors of Estimated Camera Parameters
                ----------------------------------------------
    Intrinsics
    ----------
    Focal length (pixels):   [  794.4361 +/- 1.3790      796.3933 +/- 1.3197  ]
    Principal point (pixels):[  606.8329 +/- 0.8403      393.2514 +/- 0.9863  ]
    Radial distortion:       [   -0.3111 +/- 0.0010        0.0837 +/- 0.0007  ]
    Extrinsics
    ----------
    Rotation vectors:
                             [   -0.2723 +/- 0.0024        0.0407 +/- 0.0022        0.0792 +/- 0.0005  ] ...
    Translation vectors (millimeters):
                             [  -90.3841 +/- 0.5212     -121.9121 +/- 0.6037      485.5467 +/- 0.8995  ] ...

    根据上述结果,我们可以得到此鱼眼相机的畸变参数为(k1=-0.3111 k2=0.0837),使用这个参数进行图像的畸变矫正即可。

    4. 使用畸变参数对Camera采集的图像进行矫正:

    将3步骤中保存下来的cameraParams Mat数据加载到Matlab当中:

    load cameraParams

    注意,此时必须添加cameraParams文件保存的文件空间到Matlab工作空间中来,加载完成之后就可以使用参数进行相机采集图片的矫正了:

    I = imread('C:UsersAdministratorDesktopImageDataCAM0CSICamera0-41.jpg');
    I_R = undistortImage(I, cameraParams);
    figure,
    imshow(I_R)
    figure,
    imshow(I)

    运行结果如下所示:

    至此,关于Matlab这端的图像畸变矫正过程就算是完成了,如何使用畸变以及相机内参完成畸变矫正参看下面链接:

    相机畸变校正详解:https://blog.csdn.net/hanxiaoyong_/article/details/82888946

    二、Cpp-Opencv标定鱼眼镜头实践

    1. 依然使用之前采集的图片源,使用Opencv官方代码进行Camera的矫正:

    首先下载官方源代码:https://github.com/opencv/opencv/tree/master/samples/cpp/tutorial_code/calib3d/camera_calibration

    参考官方标定算法手册:https://docs.opencv.org/master/d4/d94/tutorial_camera_calibration.html

     下载很慢的可以直接拷贝我的程序:

    camera_calibration.cpp (主程序文件,包括了图像输入,图像角点提取,图形标定,相机参数保存等功能模块)

      1 #include <iostream>
      2 #include <sstream>
      3 #include <string>
      4 #include <ctime>
      5 #include <cstdio>
      6 
      7 #include <opencv2/core.hpp>
      8 #include <opencv2/core/utility.hpp>
      9 #include <opencv2/imgproc.hpp>
     10 #include <opencv2/calib3d.hpp>
     11 #include <opencv2/imgcodecs.hpp>
     12 #include <opencv2/videoio.hpp>
     13 #include <opencv2/highgui.hpp>
     14 
     15 using namespace cv;
     16 using namespace std;
     17 
     18 class Settings
     19 {
     20 public:
     21     Settings() : goodInput(false) {}
     22     enum Pattern { NOT_EXISTING, CHESSBOARD, CIRCLES_GRID, ASYMMETRIC_CIRCLES_GRID };
     23     enum InputType { INVALID, CAMERA, VIDEO_FILE, IMAGE_LIST };
     24 
     25     void write(FileStorage& fs) const                        //Write serialization for this class
     26     {
     27         fs << "{"
     28                   << "BoardSize_Width"  << boardSize.width
     29                   << "BoardSize_Height" << boardSize.height
     30                   << "Square_Size"         << squareSize
     31                   << "Calibrate_Pattern" << patternToUse
     32                   << "Calibrate_NrOfFrameToUse" << nrFrames
     33                   << "Calibrate_FixAspectRatio" << aspectRatio
     34                   << "Calibrate_AssumeZeroTangentialDistortion" << calibZeroTangentDist
     35                   << "Calibrate_FixPrincipalPointAtTheCenter" << calibFixPrincipalPoint
     36 
     37                   << "Write_DetectedFeaturePoints" << writePoints
     38                   << "Write_extrinsicParameters"   << writeExtrinsics
     39                   << "Write_gridPoints" << writeGrid
     40                   << "Write_outputFileName"  << outputFileName
     41 
     42                   << "Show_UndistortedImage" << showUndistorsed
     43 
     44                   << "Input_FlipAroundHorizontalAxis" << flipVertical
     45                   << "Input_Delay" << delay
     46                   << "Input" << input
     47            << "}";
     48     }
     49     void read(const FileNode& node)                          //Read serialization for this class
     50     {
     51         node["BoardSize_Width" ] >> boardSize.width;
     52         node["BoardSize_Height"] >> boardSize.height;
     53         node["Calibrate_Pattern"] >> patternToUse;
     54         node["Square_Size"]  >> squareSize;
     55         node["Calibrate_NrOfFrameToUse"] >> nrFrames;
     56         node["Calibrate_FixAspectRatio"] >> aspectRatio;
     57         node["Write_DetectedFeaturePoints"] >> writePoints;
     58         node["Write_extrinsicParameters"] >> writeExtrinsics;
     59         node["Write_gridPoints"] >> writeGrid;
     60         node["Write_outputFileName"] >> outputFileName;
     61         node["Calibrate_AssumeZeroTangentialDistortion"] >> calibZeroTangentDist;
     62         node["Calibrate_FixPrincipalPointAtTheCenter"] >> calibFixPrincipalPoint;
     63         node["Calibrate_UseFisheyeModel"] >> useFisheye;
     64         node["Input_FlipAroundHorizontalAxis"] >> flipVertical;
     65         node["Show_UndistortedImage"] >> showUndistorsed;
     66         node["Input"] >> input;
     67         node["Input_Delay"] >> delay;
     68         node["Fix_K1"] >> fixK1;
     69         node["Fix_K2"] >> fixK2;
     70         node["Fix_K3"] >> fixK3;
     71         node["Fix_K4"] >> fixK4;
     72         node["Fix_K5"] >> fixK5;
     73 
     74         validate();
     75     }
     76     void validate()
     77     {
     78         goodInput = true;
     79         if (boardSize.width <= 0 || boardSize.height <= 0)
     80         {
     81             cerr << "Invalid Board size: " << boardSize.width << " " << boardSize.height << endl;
     82             goodInput = false;
     83         }
     84         if (squareSize <= 10e-6)
     85         {
     86             cerr << "Invalid square size " << squareSize << endl;
     87             goodInput = false;
     88         }
     89         if (nrFrames <= 0)
     90         {
     91             cerr << "Invalid number of frames " << nrFrames << endl;
     92             goodInput = false;
     93         }
     94 
     95         if (input.empty())      // Check for valid input
     96                 inputType = INVALID;
     97         else
     98         {
     99             if (input[0] >= '0' && input[0] <= '9')
    100             {
    101                 stringstream ss(input);
    102                 ss >> cameraID;
    103                 inputType = CAMERA;
    104             }
    105             else
    106             {
    107                 if (isListOfImages(input) && readStringList(input, imageList))
    108                 {
    109                     inputType = IMAGE_LIST;
    110                     nrFrames = (nrFrames < (int)imageList.size()) ? nrFrames : (int)imageList.size();
    111                 }
    112                 else
    113                     inputType = VIDEO_FILE;
    114             }
    115             if (inputType == CAMERA)
    116                 inputCapture.open(cameraID);
    117             if (inputType == VIDEO_FILE)
    118                 inputCapture.open(input);
    119             if (inputType != IMAGE_LIST && !inputCapture.isOpened())
    120                     inputType = INVALID;
    121         }
    122         if (inputType == INVALID)
    123         {
    124             cerr << " Input does not exist: " << input;
    125             goodInput = false;
    126         }
    127 
    128         flag = 0;
    129         if(calibFixPrincipalPoint) flag |= CALIB_FIX_PRINCIPAL_POINT;
    130         if(calibZeroTangentDist)   flag |= CALIB_ZERO_TANGENT_DIST;
    131         if(aspectRatio)            flag |= CALIB_FIX_ASPECT_RATIO;
    132         if(fixK1)                  flag |= CALIB_FIX_K1;
    133         if(fixK2)                  flag |= CALIB_FIX_K2;
    134         if(fixK3)                  flag |= CALIB_FIX_K3;
    135         if(fixK4)                  flag |= CALIB_FIX_K4;
    136         if(fixK5)                  flag |= CALIB_FIX_K5;
    137 
    138         if (useFisheye) {
    139             // the fisheye model has its own enum, so overwrite the flags
    140             flag = fisheye::CALIB_FIX_SKEW | fisheye::CALIB_RECOMPUTE_EXTRINSIC;
    141             if(fixK1)                   flag |= fisheye::CALIB_FIX_K1;
    142             if(fixK2)                   flag |= fisheye::CALIB_FIX_K2;
    143             if(fixK3)                   flag |= fisheye::CALIB_FIX_K3;
    144             if(fixK4)                   flag |= fisheye::CALIB_FIX_K4;
    145             if (calibFixPrincipalPoint) flag |= fisheye::CALIB_FIX_PRINCIPAL_POINT;
    146         }
    147 
    148         calibrationPattern = NOT_EXISTING;
    149         if (!patternToUse.compare("CHESSBOARD")) calibrationPattern = CHESSBOARD;
    150         if (!patternToUse.compare("CIRCLES_GRID")) calibrationPattern = CIRCLES_GRID;
    151         if (!patternToUse.compare("ASYMMETRIC_CIRCLES_GRID")) calibrationPattern = ASYMMETRIC_CIRCLES_GRID;
    152         if (calibrationPattern == NOT_EXISTING)
    153         {
    154             cerr << " Camera calibration mode does not exist: " << patternToUse << endl;
    155             goodInput = false;
    156         }
    157         atImageList = 0;
    158 
    159     }
    160     Mat nextImage()
    161     {
    162         Mat result;
    163         if( inputCapture.isOpened() )
    164         {
    165             Mat view0;
    166             inputCapture >> view0;
    167             view0.copyTo(result);
    168         }
    169         else if( atImageList < imageList.size() )
    170             result = imread(imageList[atImageList++], IMREAD_COLOR);
    171 
    172         return result;
    173     }
    174 
    175     static bool readStringList( const string& filename, vector<string>& l )
    176     {
    177         l.clear();
    178         FileStorage fs(filename, FileStorage::READ);
    179         if( !fs.isOpened() )
    180             return false;
    181         FileNode n = fs.getFirstTopLevelNode();
    182         if( n.type() != FileNode::SEQ )
    183             return false;
    184         FileNodeIterator it = n.begin(), it_end = n.end();
    185         for( ; it != it_end; ++it )
    186             l.push_back((string)*it);
    187         return true;
    188     }
    189 
    190     static bool isListOfImages( const string& filename)
    191     {
    192         string s(filename);
    193         // Look for file extension
    194         if( s.find(".xml") == string::npos && s.find(".yaml") == string::npos && s.find(".yml") == string::npos )
    195             return false;
    196         else
    197             return true;
    198     }
    199 public:
    200     Size boardSize;              // The size of the board -> Number of items by width and height
    201     Pattern calibrationPattern;  // One of the Chessboard, circles, or asymmetric circle pattern
    202     float squareSize;            // The size of a square in your defined unit (point, millimeter,etc).
    203     int nrFrames;                // The number of frames to use from the input for calibration
    204     float aspectRatio;           // The aspect ratio
    205     int delay;                   // In case of a video input
    206     bool writePoints;            // Write detected feature points
    207     bool writeExtrinsics;        // Write extrinsic parameters
    208     bool writeGrid;              // Write refined 3D target grid points
    209     bool calibZeroTangentDist;   // Assume zero tangential distortion
    210     bool calibFixPrincipalPoint; // Fix the principal point at the center
    211     bool flipVertical;           // Flip the captured images around the horizontal axis
    212     string outputFileName;       // The name of the file where to write
    213     bool showUndistorsed;        // Show undistorted images after calibration
    214     string input;                // The input ->
    215     bool useFisheye;             // use fisheye camera model for calibration
    216     bool fixK1;                  // fix K1 distortion coefficient
    217     bool fixK2;                  // fix K2 distortion coefficient
    218     bool fixK3;                  // fix K3 distortion coefficient
    219     bool fixK4;                  // fix K4 distortion coefficient
    220     bool fixK5;                  // fix K5 distortion coefficient
    221 
    222     int cameraID;
    223     vector<string> imageList;
    224     size_t atImageList;
    225     VideoCapture inputCapture;
    226     InputType inputType;
    227     bool goodInput;
    228     int flag;
    229 
    230 private:
    231     string patternToUse;
    232 
    233 
    234 };
    235 
    236 static inline void read(const FileNode& node, Settings& x, const Settings& default_value = Settings())
    237 {
    238     if(node.empty())
    239         x = default_value;
    240     else
    241         x.read(node);
    242 }
    243 
    244 enum { DETECTION = 0, CAPTURING = 1, CALIBRATED = 2 };
    245 
    246 bool runCalibrationAndSave(Settings& s, Size imageSize, Mat&  cameraMatrix, Mat& distCoeffs,
    247                            vector<vector<Point2f> > imagePoints, float grid_width, bool release_object);
    248 
    249 int main(int argc, char* argv[])
    250 {
    251     const String keys
    252         = "{help h usage ? |           | print this message            }"
    253           "{@settings      |default.xml| input setting file            }"
    254           "{d              |           | actual distance between top-left and top-right corners of "
    255           "the calibration grid }"
    256           "{winSize        | 11        | Half of search window for cornerSubPix }";
    257     CommandLineParser parser(argc, argv, keys);
    258     parser.about("This is a camera calibration sample.
    "
    259                  "Usage: camera_calibration [configuration_file -- default ./default.xml]
    "
    260                  "Near the sample file you'll find the configuration file, which has detailed help of "
    261                  "how to edit it. It may be any OpenCV supported file format XML/YAML.");
    262     if (!parser.check()) {
    263         parser.printErrors();
    264         return 0;
    265     }
    266 
    267     if (parser.has("help")) {
    268         parser.printMessage();
    269         return 0;
    270     }
    271 
    272     //! [file_read]
    273     Settings s;
    274     const string inputSettingsFile = parser.get<string>(0);
    275     FileStorage fs(inputSettingsFile, FileStorage::READ); // Read the settings
    276     if (!fs.isOpened())
    277     {
    278         cout << "Could not open the configuration file: "" << inputSettingsFile << """ << endl;
    279         parser.printMessage();
    280         return -1;
    281     }
    282     fs["Settings"] >> s;
    283     fs.release();                                         // close Settings file
    284     //! [file_read]
    285 
    286     //FileStorage fout("settings.yml", FileStorage::WRITE); // write config as YAML
    287     //fout << "Settings" << s;
    288 
    289     if (!s.goodInput)
    290     {
    291         cout << "Invalid input detected. Application stopping. " << endl;
    292         return -1;
    293     }
    294 
    295     int winSize = parser.get<int>("winSize");
    296 
    297     float grid_width = s.squareSize * (s.boardSize.width - 1);
    298     bool release_object = false;
    299     if (parser.has("d")) {
    300         grid_width = parser.get<float>("d");
    301         release_object = true;
    302     }
    303 
    304     vector<vector<Point2f> > imagePoints;
    305     Mat cameraMatrix, distCoeffs;
    306     Size imageSize;
    307     int mode = s.inputType == Settings::IMAGE_LIST ? CAPTURING : DETECTION;
    308     clock_t prevTimestamp = 0;
    309     const Scalar RED(0,0,255), GREEN(0,255,0);
    310     const char ESC_KEY = 27;
    311 
    312     //! [get_input]
    313     for(;;)
    314     {
    315         Mat view;
    316         bool blinkOutput = false;
    317 
    318         view = s.nextImage();
    319 
    320         //-----  If no more image, or got enough, then stop calibration and show result -------------
    321         if( mode == CAPTURING && imagePoints.size() >= (size_t)s.nrFrames )
    322         {
    323           if(runCalibrationAndSave(s, imageSize,  cameraMatrix, distCoeffs, imagePoints, grid_width,
    324                                    release_object))
    325               mode = CALIBRATED;
    326           else
    327               mode = DETECTION;
    328         }
    329         if(view.empty())          // If there are no more images stop the loop
    330         {
    331             // if calibration threshold was not reached yet, calibrate now
    332             if( mode != CALIBRATED && !imagePoints.empty() )
    333                 runCalibrationAndSave(s, imageSize,  cameraMatrix, distCoeffs, imagePoints, grid_width,
    334                                       release_object);
    335             break;
    336         }
    337         //! [get_input]
    338 
    339         imageSize = view.size();  // Format input image.
    340         if( s.flipVertical )    flip( view, view, 0 );
    341 
    342         //! [find_pattern]
    343         vector<Point2f> pointBuf;
    344 
    345         bool found;
    346 
    347         int chessBoardFlags = CALIB_CB_ADAPTIVE_THRESH | CALIB_CB_NORMALIZE_IMAGE;
    348 
    349         if(!s.useFisheye) {
    350             // fast check erroneously fails with high distortions like fisheye
    351             chessBoardFlags |= CALIB_CB_FAST_CHECK;
    352         }
    353 
    354         switch( s.calibrationPattern ) // Find feature points on the input format
    355         {
    356         case Settings::CHESSBOARD:
    357             found = findChessboardCorners( view, s.boardSize, pointBuf, chessBoardFlags);
    358             break;
    359         case Settings::CIRCLES_GRID:
    360             found = findCirclesGrid( view, s.boardSize, pointBuf );
    361             break;
    362         case Settings::ASYMMETRIC_CIRCLES_GRID:
    363             found = findCirclesGrid( view, s.boardSize, pointBuf, CALIB_CB_ASYMMETRIC_GRID );
    364             break;
    365         default:
    366             found = false;
    367             break;
    368         }
    369         //! [find_pattern]
    370         //! [pattern_found]
    371         if ( found)                // If done with success,
    372         {
    373               // improve the found corners' coordinate accuracy for chessboard
    374                 if( s.calibrationPattern == Settings::CHESSBOARD)
    375                 {
    376                     Mat viewGray;
    377                     cvtColor(view, viewGray, COLOR_BGR2GRAY);
    378                     cornerSubPix( viewGray, pointBuf, Size(winSize,winSize),
    379                         Size(-1,-1), TermCriteria( TermCriteria::EPS+TermCriteria::COUNT, 30, 0.0001 ));
    380                 }
    381 
    382                 if( mode == CAPTURING &&  // For camera only take new samples after delay time
    383                     (!s.inputCapture.isOpened() || clock() - prevTimestamp > s.delay*1e-3*CLOCKS_PER_SEC) )
    384                 {
    385                     imagePoints.push_back(pointBuf);
    386                     prevTimestamp = clock();
    387                     blinkOutput = s.inputCapture.isOpened();
    388                 }
    389 
    390                 // Draw the corners.
    391                 drawChessboardCorners( view, s.boardSize, Mat(pointBuf), found );
    392         }
    393         //! [pattern_found]
    394         //----------------------------- Output Text ------------------------------------------------
    395         //! [output_text]
    396         string msg = (mode == CAPTURING) ? "100/100" :
    397                       mode == CALIBRATED ? "Calibrated" : "Press 'g' to start";
    398         int baseLine = 0;
    399         Size textSize = getTextSize(msg, 1, 1, 1, &baseLine);
    400         Point textOrigin(view.cols - 2*textSize.width - 10, view.rows - 2*baseLine - 10);
    401 
    402         if( mode == CAPTURING )
    403         {
    404             if(s.showUndistorsed)
    405                 msg = format( "%d/%d Undist", (int)imagePoints.size(), s.nrFrames );
    406             else
    407                 msg = format( "%d/%d", (int)imagePoints.size(), s.nrFrames );
    408         }
    409 
    410         putText( view, msg, textOrigin, 1, 1, mode == CALIBRATED ?  GREEN : RED);
    411 
    412         if( blinkOutput )
    413             bitwise_not(view, view);
    414         //! [output_text]
    415         //------------------------- Video capture  output  undistorted ------------------------------
    416         //! [output_undistorted]
    417         if( mode == CALIBRATED && s.showUndistorsed )
    418         {
    419             Mat temp = view.clone();
    420             if (s.useFisheye)
    421               cv::fisheye::undistortImage(temp, view, cameraMatrix, distCoeffs);
    422             else
    423               undistort(temp, view, cameraMatrix, distCoeffs);
    424         }
    425         //! [output_undistorted]
    426         //------------------------------ Show image and check for input commands -------------------
    427         //! [await_input]
    428         imshow("Image View", view);
    429         char key = (char)waitKey(s.inputCapture.isOpened() ? 50 : s.delay);
    430 
    431         if( key  == ESC_KEY )
    432             break;
    433 
    434         if( key == 'u' && mode == CALIBRATED )
    435            s.showUndistorsed = !s.showUndistorsed;
    436 
    437         if( s.inputCapture.isOpened() && key == 'g' )
    438         {
    439             mode = CAPTURING;
    440             imagePoints.clear();
    441         }
    442         //! [await_input]
    443     }
    444 
    445     // -----------------------Show the undistorted image for the image list ------------------------
    446     //! [show_results]
    447     if( s.inputType == Settings::IMAGE_LIST && s.showUndistorsed )
    448     {
    449         Mat view, rview, map1, map2;
    450 
    451         if (s.useFisheye)
    452         {
    453             Mat newCamMat;
    454             fisheye::estimateNewCameraMatrixForUndistortRectify(cameraMatrix, distCoeffs, imageSize,
    455                                                                 Matx33d::eye(), newCamMat, 1);
    456             fisheye::initUndistortRectifyMap(cameraMatrix, distCoeffs, Matx33d::eye(), newCamMat, imageSize,
    457                                              CV_16SC2, map1, map2);
    458         }
    459         else
    460         {
    461             initUndistortRectifyMap(
    462                 cameraMatrix, distCoeffs, Mat(),
    463                 getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, 1, imageSize, 0), imageSize,
    464                 CV_16SC2, map1, map2);
    465         }
    466 
    467         for(size_t i = 0; i < s.imageList.size(); i++ )
    468         {
    469             view = imread(s.imageList[i], IMREAD_COLOR);
    470             if(view.empty())
    471                 continue;
    472             remap(view, rview, map1, map2, INTER_LINEAR);
    473             imshow("Image View", rview);
    474             char c = (char)waitKey();
    475             if( c  == ESC_KEY || c == 'q' || c == 'Q' )
    476                 break;
    477         }
    478     }
    479     //! [show_results]
    480 
    481     return 0;
    482 }
    483 
    484 //! [compute_errors]
    485 static double computeReprojectionErrors( const vector<vector<Point3f> >& objectPoints,
    486                                          const vector<vector<Point2f> >& imagePoints,
    487                                          const vector<Mat>& rvecs, const vector<Mat>& tvecs,
    488                                          const Mat& cameraMatrix , const Mat& distCoeffs,
    489                                          vector<float>& perViewErrors, bool fisheye)
    490 {
    491     vector<Point2f> imagePoints2;
    492     size_t totalPoints = 0;
    493     double totalErr = 0, err;
    494     perViewErrors.resize(objectPoints.size());
    495 
    496     for(size_t i = 0; i < objectPoints.size(); ++i )
    497     {
    498         if (fisheye)
    499         {
    500             fisheye::projectPoints(objectPoints[i], imagePoints2, rvecs[i], tvecs[i], cameraMatrix,
    501                                    distCoeffs);
    502         }
    503         else
    504         {
    505             projectPoints(objectPoints[i], rvecs[i], tvecs[i], cameraMatrix, distCoeffs, imagePoints2);
    506         }
    507         err = norm(imagePoints[i], imagePoints2, NORM_L2);
    508 
    509         size_t n = objectPoints[i].size();
    510         perViewErrors[i] = (float) std::sqrt(err*err/n);
    511         totalErr        += err*err;
    512         totalPoints     += n;
    513     }
    514 
    515     return std::sqrt(totalErr/totalPoints);
    516 }
    517 //! [compute_errors]
    518 //! [board_corners]
    519 static void calcBoardCornerPositions(Size boardSize, float squareSize, vector<Point3f>& corners,
    520                                      Settings::Pattern patternType /*= Settings::CHESSBOARD*/)
    521 {
    522     corners.clear();
    523 
    524     switch(patternType)
    525     {
    526     case Settings::CHESSBOARD:
    527     case Settings::CIRCLES_GRID:
    528         for( int i = 0; i < boardSize.height; ++i )
    529             for( int j = 0; j < boardSize.width; ++j )
    530                 corners.push_back(Point3f(j*squareSize, i*squareSize, 0));
    531         break;
    532 
    533     case Settings::ASYMMETRIC_CIRCLES_GRID:
    534         for( int i = 0; i < boardSize.height; i++ )
    535             for( int j = 0; j < boardSize.width; j++ )
    536                 corners.push_back(Point3f((2*j + i % 2)*squareSize, i*squareSize, 0));
    537         break;
    538     default:
    539         break;
    540     }
    541 }
    542 //! [board_corners]
    543 static bool runCalibration( Settings& s, Size& imageSize, Mat& cameraMatrix, Mat& distCoeffs,
    544                             vector<vector<Point2f> > imagePoints, vector<Mat>& rvecs, vector<Mat>& tvecs,
    545                             vector<float>& reprojErrs,  double& totalAvgErr, vector<Point3f>& newObjPoints,
    546                             float grid_width, bool release_object)
    547 {
    548     //! [fixed_aspect]
    549     cameraMatrix = Mat::eye(3, 3, CV_64F);
    550     if( s.flag & CALIB_FIX_ASPECT_RATIO )
    551         cameraMatrix.at<double>(0,0) = s.aspectRatio;
    552     //! [fixed_aspect]
    553     if (s.useFisheye) {
    554         distCoeffs = Mat::zeros(4, 1, CV_64F);
    555     } else {
    556         distCoeffs = Mat::zeros(8, 1, CV_64F);
    557     }
    558 
    559     vector<vector<Point3f> > objectPoints(1);
    560     calcBoardCornerPositions(s.boardSize, s.squareSize, objectPoints[0], s.calibrationPattern);
    561     objectPoints[0][s.boardSize.width - 1].x = objectPoints[0][0].x + grid_width;
    562     newObjPoints = objectPoints[0];
    563 
    564     objectPoints.resize(imagePoints.size(),objectPoints[0]);
    565 
    566     //Find intrinsic and extrinsic camera parameters
    567     double rms;
    568 
    569     if (s.useFisheye) {
    570         Mat _rvecs, _tvecs;
    571         rms = fisheye::calibrate(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, _rvecs,
    572                                  _tvecs, s.flag);
    573 
    574         rvecs.reserve(_rvecs.rows);
    575         tvecs.reserve(_tvecs.rows);
    576         for(int i = 0; i < int(objectPoints.size()); i++){
    577             rvecs.push_back(_rvecs.row(i));
    578             tvecs.push_back(_tvecs.row(i));
    579         }
    580     } else {
    581         int iFixedPoint = -1;
    582         if (release_object)
    583             iFixedPoint = s.boardSize.width - 1;
    584         rms = calibrateCameraRO(objectPoints, imagePoints, imageSize, iFixedPoint,
    585                                 cameraMatrix, distCoeffs, rvecs, tvecs, newObjPoints,
    586                                 s.flag | CALIB_USE_LU);
    587     }
    588 
    589     if (release_object) {
    590         cout << "New board corners: " << endl;
    591         cout << newObjPoints[0] << endl;
    592         cout << newObjPoints[s.boardSize.width - 1] << endl;
    593         cout << newObjPoints[s.boardSize.width * (s.boardSize.height - 1)] << endl;
    594         cout << newObjPoints.back() << endl;
    595     }
    596 
    597     cout << "Re-projection error reported by calibrateCamera: "<< rms << endl;
    598 
    599     bool ok = checkRange(cameraMatrix) && checkRange(distCoeffs);
    600 
    601     objectPoints.clear();
    602     objectPoints.resize(imagePoints.size(), newObjPoints);
    603     totalAvgErr = computeReprojectionErrors(objectPoints, imagePoints, rvecs, tvecs, cameraMatrix,
    604                                             distCoeffs, reprojErrs, s.useFisheye);
    605 
    606     return ok;
    607 }
    608 
    609 // Print camera parameters to the output file
    610 static void saveCameraParams( Settings& s, Size& imageSize, Mat& cameraMatrix, Mat& distCoeffs,
    611                               const vector<Mat>& rvecs, const vector<Mat>& tvecs,
    612                               const vector<float>& reprojErrs, const vector<vector<Point2f> >& imagePoints,
    613                               double totalAvgErr, const vector<Point3f>& newObjPoints )
    614 {
    615     FileStorage fs( s.outputFileName, FileStorage::WRITE );
    616 
    617     time_t tm;
    618     time( &tm );
    619     struct tm *t2 = localtime( &tm );
    620     char buf[1024];
    621     strftime( buf, sizeof(buf), "%c", t2 );
    622 
    623     fs << "calibration_time" << buf;
    624 
    625     if( !rvecs.empty() || !reprojErrs.empty() )
    626         fs << "nr_of_frames" << (int)std::max(rvecs.size(), reprojErrs.size());
    627     fs << "image_width" << imageSize.width;
    628     fs << "image_height" << imageSize.height;
    629     fs << "board_width" << s.boardSize.width;
    630     fs << "board_height" << s.boardSize.height;
    631     fs << "square_size" << s.squareSize;
    632 
    633     if( s.flag & CALIB_FIX_ASPECT_RATIO )
    634         fs << "fix_aspect_ratio" << s.aspectRatio;
    635 
    636     if (s.flag)
    637     {
    638         std::stringstream flagsStringStream;
    639         if (s.useFisheye)
    640         {
    641             flagsStringStream << "flags:"
    642                 << (s.flag & fisheye::CALIB_FIX_SKEW ? " +fix_skew" : "")
    643                 << (s.flag & fisheye::CALIB_FIX_K1 ? " +fix_k1" : "")
    644                 << (s.flag & fisheye::CALIB_FIX_K2 ? " +fix_k2" : "")
    645                 << (s.flag & fisheye::CALIB_FIX_K3 ? " +fix_k3" : "")
    646                 << (s.flag & fisheye::CALIB_FIX_K4 ? " +fix_k4" : "")
    647                 << (s.flag & fisheye::CALIB_RECOMPUTE_EXTRINSIC ? " +recompute_extrinsic" : "");
    648         }
    649         else
    650         {
    651             flagsStringStream << "flags:"
    652                 << (s.flag & CALIB_USE_INTRINSIC_GUESS ? " +use_intrinsic_guess" : "")
    653                 << (s.flag & CALIB_FIX_ASPECT_RATIO ? " +fix_aspectRatio" : "")
    654                 << (s.flag & CALIB_FIX_PRINCIPAL_POINT ? " +fix_principal_point" : "")
    655                 << (s.flag & CALIB_ZERO_TANGENT_DIST ? " +zero_tangent_dist" : "")
    656                 << (s.flag & CALIB_FIX_K1 ? " +fix_k1" : "")
    657                 << (s.flag & CALIB_FIX_K2 ? " +fix_k2" : "")
    658                 << (s.flag & CALIB_FIX_K3 ? " +fix_k3" : "")
    659                 << (s.flag & CALIB_FIX_K4 ? " +fix_k4" : "")
    660                 << (s.flag & CALIB_FIX_K5 ? " +fix_k5" : "");
    661         }
    662         fs.writeComment(flagsStringStream.str());
    663     }
    664 
    665     fs << "flags" << s.flag;
    666 
    667     fs << "fisheye_model" << s.useFisheye;
    668 
    669     fs << "camera_matrix" << cameraMatrix;
    670     fs << "distortion_coefficients" << distCoeffs;
    671 
    672     fs << "avg_reprojection_error" << totalAvgErr;
    673     if (s.writeExtrinsics && !reprojErrs.empty())
    674         fs << "per_view_reprojection_errors" << Mat(reprojErrs);
    675 
    676     if(s.writeExtrinsics && !rvecs.empty() && !tvecs.empty() )
    677     {
    678         CV_Assert(rvecs[0].type() == tvecs[0].type());
    679         Mat bigmat((int)rvecs.size(), 6, CV_MAKETYPE(rvecs[0].type(), 1));
    680         bool needReshapeR = rvecs[0].depth() != 1 ? true : false;
    681         bool needReshapeT = tvecs[0].depth() != 1 ? true : false;
    682 
    683         for( size_t i = 0; i < rvecs.size(); i++ )
    684         {
    685             Mat r = bigmat(Range(int(i), int(i+1)), Range(0,3));
    686             Mat t = bigmat(Range(int(i), int(i+1)), Range(3,6));
    687 
    688             if(needReshapeR)
    689                 rvecs[i].reshape(1, 1).copyTo(r);
    690             else
    691             {
    692                 //*.t() is MatExpr (not Mat) so we can use assignment operator
    693                 CV_Assert(rvecs[i].rows == 3 && rvecs[i].cols == 1);
    694                 r = rvecs[i].t();
    695             }
    696 
    697             if(needReshapeT)
    698                 tvecs[i].reshape(1, 1).copyTo(t);
    699             else
    700             {
    701                 CV_Assert(tvecs[i].rows == 3 && tvecs[i].cols == 1);
    702                 t = tvecs[i].t();
    703             }
    704         }
    705         fs.writeComment("a set of 6-tuples (rotation vector + translation vector) for each view");
    706         fs << "extrinsic_parameters" << bigmat;
    707     }
    708 
    709     if(s.writePoints && !imagePoints.empty() )
    710     {
    711         Mat imagePtMat((int)imagePoints.size(), (int)imagePoints[0].size(), CV_32FC2);
    712         for( size_t i = 0; i < imagePoints.size(); i++ )
    713         {
    714             Mat r = imagePtMat.row(int(i)).reshape(2, imagePtMat.cols);
    715             Mat imgpti(imagePoints[i]);
    716             imgpti.copyTo(r);
    717         }
    718         fs << "image_points" << imagePtMat;
    719     }
    720 
    721     if( s.writeGrid && !newObjPoints.empty() )
    722     {
    723         fs << "grid_points" << newObjPoints;
    724     }
    725 }
    726 
    727 //! [run_and_save]
    728 bool runCalibrationAndSave(Settings& s, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs,
    729                            vector<vector<Point2f> > imagePoints, float grid_width, bool release_object)
    730 {
    731     vector<Mat> rvecs, tvecs;
    732     vector<float> reprojErrs;
    733     double totalAvgErr = 0;
    734     vector<Point3f> newObjPoints;
    735 
    736     bool ok = runCalibration(s, imageSize, cameraMatrix, distCoeffs, imagePoints, rvecs, tvecs, reprojErrs,
    737                              totalAvgErr, newObjPoints, grid_width, release_object);
    738     cout << (ok ? "Calibration succeeded" : "Calibration failed")
    739          << ". avg re projection error = " << totalAvgErr << endl;
    740 
    741     if (ok)
    742         saveCameraParams(s, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, reprojErrs, imagePoints,
    743                          totalAvgErr, newObjPoints);
    744     return ok;
    745 }
    746 //! [run_and_save]
    View Code

    VID5.xml (外部配置文件,包括了待标定相机采集图像的绝对路径或者相对路径)

    <?xml version="1.0"?>
    <opencv_storage>
    <images>
    images/CameraCalibraation/VID5/xx1.jpg
    images/CameraCalibraation/VID5/xx2.jpg
    images/CameraCalibraation/VID5/xx3.jpg
    images/CameraCalibraation/VID5/xx4.jpg
    images/CameraCalibraation/VID5/xx5.jpg
    images/CameraCalibraation/VID5/xx6.jpg
    images/CameraCalibraation/VID5/xx7.jpg
    images/CameraCalibraation/VID5/xx8.jpg
    </images>
    </opencv_storage>
    View Code

    in_VID5.xml (标定基本参数配置,包括了标定的模式,图像样本的获取方式等等)

    <?xml version="1.0"?>
    <opencv_storage>
    <Settings>
      <!-- Number of inner corners per a item row and column. (square, circle) -->
      <BoardSize_Width> 9</BoardSize_Width>
      <BoardSize_Height>6</BoardSize_Height>
      
      <!-- The size of a square in some user defined metric system (pixel, millimeter)-->
      <Square_Size>50</Square_Size>
      
      <!-- The type of input used for camera calibration. One of: CHESSBOARD CIRCLES_GRID ASYMMETRIC_CIRCLES_GRID -->
      <Calibrate_Pattern>"CHESSBOARD"</Calibrate_Pattern>
      
      <!-- The input to use for calibration. 
            To use an input camera -> give the ID of the camera, like "1"
            To use an input video  -> give the path of the input video, like "/tmp/x.avi"
            To use an image list   -> give the path to the XML or YAML file containing the list of the images, like "/tmp/circles_list.xml"
            -->
      <Input>"images/CameraCalibration/VID5/VID5.xml"</Input>
      <!--  If true (non-zero) we flip the input images around the horizontal axis.-->
      <Input_FlipAroundHorizontalAxis>0</Input_FlipAroundHorizontalAxis>
      
      <!-- Time delay between frames in case of camera. -->
      <Input_Delay>100</Input_Delay>    
      
      <!-- How many frames to use, for calibration. -->
      <Calibrate_NrOfFrameToUse>25</Calibrate_NrOfFrameToUse>
      <!-- Consider only fy as a free parameter, the ratio fx/fy stays the same as in the input cameraMatrix. 
           Use or not setting. 0 - False Non-Zero - True-->
      <Calibrate_FixAspectRatio> 1 </Calibrate_FixAspectRatio>
      <!-- If true (non-zero) tangential distortion coefficients  are set to zeros and stay zero.-->
      <Calibrate_AssumeZeroTangentialDistortion>1</Calibrate_AssumeZeroTangentialDistortion>
      <!-- If true (non-zero) the principal point is not changed during the global optimization.-->
      <Calibrate_FixPrincipalPointAtTheCenter> 1 </Calibrate_FixPrincipalPointAtTheCenter>
      
      <!-- The name of the output log file. -->
      <Write_outputFileName>"out_camera_data.xml"</Write_outputFileName>
      <!-- If true (non-zero) we write to the output file the feature points.-->
      <Write_DetectedFeaturePoints>1</Write_DetectedFeaturePoints>
      <!-- If true (non-zero) we write to the output file the extrinsic camera parameters.-->
      <Write_extrinsicParameters>1</Write_extrinsicParameters>
      <!-- If true (non-zero) we write to the output file the refined 3D target grid points.-->
      <Write_gridPoints>1</Write_gridPoints>
      <!-- If true (non-zero) we show after calibration the undistorted images.-->
      <Show_UndistortedImage>1</Show_UndistortedImage>
      <!-- If true (non-zero) will be used fisheye camera model.-->
      <Calibrate_UseFisheyeModel>0</Calibrate_UseFisheyeModel>
      <!-- If true (non-zero) distortion coefficient k1 will be equals to zero.-->
      <Fix_K1>0</Fix_K1>
      <!-- If true (non-zero) distortion coefficient k2 will be equals to zero.-->
      <Fix_K2>0</Fix_K2>
      <!-- If true (non-zero) distortion coefficient k3 will be equals to zero.-->
      <Fix_K3>0</Fix_K3>
      <!-- If true (non-zero) distortion coefficient k4 will be equals to zero.-->
      <Fix_K4>1</Fix_K4>
      <!-- If true (non-zero) distortion coefficient k5 will be equals to zero.-->
      <Fix_K5>1</Fix_K5>
    </Settings>
    </opencv_storage>
    View Code

    out_camera_data.yml (主程序输出保存的相机基本参数,以方便下次相机的使用)

    %YAML:1.0
    calibration_Time: "08/19/11 20:44:38"
    nrOfFrames: 8
    image_Width: 640
    image_Height: 480
    board_Width: 9
    board_Height: 6
    square_Size: 50.
    FixAspectRatio: 1.
    # flags:  +fix_aspectRatio +fix_principal_point +zero_tangent_dist
    flagValue: 14
    Camera_Matrix: !!opencv-matrix
       rows: 3
       cols: 3
       dt: d
       data: [ 6.5746697810243404e+002, 0., 3.1950000000000000e+002, 0.,
           6.5746697810243404e+002, 2.3950000000000000e+002, 0., 0., 1. ]
    Distortion_Coefficients: !!opencv-matrix
       rows: 5
       cols: 1
       dt: d
       data: [ -4.1802327018241026e-001, 5.0715243805833121e-001, 0., 0.,
           -5.7843596847939704e-001 ]
    Avg_Reprojection_Error: 3.8441346462381665e-001
    Per_View_Reprojection_Errors: !!opencv-matrix
       rows: 8
       cols: 1
       dt: f
       data: [ 5.04357755e-001, 4.85754758e-001, 3.99563968e-001,
           4.13829178e-001, 3.53570908e-001, 3.21116358e-001,
           2.74473161e-001, 2.39761785e-001 ]
    # a set of 6-tuples (rotation vector + translation vector) for each view
    Extrinsic_Parameters: !!opencv-matrix
       rows: 8
       cols: 6
       dt: d
       data: [ -7.8704123655486097e-002, -1.5922384772614945e-001,
           3.1166227207451498e+000, 2.4224388101960471e+002,
           1.1795590397660339e+002, 6.2576484126093249e+002,
           -1.4117480285164308e-001, -1.7917415443804836e-002,
           3.1333182268743949e+000, 2.5943034781849354e+002,
           1.4039780562976958e+002, 6.3848706527260981e+002,
           7.2230525186138789e-002, -7.5445981266787754e-002,
           1.5712860749221762e+000, 1.7426560451795339e+002,
           -1.9309240362258871e+002, 7.0891416556762647e+002,
           2.0367310600105853e-002, 6.8565520026996951e-002,
           -5.4313033031644169e-004, -2.0146314940404827e+002,
           -1.3305643514116997e+002, 7.4933554744027231e+002,
           -3.4468530027734055e-002, 2.1921265175331925e-002,
           -1.5731053528054522e+000, -1.1155718744299284e+002,
           2.0307615364261443e+002, 8.4915903914333899e+002,
           3.7425562109513817e-002, 7.4883169379022230e-002,
           -3.6031632305130512e-002, -2.0094505419395196e+002,
           -1.1627359108310560e+002, 9.2021583518760133e+002,
           6.8105689976949157e-002, 6.4426739692440949e-002,
           -7.0967130057087435e-002, -1.9233852871740035e+002,
           -1.0334652096641923e+002, 1.0755293563503658e+003,
           -5.8017546499862287e-002, -1.6909812666033443e-003,
           -1.5876137659782963e+000, -1.0242234847115104e+002,
           2.2583088401423066e+002, 1.1125972190244058e+003 ]
    Image_points: !!opencv-matrix
       rows: 8
       cols: 54
       dt: "2f"
       data: [ 5.58494690e+002, 3.55650085e+002, 5.13314697e+002,
           3.59107666e+002, 4.65728333e+002, 3.62133911e+002,
           4.15701111e+002, 3.65026459e+002, 3.64399353e+002,
           3.67339203e+002, 3.12101196e+002, 3.69211914e+002,
           2.59208405e+002, 3.70413513e+002, 2.07456192e+002,
           3.71175995e+002, 1.56619507e+002, 3.72176544e+002,
           5.60868713e+002, 3.08104828e+002, 5.15191772e+002,
           3.10485626e+002, 4.67032959e+002, 3.12660004e+002,
           4.16112152e+002, 3.14887177e+002, 3.64010712e+002,
           3.16825775e+002, 3.10712372e+002, 3.18640808e+002,
           2.56853943e+002, 3.20017365e+002, 2.04168182e+002,
           3.20908417e+002, 1.52469528e+002, 3.22105377e+002,
           5.62328369e+002, 2.58646881e+002, 5.16396301e+002,
           2.59919281e+002, 4.67907654e+002, 2.61257874e+002,
           4.16463440e+002, 2.62675537e+002, 3.63546570e+002,
           2.64064117e+002, 3.09528137e+002, 2.65489990e+002,
           2.54765533e+002, 2.66862030e+002, 2.01299225e+002,
           2.67997345e+002, 1.48913437e+002, 2.69627167e+002,
           5.63098022e+002, 2.08423523e+002, 5.16782654e+002,
           2.08424667e+002, 4.68059296e+002, 2.08661697e+002,
           4.16216431e+002, 2.09268982e+002, 3.62888763e+002,
           2.10013397e+002, 3.08458557e+002, 2.11074738e+002,
           2.53267990e+002, 2.12496582e+002, 1.99121384e+002,
           2.14005814e+002, 1.46551376e+002, 2.15851318e+002,
           5.62997437e+002, 1.57966492e+002, 5.16406494e+002,
           1.56580688e+002, 4.67334900e+002, 1.55756500e+002,
           4.15378235e+002, 1.55492874e+002, 3.62096710e+002,
           1.55498734e+002, 3.07522827e+002, 1.56133240e+002,
           2.52235214e+002, 1.57516571e+002, 1.97876328e+002,
           1.59318787e+002, 1.45078247e+002, 1.61638428e+002,
           5.62097168e+002, 1.07469536e+002, 5.15766846e+002,
           1.04902527e+002, 4.66562866e+002, 1.03045807e+002,
           4.14651459e+002, 1.01924713e+002, 3.61240662e+002,
           1.01357826e+002, 3.06746613e+002, 1.01582802e+002,
           2.51568024e+002, 1.02920105e+002, 1.97343307e+002,
           1.04941299e+002, 1.44756821e+002, 1.07737488e+002,
           5.68062500e+002, 3.73591125e+002, 5.25272644e+002,
           3.77019318e+002, 4.79870941e+002, 3.80086578e+002,
           4.31823730e+002, 3.83036652e+002, 3.81995758e+002,
           3.85271759e+002, 3.30728729e+002, 3.86998779e+002,
           2.78071167e+002, 3.88151031e+002, 2.26231567e+002,
           3.88669586e+002, 1.74855331e+002, 3.89197998e+002,
           5.69792542e+002, 3.27097382e+002, 5.26866028e+002,
           3.29362366e+002, 4.81278229e+002, 3.31532928e+002,
           4.32783203e+002, 3.33552185e+002, 3.82408234e+002,
           3.35186554e+002, 3.30427399e+002, 3.36404053e+002,
           2.77138519e+002, 3.37450958e+002, 2.24525131e+002,
           3.37957092e+002, 1.72285507e+002, 3.38503540e+002,
           5.70942749e+002, 2.79243713e+002, 5.27789307e+002,
           2.80073486e+002, 4.82146576e+002, 2.81226410e+002,
           4.33247375e+002, 2.82237427e+002, 3.82503662e+002,
           2.83062286e+002, 3.30138885e+002, 2.83794434e+002,
           2.76433228e+002, 2.84549286e+002, 2.23158783e+002,
           2.84981049e+002, 1.70520218e+002, 2.85720886e+002,
           5.71001953e+002, 2.30928329e+002, 5.27846863e+002,
           2.30519928e+002, 4.82114563e+002, 2.30268906e+002,
           4.33114563e+002, 2.30243515e+002, 3.82384857e+002,
           2.30311340e+002, 3.29870392e+002, 2.30454620e+002,
           2.76012634e+002, 2.30882156e+002, 2.22529434e+002,
           2.31355362e+002, 1.69742065e+002, 2.32063004e+002,
           5.70199036e+002, 1.82609772e+002, 5.27030884e+002,
           1.80973267e+002, 4.81193573e+002, 1.79573792e+002,
           4.32409821e+002, 1.78475616e+002, 3.81855530e+002,
           1.77680283e+002, 3.29641937e+002, 1.77092087e+002,
           2.75895782e+002, 1.77155502e+002, 2.22438889e+002,
           1.77605667e+002, 1.69884583e+002, 1.78365585e+002,
           5.69026245e+002, 1.34654831e+002, 5.26171570e+002,
           1.31798691e+002, 4.80653503e+002, 1.29171509e+002,
           4.31869904e+002, 1.27280067e+002, 3.81419739e+002,
           1.25591202e+002, 3.29466644e+002, 1.24407089e+002,
           2.76225342e+002, 1.24174736e+002, 2.23024109e+002,
           1.24463333e+002, 1.70838898e+002, 1.25398903e+002,
           4.73812897e+002, 6.94673386e+001, 4.74245453e+002,
           1.12387466e+002, 4.74243347e+002, 1.56034164e+002,
           4.73834778e+002, 2.00523651e+002, 4.72891602e+002,
           2.44457306e+002, 4.71412811e+002, 2.87981171e+002,
           4.69708252e+002, 3.30783173e+002, 4.67558228e+002,
           3.71818420e+002, 4.65495667e+002, 4.11996979e+002,
           4.31027649e+002, 6.75546722e+001, 4.31269440e+002,
           1.10960022e+002, 4.31185486e+002, 1.55113556e+002,
           4.30830139e+002, 2.00061066e+002, 4.30168427e+002,
           2.44456863e+002, 4.29107544e+002, 2.88479645e+002,
           4.27829071e+002, 3.31813507e+002, 4.26131653e+002,
           3.73071228e+002, 4.24718811e+002, 4.13476563e+002,
           3.86868805e+002, 6.61982269e+001, 3.86895416e+002,
           1.09904411e+002, 3.86690216e+002, 1.54396423e+002,
           3.86368591e+002, 1.99800369e+002, 3.85792206e+002,
           2.44538574e+002, 3.85117279e+002, 2.88826447e+002,
           3.84405273e+002, 3.32408020e+002, 3.83303772e+002,
           3.74074097e+002, 3.82477448e+002, 4.14638977e+002,
           3.41941437e+002, 6.54462357e+001, 3.41628204e+002,
           1.09383698e+002, 3.41402344e+002, 1.54105545e+002,
           3.41168854e+002, 1.99655045e+002, 3.40816681e+002,
           2.44469910e+002, 3.40516937e+002, 2.88975800e+002,
           3.40365662e+002, 3.32670990e+002, 3.39935211e+002,
           3.74465759e+002, 3.39847626e+002, 4.14742279e+002,
           2.96694000e+002, 6.56859589e+001, 2.96075226e+002,
           1.09505333e+002, 2.95704895e+002, 1.54202652e+002,
           2.95653107e+002, 1.99734131e+002, 2.95589661e+002,
           2.44549530e+002, 2.95629547e+002, 2.88889496e+002,
           2.96138733e+002, 3.32610931e+002, 2.96520905e+002,
           3.74608551e+002, 2.96987091e+002, 4.14774902e+002,
           2.51414978e+002, 6.65755463e+001, 2.50681854e+002,
           1.10189331e+002, 2.50183380e+002, 1.54658005e+002,
           2.50331161e+002, 2.00073761e+002, 2.50590790e+002,
           2.44719513e+002, 2.51083817e+002, 2.88868286e+002,
           2.52134262e+002, 3.32266937e+002, 2.53097809e+002,
           3.74022491e+002, 2.54404007e+002, 4.14018066e+002,
           1.49524078e+002, 1.27699501e+002, 1.89511658e+002,
           1.25816605e+002, 2.31050888e+002, 1.24260918e+002,
           2.74076721e+002, 1.23023209e+002, 3.17643005e+002,
           1.22288109e+002, 3.61785889e+002, 1.22105164e+002,
           4.06142670e+002, 1.22401566e+002, 4.49623962e+002,
           1.23246025e+002, 4.92677216e+002, 1.24087708e+002,
           1.48706085e+002, 1.69077423e+002, 1.88827805e+002,
           1.67750443e+002, 2.30439865e+002, 1.66769333e+002,
           2.73830933e+002, 1.65871170e+002, 3.17596741e+002,
           1.65410919e+002, 3.61983459e+002, 1.65327866e+002,
           4.06748322e+002, 1.65463974e+002, 4.50450226e+002,
           1.66126526e+002, 4.93614655e+002, 1.66970413e+002,
           1.48312607e+002, 2.11499451e+002, 1.88574097e+002,
           2.10860214e+002, 2.30130676e+002, 2.10261612e+002,
           2.73557709e+002, 2.09837143e+002, 3.17542572e+002,
           2.09633057e+002, 3.62091248e+002, 2.09732620e+002,
           4.06934570e+002, 2.09926758e+002, 4.50914612e+002,
           2.10320221e+002, 4.94044495e+002, 2.10900925e+002,
           1.48613831e+002, 2.53997177e+002, 1.88797791e+002,
           2.53912842e+002, 2.30240204e+002, 2.53975067e+002,
           2.73746704e+002, 2.54010208e+002, 3.17718262e+002,
           2.54106003e+002, 3.62188965e+002, 2.54205475e+002,
           4.06908783e+002, 2.54317505e+002, 4.50824951e+002,
           2.54539490e+002, 4.93825714e+002, 2.54753876e+002,
           1.49541687e+002, 2.96404175e+002, 1.89357727e+002,
           2.97117523e+002, 2.30807007e+002, 2.97805603e+002,
           2.74325470e+002, 2.97966522e+002, 3.18042206e+002,
           2.98304535e+002, 3.62105774e+002, 2.98552643e+002,
           4.06672272e+002, 2.98572418e+002, 4.50363068e+002,
           2.98569550e+002, 4.93109894e+002, 2.98516205e+002,
           1.50883698e+002, 3.38493195e+002, 1.90633621e+002,
           3.39862610e+002, 2.31920990e+002, 3.40869415e+002,
           2.74971252e+002, 3.41453766e+002, 3.18235229e+002,
           3.41952637e+002, 3.62063477e+002, 3.42314026e+002,
           4.06098938e+002, 3.42221802e+002, 4.49477386e+002,
           3.42063812e+002, 4.91864716e+002, 3.41727600e+002,
           2.36129852e+002, 3.92798004e+002, 2.34999939e+002,
           3.56118683e+002, 2.34376099e+002, 3.18607025e+002,
           2.33822159e+002, 2.80400696e+002, 2.33565445e+002,
           2.42213104e+002, 2.33583069e+002, 2.03937286e+002,
           2.34028824e+002, 1.65756607e+002, 2.34613373e+002,
           1.28586639e+002, 2.35190308e+002, 9.18279037e+001,
           2.73031616e+002, 3.93267242e+002, 2.72295166e+002,
           3.56342743e+002, 2.71799347e+002, 3.18847412e+002,
           2.71418854e+002, 2.80287872e+002, 2.71161469e+002,
           2.41881134e+002, 2.71248962e+002, 2.03348145e+002,
           2.71379303e+002, 1.64895874e+002, 2.71946045e+002,
           1.27450935e+002, 2.72322418e+002, 9.06900787e+001,
           3.10670715e+002, 3.93568848e+002, 3.10389160e+002,
           3.56545959e+002, 3.10084625e+002, 3.18814514e+002,
           3.09801544e+002, 2.80242737e+002, 3.09678711e+002,
           2.41574814e+002, 3.09779663e+002, 2.02989838e+002,
           3.09842712e+002, 1.64338043e+002, 3.10076782e+002,
           1.26870911e+002, 3.10243286e+002, 8.98413315e+001,
           3.48618134e+002, 3.93563202e+002, 3.48617065e+002,
           3.56472382e+002, 3.48608795e+002, 3.18855621e+002,
           3.48544556e+002, 2.80011017e+002, 3.48556396e+002,
           2.41388168e+002, 3.48585388e+002, 2.02692429e+002,
           3.48435089e+002, 1.64099731e+002, 3.48442902e+002,
           1.26549957e+002, 3.48338043e+002, 8.98002014e+001,
           3.86625610e+002, 3.93188599e+002, 3.87047729e+002,
           3.56377594e+002, 3.87306274e+002, 3.18714752e+002,
           3.87337799e+002, 2.79868896e+002, 3.87402740e+002,
           2.41228760e+002, 3.87295166e+002, 2.02695313e+002,
           3.87030273e+002, 1.64203415e+002, 3.86741211e+002,
           1.26606262e+002, 3.86337311e+002, 8.99655075e+001,
           4.24534088e+002, 3.92702545e+002, 4.25310822e+002,
           3.55900452e+002, 4.25869019e+002, 3.18160614e+002,
           4.25909790e+002, 2.79615753e+002, 4.25977295e+002,
           2.41165100e+002, 4.25826477e+002, 2.02876389e+002,
           4.25331665e+002, 1.64527618e+002, 4.24775787e+002,
           1.27097328e+002, 4.23985138e+002, 9.08176651e+001,
           1.79142670e+002, 1.58573654e+002, 2.12791580e+002,
           1.56291031e+002, 2.47140106e+002, 1.54265656e+002,
           2.82607300e+002, 1.52373688e+002, 3.18175507e+002,
           1.50692184e+002, 3.54185852e+002, 1.49404175e+002,
           3.90455200e+002, 1.48229370e+002, 4.26106689e+002,
           1.47507843e+002, 4.61576141e+002, 1.46712479e+002,
           1.80388336e+002, 1.93027603e+002, 2.14026459e+002,
           1.91128204e+002, 2.48376541e+002, 1.89414978e+002,
           2.83795807e+002, 1.87720856e+002, 3.19472473e+002,
           1.86192383e+002, 3.55483826e+002, 1.84929199e+002,
           3.91970764e+002, 1.83747040e+002, 4.27654572e+002,
           1.82931534e+002, 4.63295227e+002, 1.81977234e+002,
           1.81914261e+002, 2.27955460e+002, 2.15291260e+002,
           2.26512482e+002, 2.49628265e+002, 2.25067520e+002,
           2.85066406e+002, 2.23593185e+002, 3.20846680e+002,
           2.22337708e+002, 3.56862885e+002, 2.21191040e+002,
           3.93279907e+002, 2.19905640e+002, 4.29202271e+002,
           2.18870361e+002, 4.64728424e+002, 2.17972977e+002,
           1.83496948e+002, 2.62963226e+002, 2.16930527e+002,
           2.61755219e+002, 2.51115829e+002, 2.60777222e+002,
           2.86553406e+002, 2.59500336e+002, 3.22299896e+002,
           2.58380737e+002, 3.58307648e+002, 2.57236694e+002,
           3.94551819e+002, 2.56009125e+002, 4.30358948e+002,
           2.54925797e+002, 4.65684998e+002, 2.54021484e+002,
           1.85461685e+002, 2.97687378e+002, 2.18712234e+002,
           2.96999207e+002, 2.52770218e+002, 2.96270752e+002,
           2.88213776e+002, 2.95168213e+002, 3.23698334e+002,
           2.94233032e+002, 3.59477722e+002, 2.93170715e+002,
           3.95647766e+002, 2.91897400e+002, 4.31309845e+002,
           2.90856995e+002, 4.66494110e+002, 2.89726410e+002,
           1.87661331e+002, 3.32186188e+002, 2.20767746e+002,
           3.31906250e+002, 2.54839096e+002, 3.31398651e+002,
           2.89963745e+002, 3.30524139e+002, 3.25207642e+002,
           3.29771820e+002, 3.60686035e+002, 3.28762695e+002,
           3.96576447e+002, 3.27542206e+002, 4.31994415e+002,
           3.26294189e+002, 4.66894653e+002, 3.24949921e+002,
           2.03543015e+002, 1.77473557e+002, 2.32777847e+002,
           1.74712509e+002, 2.62628723e+002, 1.72331970e+002,
           2.93045898e+002, 1.69686768e+002, 3.23527618e+002,
           1.67496246e+002, 3.54206787e+002, 1.65446075e+002,
           3.85180176e+002, 1.63360580e+002, 4.15484253e+002,
           1.61536423e+002, 4.45720947e+002, 1.59896164e+002,
           2.05864395e+002, 2.07228104e+002, 2.35242096e+002,
           2.04699326e+002, 2.64853973e+002, 2.02407455e+002,
           2.95353882e+002, 1.99972321e+002, 3.25811890e+002,
           1.97671921e+002, 3.56471252e+002, 1.95763168e+002,
           3.87280548e+002, 1.93597977e+002, 4.17615814e+002,
           1.91867371e+002, 4.48018677e+002, 1.90067413e+002,
           2.08421249e+002, 2.37166977e+002, 2.37513824e+002,
           2.34982773e+002, 2.67261261e+002, 2.32802841e+002,
           2.97555817e+002, 2.30466080e+002, 3.28118103e+002,
           2.28462463e+002, 3.58699707e+002, 2.26417038e+002,
           3.89468842e+002, 2.24356827e+002, 4.19895996e+002,
           2.22421921e+002, 4.50077850e+002, 2.20683517e+002,
           2.11095444e+002, 2.66940186e+002, 2.40241348e+002,
           2.64970093e+002, 2.69563019e+002, 2.63153290e+002,
           2.99863464e+002, 2.60983551e+002, 3.30282440e+002,
           2.58911560e+002, 3.60724792e+002, 2.56935730e+002,
           3.91487915e+002, 2.54799423e+002, 4.21789093e+002,
           2.52929688e+002, 4.51818481e+002, 2.51059357e+002,
           2.13829117e+002, 2.96591217e+002, 2.42742859e+002,
           2.94884583e+002, 2.72209076e+002, 2.93215668e+002,
           3.02402985e+002, 2.91230591e+002, 3.32536072e+002,
           2.89165192e+002, 3.62860901e+002, 2.87413605e+002,
           3.93481842e+002, 2.85199615e+002, 4.23728851e+002,
           2.83277496e+002, 4.53453094e+002, 2.81229309e+002,
           2.16799316e+002, 3.25975220e+002, 2.45605515e+002,
           3.24619904e+002, 2.74777344e+002, 3.22958679e+002,
           3.04762817e+002, 3.21008057e+002, 3.34797150e+002,
           3.19291443e+002, 3.65005798e+002, 3.17295044e+002,
           3.95311981e+002, 3.15296021e+002, 4.25312592e+002,
           3.13086945e+002, 4.54931152e+002, 3.11027130e+002,
           2.60550232e+002, 3.70739563e+002, 2.59674011e+002,
           3.42115936e+002, 2.58910492e+002, 3.13278015e+002,
           2.58195618e+002, 2.84013580e+002, 2.57727173e+002,
           2.55017166e+002, 2.57326263e+002, 2.25760986e+002,
           2.57096619e+002, 1.96577972e+002, 2.57031860e+002,
           1.68026199e+002, 2.56873383e+002, 1.39550308e+002,
           2.89019318e+002, 3.70481354e+002, 2.88355560e+002,
           3.41833252e+002, 2.87601471e+002, 3.12872925e+002,
           2.87057190e+002, 2.83485535e+002, 2.86599762e+002,
           2.54255096e+002, 2.86174438e+002, 2.25023285e+002,
           2.85775940e+002, 1.95715347e+002, 2.85577087e+002,
           1.66989502e+002, 2.85395477e+002, 1.38597382e+002,
           3.18072754e+002, 3.70118317e+002, 3.17432709e+002,
           3.41398743e+002, 3.16917267e+002, 3.12476044e+002,
           3.16284363e+002, 2.83001587e+002, 3.15799072e+002,
           2.53725845e+002, 3.15411957e+002, 2.24337708e+002,
           3.15070374e+002, 1.95034119e+002, 3.14736847e+002,
           1.66195313e+002, 3.14439789e+002, 1.37797058e+002,
           3.47083588e+002, 3.69678101e+002, 3.46717987e+002,
           3.40949524e+002, 3.46185303e+002, 3.12009857e+002,
           3.45728088e+002, 2.82454071e+002, 3.45226624e+002,
           2.53109863e+002, 3.44883606e+002, 2.23839539e+002,
           3.44373535e+002, 1.94399933e+002, 3.43879852e+002,
           1.65690643e+002, 3.43438629e+002, 1.37252930e+002,
           3.76341522e+002, 3.68972321e+002, 3.76086884e+002,
           3.40412842e+002, 3.75708893e+002, 3.11398376e+002,
           3.75143494e+002, 2.81901520e+002, 3.74762970e+002,
           2.52577988e+002, 3.74223969e+002, 2.23348221e+002,
           3.73600891e+002, 1.93979538e+002, 3.72983917e+002,
           1.65201294e+002, 3.72517273e+002, 1.36871033e+002,
           4.05512115e+002, 3.68243225e+002, 4.05366333e+002,
           3.39678650e+002, 4.05090027e+002, 3.10679108e+002,
           4.04612366e+002, 2.81203522e+002, 4.04152649e+002,
           2.52051605e+002, 4.03539703e+002, 2.22930420e+002,
           4.02903351e+002, 1.93625381e+002, 4.02272827e+002,
           1.65004440e+002, 4.01353333e+002, 1.36796814e+002 ]
    View Code

    (注:我这里使用的是最新版本Opencv4.x,其他版本的标定文件不一定兼容,例如我使用Opencv3中的camera_calibration.cpp在Opencv4.x环境下就无法编译通过)

    编译方式采用Cmake,CMakeLists.txt脚本如下:

    1 cmake_minimum_required(VERSION 2.8)
    2 
    3 project(main_calibration)
    4 
    5 find_package(OpenCV REQUIRED)
    6 include_directories(${OpenCV_INCLUDE_DIRS})
    7 
    8 add_executable(main_calibration camera_calibration.cpp)
    9 target_link_libraries(main_calibration ${OpenCV_LIBS})

    编译流程如下:

    Step1:本地主程序camera_calibration.cpp文件目录下新建编译临时文件夹build.(CMakeLists.txt和主程序文件在同一目录下).

    Step2:切换目录到build文件夹下,使用cmake命令生成对应的Makefile以及预编译临时文件.

    Step3:使用make命令进行编译,编译完成后自动在build文件夹下生成可执行文件main_calibration.

    mkdir build
    cd build
    cmake ..
    make

    接下来修改可执行文件main_calibration可执行文件的参数文件in_VID5.xml

    Line5: <BoardSize_Width>8</BoardSize_Width> # 设置Chess标定板宽度方向角点数.(注意是inner方块的角点数)
    Line6: <BoardSize_Height>6</BoardSize_Height> # 设置Chess标定板高度方向角点数.(注意inner角点表示出了最外侧一圈方格的部分)
    Line9: <Square_Size>40</Square_Size> # 实际物理棋盘上方块的边长(Units:mm)
    Line12: <Calibration_Pattern>"CHESSBARD"</Calibration_Pattern> # 一般这里都设置为棋盘,如果你的是其他标定板请使用其他参数.
    Line19:<Input>"absolute_path/VID5.xml"</Input> # 这里如果设置为1表示使用Camera来现场采集图片进行标定,一般来说可以设置VID5.xml文件路径,程序将会通过VID5.xml文件中标定图片路径读取图片,这里需要配置好VID5.xml文件.
    Line24:<Input_Delay>100</Input_Delay> # 如果使用Camera来实时采集标定图像,则这个参数用来设定两次采集动作之间的时间间隔,如果不采用Camera则不用设置.
    Line27:<Calibrate_NrOfFrameToUse><Calibrate_NrOfFrameToUse> # 设置用来标定的有效图像数量,25表示使用能够找到角点并满足角点要求的25张标定图进行相机标定.
    Line37: <Write_outputFileName>"out_camera_data.yml"</Write_outputFileName> # 设置标定完成后参数保存的路径以及文件,注意文件后缀名为.yml.
    Line47: <Calibrate_UseFisheyeModel>1</Calibrate_UseFishModel> # 如果需要标定的为鱼眼镜头,则需要设置为1.

    根据in_VID5.xml中的设置,如果选用已经拍摄好的照片则需要修改VID5.xml文件内容,添加标定图像的绝对路径:

    如图上所示,一般需要采集足够多的图像,以保证能够找到足够用来标定Camera的图像,如果不满足要求则会出现如下错误(请调整光照等条件重新采集图像):

    完成基本参数文件设置之后开始运行:

    ./main_calibration ../in_VID5.xml

    运行过程截图如下:

     如上左图表示图像角点提取的情况,右图表示矫正之后的结果。

    三、使用标定结果矫正畸变

    参考程序如下,只采用了径向畸变矫正(注:完成了彩色图像畸变校正以及单通道灰度图像矫正):

    在插值过程中使用了最近邻差值算法,如使用其他算法请自行封装调用。

     1 #include <iostream>
     2 #include <string.h>
     3 #include <opencv2/opencv.hpp>
     4 
     5 using namespace std;
     6 using namespace cv;
     7 
     8 #define SHOW 0
     9 int main(void)
    10 {
    11   string img_path = "../CSICamera0-31.jpg";
    12   string res_path = "../undistort.jpg";
    13   cout << "Begin to Calibrate the image file:" << img_path << endl;
    14   double k1=-0.3403,k2=0.1520125;
    15   double fx=784.59,fy=784.59,cx=640,cy=480;
    16 
    17 #if SHOW
    18   namedWindow("OriImage", WINDOW_AUTOSIZE);
    19   namedWindow("ResImage", WINDOW_AUTOSIZE);
    20 #endif
    21 
    22   Mat Ori = imread(img_path);
    23 #if SHOW
    24   imshow("OriImage",Ori);
    25 #endif
    26 
    27   int rows = Ori.rows, cols = Ori.cols,row,col;
    28   double row_undistort,col_undistort,x1,x2,y1,y2,r;
    29   Mat gry_undistort = Mat(rows,cols,CV_8UC1);
    30   Mat Gry = Mat(rows,cols,CV_8UC1);
    31   Mat img_undistort = Mat(rows,cols,CV_8UC3);
    32 
    33   cvtColor(Ori,Gry,COLOR_BGR2GRAY);
    34 
    35   for(row=0;row<rows;row++){
    36     for(col=0;col<cols;col++){
    37       x1 = (col-cx)/fx; // calc center x
    38       y1 = (row-cy)/fy; // calc center y
    39       r = pow(x1,2) + pow(y1,2); // calc center distance
    40       x2 = x1*(1+k1*r+k2*pow(r,2)); // undistort img pos-col
    41       y2 = y1*(1+k1*r+k2*pow(r,2)); // undistort img pos-row
    42       row_undistort = fy*y2 + cy;
    43       col_undistort = fx*x2 + cx;
    44 
    45       if(row_undistort >=0 && col_undistort >= 0 && row_undistort < rows && col_undistort < cols){
    46         gry_undistort.at<uchar>(row,col) = Gry.at<uchar>((int)row_undistort,(int)col_undistort);
    47         img_undistort.at<Vec3b>(row,col)[0] = Ori.at<Vec3b>((int)row_undistort,(int)col_undistort)[0];
    48         img_undistort.at<Vec3b>(row,col)[1] = Ori.at<Vec3b>((int)row_undistort,(int)col_undistort)[1];
    49         img_undistort.at<Vec3b>(row,col)[2] = Ori.at<Vec3b>((int)row_undistort,(int)col_undistort)[2];
    50       }else{
    51         gry_undistort.at<uchar>(row,col) = 0;
    52         img_undistort.at<Vec3b>(row,col)[0] = 0;
    53         img_undistort.at<Vec3b>(row,col)[1] = 0;
    54         img_undistort.at<Vec3b>(row,col)[2] = 0;
    55       }
    56     }
    57   }
    58 
    59 #if SHOW
    60   imshow("ResImage",img_undistort);
    61   while(1){
    62     int keycode = waitKey(30) & 0xff ;
    63     if (keycode == 27) break ;
    64   }
    65   destroyAllWindows();
    66 #else
    67   imwrite(res_path,img_undistort);
    68 #endif
    69 
    70   return 0;
    71 }

    实际处理结果:

    使用cuda加速的畸变矫正算法:传送门

    四、参考资料

    畸变矫正Opencv代码打包Baidu-Pan下载地址:https://pan.baidu.com/s/1icrwvNws2N1j7b7bjGxPNA  提取码:6koe 

    Matlab标定工具箱使用官方参考教程:http://www.vision.caltech.edu/bouguetj/calib_doc/htmls/example.html

    图像矫正及畸变参数使用:https://blog.csdn.net/weixin_38009585/article/details/82356022

  • 相关阅读:
    OK335xS-Android mkmmc-android-ubifs.sh hacking
    OK335xS-Android pack-ubi-256M.sh hacking
    OK335xS Ubuntu 12.04.1 版本 Android 开发环境搭建
    Qt Quick Hello World hacking
    Qt QML referenceexamples attached Demo hacking
    QT 5.4.1 for Android Ubuntu QtWebView Demo
    I.MX6 working note for high efficiency
    QT 5.4.1 for Android Windows环境搭建
    mkbootimg hacking
    Generate And Play A Tone In Android hacking
  • 原文地址:https://www.cnblogs.com/uestc-mm/p/12703897.html
Copyright © 2011-2022 走看看