接上一篇文章讲解的相机标定的基本概念,这篇文章主要阐述一下如何使用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...')
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:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-0.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-3.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-4.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-5.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-7.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-8.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-9.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-10.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-11.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-12.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-13.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-14.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-15.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-16.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-17.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-18.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-19.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-20.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-21.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-22.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-23.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-24.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-25.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-26.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-27.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-28.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-29.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-30.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-31.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-32.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-33.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-34.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-35.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-36.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-37.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-40.jpg',...
'C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-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')
运行刚刚生成保存的代码,得到如下的结果:
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步骤中保存下来的数据加载到Matlab当中:
load cameraParams
注意,此时必须添加cameraParams文件保存的文件空间到Matlab工作空间中来,加载完成之后就可以使用参数进行相机采集图片的矫正了:
I = imread('C:\Users\Administrator\Desktop\ImageData\CAM0\CSICamera0-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.\n"
259 "Usage: camera_calibration [configuration_file -- default ./default.xml]\n"
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]
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>
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>
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 ]
(注:我这里使用的是最新版本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
运行过程截图如下:
如上左图表示图像角点提取的情况,右图表示矫正之后的结果。
三、使用标定结果矫正畸变
###
四、参考资料
以上代码打包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
来源:oschina
链接:https://my.oschina.net/u/4325154/blog/3300676