Rev 3 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3 | PointedEar | 1 | /*------------------------------------------------------------------------------------------*\ |
2 | This file contains material supporting chapter 9 of the cookbook: |
||
5 | PointedEar | 3 | Computer Vision Programming using the OpenCV Library. |
4 | by Robert Laganiere, Packt Publishing, 2011. |
||
3 | PointedEar | 5 | |
5 | PointedEar | 6 | This program is free software; permission is hereby granted to use, copy, modify, |
7 | and distribute this source code, or portions thereof, for any purpose, without fee, |
||
8 | subject to the restriction that the copyright notice may not be removed |
||
9 | or altered from any source or altered source distribution. |
||
10 | The software is released on an as-is basis and without any warranties of any kind. |
||
11 | In particular, the software is not guaranteed to be fault-tolerant or free from failure. |
||
12 | The author disclaims all warranties with regard to this software, any use, |
||
13 | and any consequent failure, is purely the responsibility of the user. |
||
3 | PointedEar | 14 | |
5 | PointedEar | 15 | Copyright (C) 2010-2011 Robert Laganiere, www.laganiere.name |
16 | \*------------------------------------------------------------------------------------------*/ |
||
3 | PointedEar | 17 | |
18 | #include "CameraCalibrator.h" |
||
19 | |||
20 | // Open chessboard images and extract corner points |
||
5 | PointedEar | 21 | int |
22 | CameraCalibrator::addChessboardPoints(const std::vector<std::string>& filelist, |
||
23 | cv::Size & boardSize) |
||
24 | { |
||
3 | PointedEar | 25 | |
5 | PointedEar | 26 | // the points on the chessboard |
27 | std::vector<cv::Point2f> imageCorners; |
||
28 | std::vector<cv::Point3f> objectCorners; |
||
3 | PointedEar | 29 | |
5 | PointedEar | 30 | // 3D Scene Points: |
31 | // Initialize the chessboard corners |
||
32 | // in the chessboard reference frame |
||
33 | // The corners are at 3D location (X,Y,Z)= (i,j,0) |
||
34 | for (int i = 0; i < boardSize.height; i++) |
||
35 | { |
||
36 | for (int j = 0; j < boardSize.width; j++) |
||
37 | { |
||
3 | PointedEar | 38 | |
5 | PointedEar | 39 | objectCorners.push_back(cv::Point3f(i, j, 0.0f)); |
40 | } |
||
3 | PointedEar | 41 | } |
42 | |||
5 | PointedEar | 43 | // 2D Image points: |
44 | cv::Mat image; // to contain chessboard image |
||
45 | int successes = 0; |
||
46 | // for all viewpoints |
||
47 | for (unsigned int i = 0; i < filelist.size(); i++) |
||
48 | { |
||
3 | PointedEar | 49 | |
5 | PointedEar | 50 | // Open the image |
51 | image = cv::imread(filelist[i], 0); |
||
3 | PointedEar | 52 | |
5 | PointedEar | 53 | // Get the chessboard corners |
54 | bool found = cv::findChessboardCorners(image, boardSize, imageCorners); |
||
3 | PointedEar | 55 | |
5 | PointedEar | 56 | // Get subpixel accuracy on the corners |
57 | cv::cornerSubPix(image, imageCorners, cv::Size(5, 5), cv::Size(-1, -1), |
||
58 | cv::TermCriteria(cv::TermCriteria::MAX_ITER + cv::TermCriteria::EPS, |
||
59 | 30, // max number of iterations |
||
60 | 0.1)); // min accuracy |
||
3 | PointedEar | 61 | |
5 | PointedEar | 62 | // If we have a good board, add it to our data |
63 | if (imageCorners.size() == (unsigned int) boardSize.area()) |
||
64 | { |
||
3 | PointedEar | 65 | |
5 | PointedEar | 66 | // Add image and scene points from one view |
67 | addPoints(imageCorners, objectCorners); |
||
68 | successes++; |
||
69 | } |
||
3 | PointedEar | 70 | |
5 | PointedEar | 71 | //Draw the corners |
72 | cv::drawChessboardCorners(image, boardSize, imageCorners, found); |
||
73 | cv::imshow("Corners on Chessboard", image); |
||
74 | cv::waitKey(100); |
||
3 | PointedEar | 75 | } |
76 | |||
5 | PointedEar | 77 | return successes; |
3 | PointedEar | 78 | } |
79 | |||
80 | // Add scene points and corresponding image points |
||
5 | PointedEar | 81 | void |
82 | CameraCalibrator::addPoints(const std::vector<cv::Point2f>& imageCorners, |
||
83 | const std::vector<cv::Point3f>& objectCorners) |
||
84 | { |
||
3 | PointedEar | 85 | |
5 | PointedEar | 86 | // 2D image points from one view |
87 | imagePoints.push_back(imageCorners); |
||
88 | // corresponding 3D scene points |
||
89 | objectPoints.push_back(objectCorners); |
||
3 | PointedEar | 90 | } |
91 | |||
92 | // Calibrate the camera |
||
93 | // returns the re-projection error |
||
5 | PointedEar | 94 | double |
95 | CameraCalibrator::calibrate(cv::Size imageSize) |
||
3 | PointedEar | 96 | { |
5 | PointedEar | 97 | // undistorter must be reinitialized |
98 | mustInitUndistort = true; |
||
3 | PointedEar | 99 | |
5 | PointedEar | 100 | //Output rotations and translations |
101 | std::vector<cv::Mat> rvecs, tvecs; |
||
3 | PointedEar | 102 | |
5 | PointedEar | 103 | // start calibration |
104 | return calibrateCamera(objectPoints, // the 3D points |
||
105 | imagePoints, // the image points |
||
106 | imageSize, // image size |
||
107 | cameraMatrix, // output camera matrix |
||
108 | distCoeffs, // output distortion matrix |
||
109 | rvecs, tvecs, // Rs, Ts |
||
110 | flag); // set options |
||
3 | PointedEar | 111 | // ,CV_CALIB_USE_INTRINSIC_GUESS); |
112 | |||
113 | } |
||
114 | |||
115 | // remove distortion in an image (after calibration) |
||
5 | PointedEar | 116 | cv::Mat |
117 | CameraCalibrator::remap(const cv::Mat &image) |
||
118 | { |
||
3 | PointedEar | 119 | |
5 | PointedEar | 120 | cv::Mat undistorted; |
3 | PointedEar | 121 | |
5 | PointedEar | 122 | if (mustInitUndistort) |
123 | { // called once per calibration |
||
124 | |||
125 | cv::initUndistortRectifyMap(cameraMatrix, // computed camera matrix |
||
126 | distCoeffs, // computed distortion matrix |
||
127 | cv::Mat(), // optional rectification (none) |
||
128 | cv::Mat(), // camera matrix to generate undistorted |
||
129 | cv::Size(640, 480), |
||
3 | PointedEar | 130 | // image.size(), // size of undistorted |
5 | PointedEar | 131 | CV_32FC1,// type of output map |
132 | map1, map2); // the x and y mapping functions |
||
3 | PointedEar | 133 | |
5 | PointedEar | 134 | mustInitUndistort = false; |
135 | } |
||
3 | PointedEar | 136 | |
5 | PointedEar | 137 | // Apply mapping functions |
138 | cv::remap(image, undistorted, map1, map2, cv::INTER_LINEAR); // interpolation type |
||
3 | PointedEar | 139 | |
5 | PointedEar | 140 | return undistorted; |
3 | PointedEar | 141 | } |
142 | |||
143 | // Set the calibration options |
||
144 | // 8radialCoeffEnabled should be true if 8 radial coefficients are required (5 is default) |
||
145 | // tangentialParamEnabled should be true if tangeantial distortion is present |
||
5 | PointedEar | 146 | void |
147 | CameraCalibrator::setCalibrationFlag(bool radial8CoeffEnabled, |
||
148 | bool tangentialParamEnabled) |
||
149 | { |
||
3 | PointedEar | 150 | |
5 | PointedEar | 151 | // Set the flag used in cv::calibrateCamera() |
152 | flag = 0; |
||
153 | if (!tangentialParamEnabled) |
||
154 | flag += CV_CALIB_ZERO_TANGENT_DIST; |
||
155 | if (radial8CoeffEnabled) |
||
156 | flag += CV_CALIB_RATIONAL_MODEL; |
||
3 | PointedEar | 157 | } |
158 |