在你看到这篇博文的时候,希望你能先看下我的上一篇博文,对相关的知识点有所了解后再看这篇博文
下面的几个函数就是实现相机校正的关键
addChessboardPoints()
函数 - 用于读入一系列的棋盘图像并检测角点;calibrate()
函数 - 用于进行相机校正,得到相机的参数矩阵和畸变系数;remap()
函数 - 用于根据相机校正结果修复图像的畸变;//主要靠这个函数实现校正initUndistortRectifyMapaddPoints()
函数 -addChessboardPoints()
在检测完角点后会调用这个函数。也可自己手动调用这个函数添加已知的角点位置和对应的空间坐标点。
main.c 1 #include <QCoreApplication>
2 #include <iostream>
3 #include <iomanip>
4 #include <vector>
5 #include <opencv2/core/core.hpp>
6 #include <opencv2/imgproc/imgproc.hpp>
7 #include <opencv2/highgui/highgui.hpp>
8 #include <opencv2/features2d/features2d.hpp>
9
10 #include "CameraCalibrator.h"
11
12 int main()
13 {
14
15 cv::namedWindow("Image");
16 cv::Mat image;
17 std::vector<std::string> filelist;
18
19 // generate list of chessboard image filename
20 for (int i=1; i<=20; i++) {
21
22 std::stringstream str;
23 str << "/home/bi/pic/chessboards/chessboard" << std::setw(2) << std::setfill('0') << i << ".jpg";
24 std::cout << str.str() << std::endl;
25
26 filelist.push_back(str.str());
27 image= cv::imread(str.str(),0);//直接变为灰度图
28 //cvtColor(image,image,CV_BGR2GRAY);
29 cv::imshow("Image",image);
30
31 cv::waitKey(1000);
32 }
33
34 // Create calibrator object
35 CameraCalibrator cameraCalibrator;
36 // add the corners from the chessboard
37 cv::Size boardSize(6,4);
38 cameraCalibrator.addChessboardPoints(
39 filelist, // filenames of chessboard image
40 boardSize); // size of chessboard
41 // calibrate the camera
42 // cameraCalibrator.setCalibrationFlag(true,true);
43 cameraCalibrator.calibrate(image.size());
44
45 // Image Undistortion
46 image = cv::imread(filelist[6]);
47 cv::Mat uImage= cameraCalibrator.remap(image);
48
49 // display camera matrix
50 cv::Mat cameraMatrix= cameraCalibrator.getCameraMatrix();
51 std::cout << " Camera intrinsic: " << cameraMatrix.rows << "x" << cameraMatrix.cols << std::endl;
52 std::cout << cameraMatrix.at<double>(0,0) << " " << cameraMatrix.at<double>(0,1) << " " << cameraMatrix.at<double>(0,2) << std::endl;
53 std::cout << cameraMatrix.at<double>(1,0) << " " << cameraMatrix.at<double>(1,1) << " " << cameraMatrix.at<double>(1,2) << std::endl;
54 std::cout << cameraMatrix.at<double>(2,0) << " " << cameraMatrix.at<double>(2,1) << " " << cameraMatrix.at<double>(2,2) << std::endl;
55
56 imshow("Original Image", image);
57 imshow("Undistorted Image", uImage);
58
59 cv::waitKey();
60 return 0;
61 }
CameraCalibrator.h
addChessboardPoints()
函数 - 用于读入一系列的棋盘图像并检测角点;calibrate()
函数 - 用于进行相机校正,得到相机的参数矩阵和畸变系数;remap()
函数 - 用于根据相机校正结果修复图像的畸变;//主要靠这个函数实现校正initUndistortRectifyMapaddPoints()
函数 -addChessboardPoints()
在检测完角点后会调用这个函数。也可自己手动调用这个函数添加已知的角点位置和对应的空间坐标点。
1 #ifndef CAMERACALIBRATOR_H
2 #define CAMERACALIBRATOR_H
3
4 #include <vector>
5 #include <iostream>
6
7 #include <opencv2/core/core.hpp>
8 #include "opencv2/imgproc/imgproc.hpp"
9 #include "opencv2/calib3d/calib3d.hpp"
10 #include <opencv2/highgui/highgui.hpp>
11
12 class CameraCalibrator {
13
14 // input points
15 std::vector<std::vector<cv::Point3f>> objectPoints;
16 std::vector<std::vector<cv::Point2f>> imagePoints;
17 // output Matrices
18 cv::Mat cameraMatrix;
19 cv::Mat distCoeffs;
20 // flag to specify how calibration is done
21 int flag;
22 // used in image undistortion
23 cv::Mat map1,map2;
24 bool mustInitUndistort;
25
26 public:
27 CameraCalibrator() : flag(0), mustInitUndistort(true) {};
28
29 // Open the chessboard images and extract corner points
30 int addChessboardPoints(const std::vector<std::string>& filelist, cv::Size & boardSize);
31 // Add scene points and corresponding image points
32 void addPoints(const std::vector<cv::Point2f>& imageCorners, const std::vector<cv::Point3f>& objectCorners);
33 // Calibrate the camera
34 double calibrate(cv::Size &imageSize);
35 // Set the calibration flag
36 void setCalibrationFlag(bool radial8CoeffEnabled=false, bool tangentialParamEnabled=false);
37 // Remove distortion in an image (after calibration)
38 cv::Mat CameraCalibrator::remap(const cv::Mat &image);
39
40 // Getters
41 cv::Mat getCameraMatrix() { return cameraMatrix; }
42 cv::Mat getDistCoeffs() { return distCoeffs; }
43 };
44
45 #endif // CAMERACALIBRATOR_H
View Code
CameraCalibrator.cpp
1 #include "CameraCalibrator.h"
2
3 // Open chessboard images and extract corner points
4 int CameraCalibrator::addChessboardPoints(
5 const std::vector<std::string>& filelist,
6 cv::Size & boardSize) {
7
8 // the points on the chessboard
9 std::vector<cv::Point2f> imageCorners;
10 std::vector<cv::Point3f> objectCorners;
11
12 // 3D Scene Points:
13 // Initialize the chessboard corners
14 // in the chessboard reference frame
15 // The corners are at 3D location (X,Y,Z)= (i,j,0)
16 for (int i=0; i<boardSize.height; i++) {
17 for (int j=0; j<boardSize.width; j++) {
18
19 objectCorners.push_back(cv::Point3f(i, j, 0.0f));
20 }
21 }
22
23 // 2D Image points:
24 cv::Mat image; // to contain chessboard image
25 int successes = 0;
26 // for all viewpoints
27 for (int i=0; i<filelist.size(); i++) {
28
29 // Open the image
30 image = cv::imread(filelist[i],0);
31
32 // Get the chessboard corners
33 bool found = cv::findChessboardCorners(
34 image, boardSize, imageCorners);
35
36 // Get subpixel accuracy on the corners
37 cv::cornerSubPix(image, imageCorners,
38 cv::Size(5,5),
39 cv::Size(-1,-1),
40 cv::TermCriteria(cv::TermCriteria::MAX_ITER +
41 cv::TermCriteria::EPS,
42 30, // max number of iterations
43 0.1)); // min accuracy
44
45 // If we have a good board, add it to our data
46 if (imageCorners.size() == boardSize.area()) {
47
48 // Add image and scene points from one view
49 addPoints(imageCorners, objectCorners);
50 successes++;
51 }
52
53 //Draw the corners
54 cv::drawChessboardCorners(image, boardSize, imageCorners, found);
55 cv::imshow("Corners on Chessboard", image);
56 cv::waitKey(100);
57 }
58
59 return successes;
60 }
61
62 // Add scene points and corresponding image points
63 void CameraCalibrator::addPoints(const std::vector<cv::Point2f>& imageCorners, const std::vector<cv::Point3f>& objectCorners) {
64
65 // 2D image points from one view
66 imagePoints.push_back(imageCorners);
67 // corresponding 3D scene points
68 objectPoints.push_back(objectCorners);
69 }
70
71 // Calibrate the camera
72 // returns the re-projection error
73 double CameraCalibrator::calibrate(cv::Size &imageSize)
74 {
75 // undistorter must be reinitialized
76 mustInitUndistort= true;
77
78 //Output rotations and translations
79 std::vector<cv::Mat> rvecs, tvecs;
80
81 // start calibration
82 return
83 calibrateCamera(objectPoints, // the 3D points
84 imagePoints, // the image points
85 imageSize, // image size
86 cameraMatrix, // output camera matrix
87 distCoeffs, // output distortion matrix
88 rvecs, tvecs, // Rs, Ts
89 flag); // set options
90 // ,CV_CALIB_USE_INTRINSIC_GUESS);
91
92 }
93
94 // remove distortion in an image (after calibration)
95 cv::Mat CameraCalibrator::remap(const cv::Mat &image) {
96
97 cv::Mat undistorted;
98
99 if (mustInitUndistort) { // called once per calibration
100
101 cv::initUndistortRectifyMap(
102 cameraMatrix, // computed camera matrix
103 distCoeffs, // computed distortion matrix
104 cv::Mat(), // optional rectification (none)
105 cv::Mat(), // camera matrix to generate undistorted
106 cv::Size(640,480),
107 // image.size(), // size of undistorted
108 CV_32FC1, // type of output map
109 map1, map2); // the x and y mapping functions
110
111 mustInitUndistort= false;
112 }
113
114 // Apply mapping functions
115 cv::remap(image, undistorted, map1, map2,
116 cv::INTER_LINEAR); // interpolation type
117
118 return undistorted;
119 }
120
121
122 // Set the calibration options
123 // 8radialCoeffEnabled should be true if 8 radial coefficients are required (5 is default)
124 // tangentialParamEnabled should be true if tangeantial distortion is present
125 void CameraCalibrator::setCalibrationFlag(bool radial8CoeffEnabled, bool tangentialParamEnabled) {
126
127 // Set the flag used in cv::calibrateCamera()
128 flag = 0;
129 if (!tangentialParamEnabled) flag += CV_CALIB_ZERO_TANGENT_DIST;
130 if (radial8CoeffEnabled) flag += CV_CALIB_RATIONAL_MODEL;
131 }
View Code
findChessboardCorners
Finds the positions of internal corners of the chessboard.
C++: bool findChessboardCorners(InputArrayimage, SizepatternSize, OutputArray corners, int
flags=CV_CALIB_CB_ADAPTIVE_THRESH+CV_CALIB_CB_NORMALIZE_IMAGE
)//如果找到了棋盘内部的角点,会返回true这个时候正好对应绘制角点的patternWasFound
Parameters
image – Source chessboard view.It must be an 8-bit grayscale or color image.
patternSize– Number of inner corners per a chessboard row and column ( patternSize
= cvSize(points_per_row,points_per_colum) = cvSize(columns,rows) ).
corners – Output array of detected corners.
flags – Various operation flags that can be zero or a combination of the following values:
– CV_CALIB_CB_ADAPTIVE_THRESH Use adaptive thresholding to convert the image
to black and white, rather than a fixed threshold level (computed from the average
image brightness).
– CV_CALIB_CB_NORMALIZE_IMAGE Normalize the image gamma with
equalizeHist() before applying fixed or adaptive thresholding.
– CV_CALIB_CB_FILTER_QUADS Use additional criteria (like contour area, perimeter,
square-like shape) to filter out false quads extracted at the contour retrieval stage.
– CALIB_CB_FAST_CHECK Run a fast check on the image that looks for chessboard
corners, and shortcut the call if none is found. This can drastically speed up the call in
the degenerate condition when no chessboard is observed.
drawChessboardCorners
Renders the detected chessboard corners.
C++: voiddrawChessboardCorners(InputOutputArray image, Size patternSize, InputArray corners, bool
patternWasFound)
Python: cv2.drawChessboardCorners(image, patternSize, corners, patternWasFound)! None
C: void cvDrawChessboardCorners(CvArr image, CvSize patternSize, CvPoint2D32f corners, int
count, int patternWasFound)
Python: cv.DrawChessboardCorners(image, patternSize, corners, patternWasFound)! None
Parameters
image – Destination image.It must be an 8-bit color image.
patternSize – Number of inner corners per a chessboard row and column (patternSize =
cv::Size(points_per_row,points_per_column)).//注意这里表示的是棋盘的大小,别弄错了
corners– Array of detected corners, the output of findChessboardCorners.
patternWasFound – Parameter indicating whether the complete board was found or not.
The return value of findChessboardCorners() should be passed here.
The function draws individual chessboard corners detected either as red circles if the board was not found, or as
colored corners connected with lines if the board was found.
initUndistortRectifyMap
Computes the undistortion and rectification transformation map.
C++: voidinitUndistortRectifyMap(InputArray cameraMatrix, InputArray distCoeffs, InputArray R,
InputArray newCameraMatrix, Size size, int m1type, OutputArray
map1, OutputArray map2)
Parameters
cameraMatrix– Input camera matrix A =*
*
cameraMatrix //不用解释了吧 相机的内参矩阵
distCoeffs畸变矩阵 *– Input vector of distortion coefficients (k1; k2; p1; p2[; k3[; k4; k5; k6]]) of 4,*
**5, or 8 elements. If the vector is NULL/empty, the zero distortion coefficients are assumed.****
*R代表的是旋转矩阵*
*R– Optional rectification transformation in the object space (3x3 matrix). R1 or R2 , computed
by stereoRectify() can be passed here. If the matrix is empty, the identity transformation
is assumed. In cvInitUndistortMap R assumed to be an identity matrix.*
**
newCameraMatrix – New camera matrix A0 =
size – Undistorted image size.
m1type – Type of the first output map that can be CV_32FC1 or CV_16SC2 . See
convertMaps() for details.
map1 – The first output map.//即是 u****
*map2 – The second output map.//即是 v*
原文链接: https://www.cnblogs.com/haoxing990/p/4589461.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/217908
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!