stereo-vision
All Data Structures Namespaces Functions Modules Pages
camera.cpp
1 /*
2  * Copyright (C) 2011 Department of Robotics Brain and Cognitive Sciences - Istituto Italiano di Tecnologia
3  * Authors: Vadim Tikhanoff
4  * email: vadim.tikhanoff@iit.it
5  * website: www.robotcub.org
6  * Permission is granted to copy, distribute, and/or modify this program
7  * under the terms of the GNU General Public License, version 2 or any
8  * later version published by the Free Software Foundation.
9  *
10  * A copy of the license can be found at
11  * http://www.robotcub.org/icub/license/gpl.txtd
12  *
13  * This program is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
16  * Public License for more details
17  */
18 
19 #include <cstdio>
20 #include <opencv2/core/base.hpp>
21 #include <opencv2/imgproc.hpp>
22 #include <opencv2/calib3d.hpp>
23 #include "iCub/stereoVision/camera.h"
24 
25 Camera::Camera(string intrinsicFilePath) {
26  FileStorage fs(intrinsicFilePath.c_str(), FileStorage::READ);
27  if(!fs.isOpened())
28  {
29  printf("Failed to open file %s\n", intrinsicFilePath.c_str());
30  return;
31  }
32  fs["camera_matrix"] >> K;
33  fs["distortion_coefficients"] >> Dist;
34 
35 }
36 
37 
38 
39 void Camera::printMatrix(Mat &matrix) {
40  cout << endl;
41  int row=matrix.rows;
42  int col =matrix.cols;
43 
44  for(int i = 0; i < matrix.rows; i++)
45  {
46  const double* Mi = matrix.ptr<double>(i);
47  for(int j = 0; j < matrix.cols; j++)
48  cout << Mi[j] << " ";
49  cout << endl;
50  }
51  cout << endl;
52 }
53 void Camera::calibrate(vector<string> imageList, int boardWidth, int boardHeight) {
54  vector<vector<Point2f> > imagePoints;
55  Size boardSize, imageSize;
56  boardSize.width=boardWidth;
57  boardSize.height=boardHeight;
58  int flags=0;
59  int i;
60 
61  float squareSize = 1.f, aspectRatio = 1.f;
62 
63  Mat view, viewGray;
64 
65  for(i = 0; i<(int)imageList.size();i++)
66  {
67 
68  view = cv::imread(imageList[i], 1);
69  imageSize = view.size();
70  vector<Point2f> pointbuf;
71  cvtColor(view, viewGray, cv::COLOR_BGR2GRAY);
72 
73  bool found = findChessboardCorners( view, boardSize, pointbuf,
74  cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_FAST_CHECK + cv::CALIB_CB_NORMALIZE_IMAGE);
75 
76  if(found)
77  {
78  drawChessboardCorners( view, boardSize, Mat(pointbuf), found );
79  imagePoints.push_back(pointbuf);
80  }
81 
82  }
83  prepareandRunCalibration(imagePoints, imageSize, boardSize, squareSize, aspectRatio, flags, K, Dist);
84 
85 
86 }
87 
88 void Camera::calibrate(string imagesFilePath, int boardWidth, int boardHeight) {
89  vector<vector<Point2f> > imagePoints;
90  vector<string> imageList;
91  Size boardSize, imageSize;
92  boardSize.width=boardWidth;
93  boardSize.height=boardHeight;
94  int flags=0;
95  int i;
96 
97  float squareSize = 1.f, aspectRatio = 1.f;
98 
99  // Read Image Calibration List
100  if(!readStringList(imagesFilePath, imageList))
101  {
102  cout << "Cannot Open Image List File. Calibration Failed" << endl;
103  return;
104  }
105 
106  Mat view, viewGray;
107 
108  for(i = 0; i<(int)imageList.size();i++)
109  {
110 
111  view = cv::imread(imageList[i], 1);
112  imageSize = view.size();
113  vector<Point2f> pointbuf;
114  cvtColor(view, viewGray, cv::COLOR_BGR2GRAY);
115 
116  bool found = findChessboardCorners( view, boardSize, pointbuf,
117  cv::CALIB_CB_ADAPTIVE_THRESH + cv::CALIB_CB_FAST_CHECK + cv::CALIB_CB_NORMALIZE_IMAGE);
118 
119 
120  if(found)
121  {
122  drawChessboardCorners( view, boardSize, Mat(pointbuf), found );
123  imagePoints.push_back(pointbuf);
124  }
125 
126  }
127  prepareandRunCalibration(imagePoints, imageSize, boardSize, squareSize, aspectRatio, flags, K, Dist);
128 
129 }
130 
131 bool Camera::readStringList( const string& filename, vector<string>& l )
132 {
133  l.resize(0);
134  FileStorage fs(filename, FileStorage::READ);
135  if( !fs.isOpened() )
136  return false;
137  FileNode n = fs.getFirstTopLevelNode();
138  if( n.type() != FileNode::SEQ )
139  return false;
140  FileNodeIterator it = n.begin(), it_end = n.end();
141  for( ; it != it_end; ++it )
142  l.push_back((string)*it);
143  return true;
144 }
145 
146 
147 
148 
149 bool Camera::prepareandRunCalibration(const vector<vector<Point2f> >& imagePoints,
150  Size imageSize, Size boardSize, float squareSize,
151  float aspectRatio, int flags, Mat& cameraMatrix,
152  Mat& distCoeffs)
153 {
154  vector<Mat> rvecs, tvecs;
155  vector<float> reprojErrs;
156  double totalAvgErr = 0;
157 
158  bool ok = runCalibration(imagePoints, imageSize, boardSize, squareSize,
159  aspectRatio, flags, cameraMatrix, distCoeffs,
160  rvecs, tvecs, reprojErrs, totalAvgErr);
161  printf("%s. avg reprojection error = %.2f\n",
162  ok ? "Calibration succeeded" : "Calibration failed",
163  totalAvgErr);
164 
165  return ok;
166 
167 }
168 
169 bool Camera::runCalibration( vector<vector<Point2f> > imagePoints,
170  Size imageSize, Size boardSize,
171  float squareSize, float aspectRatio,
172  int flags, Mat& cameraMatrix, Mat& distCoeffs,
173  vector<Mat>& rvecs, vector<Mat>& tvecs,
174  vector<float>& reprojErrs,
175  double& totalAvgErr)
176 {
177  cameraMatrix = Mat::eye(3, 3, CV_64F);
178  if( flags & cv::CALIB_FIX_ASPECT_RATIO )
179  cameraMatrix.at<double>(0,0) = aspectRatio;
180 
181  distCoeffs = Mat::zeros(4, 1, CV_64F);
182 
183  vector<vector<Point3f> > objectPoints(1);
184  calcChessboardCorners(boardSize, squareSize, objectPoints[0]);
185 
186  objectPoints.resize(imagePoints.size(),objectPoints[0]);
187 
188  double rms = calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix,
189  distCoeffs, rvecs, tvecs, cv::CALIB_FIX_K3);
190  printf("RMS error reported by calibrateCamera: %g\n", rms);
191 
192  bool ok = checkRange(cameraMatrix) && checkRange(distCoeffs);
193 
194  totalAvgErr = computeReprojectionErrors(objectPoints, imagePoints,
195  rvecs, tvecs, cameraMatrix, distCoeffs, reprojErrs);
196 
197  return ok;
198 }
199 
200 void Camera::calcChessboardCorners(Size boardSize, float squareSize, vector<Point3f>& corners)
201 {
202  corners.resize(0);
203 
204  for( int i = 0; i < boardSize.height; i++ )
205  for( int j = 0; j < boardSize.width; j++ )
206  corners.push_back(Point3f(float(j*squareSize),
207  float(i*squareSize), 0));
208 }
209 
210 double Camera::computeReprojectionErrors(
211  const vector<vector<Point3f> >& objectPoints,
212  const vector<vector<Point2f> >& imagePoints,
213  const vector<Mat>& rvecs, const vector<Mat>& tvecs,
214  const Mat& cameraMatrix, const Mat& distCoeffs,
215  vector<float>& perViewErrors )
216 {
217  vector<Point2f> imagePoints2;
218  int i, totalPoints = 0;
219  double totalErr = 0, err;
220  perViewErrors.resize(objectPoints.size());
221 
222  for( i = 0; i < (int)objectPoints.size(); i++ )
223  {
224  projectPoints(Mat(objectPoints[i]), rvecs[i], tvecs[i],
225  cameraMatrix, distCoeffs, imagePoints2);
226  err = norm(Mat(imagePoints[i]), Mat(imagePoints2), cv::NORM_L2);
227  int n = (int)objectPoints[i].size();
228  perViewErrors[i] = (float)std::sqrt(err*err/n);
229  totalErr += err*err;
230  totalPoints += n;
231  }
232 
233  return std::sqrt(totalErr/totalPoints);
234 }
235 
236 
237 bool Camera::saveCalibration(string intrinsicFilePath) {
238 
239  if(this->K.empty()) {
240  printf("Camera is not calibrated, run calibration method before..\n");
241  return false;
242  }
243  FileStorage fs( intrinsicFilePath, FileStorage::WRITE );
244  fs << "camera_matrix" << this->K;
245  fs << "distortion_coefficients" << this->Dist;
246  return true;
247 }
248 
249 void Camera::printCameraMatrix()
250 { if(this->K.empty())
251  printf("Camera is not calibrated, run calibration method before..\n");
252  else
253  printMatrix(this->K);
254 }
255 
256 void Camera::printDistortionVector()
257 { if(this->Dist.empty())
258  printf("Camera is not calibrated, run calibration method before..\n");
259  else
260  printMatrix(this->Dist);
261 }
262 
263 
265  return this->K;
266 }
268  return this->Dist;
269 }
270 
271 Mat Camera::undistortImage(Mat image) {
272  Mat imund;
273  undistort(image,imund,K,Dist);
274  return imund;
275 }
276 
278  this->K=K;
279 }
280 
282  this->Dist=Dist;
283 }
void setDistCoefficients(Mat &Dist)
It sets the distortion parameters.
Definition: camera.cpp:281
Camera()
Default Constructor.
Definition: camera.h:82
Mat getDistVector()
It returns the 4x1 distortion coefficients.
Definition: camera.cpp:267
bool saveCalibration(string intrinsicFilePath)
It saves the calibration.
Definition: camera.cpp:237
void setCameraMatrix(Mat &K)
It sets the camera parameters.
Definition: camera.cpp:277
Mat undistortImage(Mat image)
It undistorts an image using the intrinsic parameters.
Definition: camera.cpp:271
Mat getCameraMatrix()
It returns the 3x3 camera matrix.
Definition: camera.cpp:264