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 |