title: Calibrate single camera using OpenCV 2.3.1 and C++
body: <p>I'm trying to calibrate a webcam using OpenCV 2.3.1 and Visual Studio 2010 (c++ console app). I'm using this class:</p>
  
  <pre><code>class CameraCalibrator{
  private:
     std::vector&lt;std::vector&lt;cv::Point3f&gt;&gt; objectPoints;
     std::vector&lt;std::vector&lt;cv::Point2f&gt;&gt; imagePoints;
     //Square Lenght
     float squareLenght;
     //output Matrices
     cv::Mat cameraMatrix; //intrinsic
     cv::Mat distCoeffs;
     //flag to specify how calibration is done
     int flag;
     //used in image undistortion
     cv::Mat map1,map2;
     bool mustInitUndistort;
  public:
      CameraCalibrator(): flag(0), squareLenght(36.0), mustInitUndistort(true){};
      int addChessboardPoints(const std::vector&lt;std::string&gt;&amp; filelist,cv::Size&amp; boardSize){
          std::vector&lt;std::string&gt;::const_iterator itImg;
          std::vector&lt;cv::Point2f&gt; imageCorners;
          std::vector&lt;cv::Point3f&gt; objectCorners;
          //initialize the chessboard corners in the chessboard reference frame
          //3d scene points
          for(int i = 0; i&lt;boardSize.height; i++){
              for(int j=0;j&lt;boardSize.width;j++){
                  objectCorners.push_back(cv::Point3f(float(i)*squareLenght,float(j)*squareLenght,0.0f));
              }
          }
          //2D Image points:
          cv::Mat image; //to contain chessboard image
          int successes = 0;
          //cv::namedWindow("Chess");
          for(itImg=filelist.begin(); itImg!=filelist.end(); itImg++){
              image = cv::imread(*itImg,0);
              bool found = cv::findChessboardCorners(image, boardSize, imageCorners);
              //cv::drawChessboardCorners(image, boardSize, imageCorners, found);
              //cv::imshow("Chess",image);
              //cv::waitKey(1000);
              cv::cornerSubPix(image, imageCorners, cv::Size(5,5),cv::Size(-1,-1),
                  cv::TermCriteria(cv::TermCriteria::MAX_ITER+cv::TermCriteria::EPS,30,0.1));
              //if we have a good board, add it to our data
              if(imageCorners.size() == boardSize.area()){
                  addPoints(imageCorners,objectCorners);
                  successes++;
              }
          }
          return successes;
      }
      void addPoints(const std::vector&lt;cv::Point2f&gt;&amp; imageCorners,const std::vector&lt;cv::Point3f&gt;&amp; objectCorners){
          //2D image point from one view
          imagePoints.push_back(imageCorners);
          //corresponding 3D scene points
          objectPoints.push_back(objectCorners);
      }
      double calibrate(cv::Size &amp;imageSize){
          mustInitUndistort = true;
          std::vector&lt;cv::Mat&gt; rvecs,tvecs;
          return
              cv::calibrateCamera(objectPoints, //the 3D points
                  imagePoints,
                  imageSize, 
                  cameraMatrix, //output camera matrix
                  distCoeffs,
                  rvecs,tvecs,
                  flag);
      }
      void remap(const cv::Mat &amp;image, cv::Mat &amp;undistorted){
          std::cout &lt;&lt; cameraMatrix;
          if(mustInitUndistort){ //called once per calibration
              cv::initUndistortRectifyMap(
                  cameraMatrix,
                  distCoeffs,
                  cv::Mat(),
                  cameraMatrix,
                  image.size(),
                  CV_32FC1,
                  map1,map2);
              mustInitUndistort = false;
          }
          //apply mapping functions
          cv::remap(image,undistorted,map1,map2,cv::INTER_LINEAR);
      }
  };
  </code></pre>
  
  <p>I'm using 10 chessboard images (supposing that's enough for calibation) with resolution 640x480. The main function looks like this:</p>
  
  <pre><code>int main(){
      CameraCalibrator calibrateCam;
      std::vector&lt;std::string&gt; filelist;
      filelist.push_back("img10.jpg");
      filelist.push_back("img09.jpg");
      filelist.push_back("img08.jpg");
      filelist.push_back("img07.jpg");
      filelist.push_back("img06.jpg");
      filelist.push_back("img05.jpg");
      filelist.push_back("img04.jpg");
      filelist.push_back("img03.jpg");
      filelist.push_back("img02.jpg");
      filelist.push_back("img01.jpg");
  
      cv::Size boardSize(8,6);
      double calibrateError;
      int success;
      success = calibrateCam.addChessboardPoints(filelist,boardSize);
      std::cout&lt;&lt;"Success:" &lt;&lt; success &lt;&lt; std::endl;
      cv::Size imageSize;
      cv::Mat inputImage, outputImage;
      inputImage = cv::imread("img10.jpg",0);
      outputImage = inputImage.clone();
      imageSize = inputImage.size();
      calibrateError = calibrateCam.calibrate(imageSize);
      std::cout&lt;&lt;"Calibration error:" &lt;&lt; calibrateError &lt;&lt; std::endl;
      calibrateCam.remap(inputImage,outputImage);
      cv::namedWindow("Original");
      cv::imshow("Original",inputImage);
      cv::namedWindow("Undistorted");
      cv::imshow("Undistorted",outputImage);
      cv::waitKey();
      return 0;
  }
  </code></pre>
  
  <p>Everything runs without errors. cameraMatrix looks like this (approximately):</p>
  
  <p>685.65  0   365.14<br>
  0   686.38  206.98<br>
  0   0   1</p>
  
  <p>Calibration error is 0.310157, which is acceptable.</p>
  
  <p><strong>But when I use remap, output image looks even worse than original</strong>. Here is the sample:  </p>
  
  <p>Original image: <img src="https://i.stack.imgur.com/bGGPF.jpg" alt="Original image">]</p>
  
  <p>Undistorted image: <img src="https://i.stack.imgur.com/1PuFZ.jpg" alt="Undistorted image">]</p>
  
  <p>So, the question is, am I doing something wrong in process of calibration? Is 10 different chessboard images enough for calibration? Do you have any suggestions?</p>