title: Root Mean Square for OpenCV Camera Calibration is too High
body: <p>I am attempting to calibrate my single webcam using opencv cv2 in python. I am using the cv2.findChessboardCorners and cv2.calibrateCamera functions. However, my root mean square returned from the calibrateCamera function seems very high. It is always around 50 no matter how many frames with found boards are used. I read that good values range from 0-1. I am using a 5x8 black and white checker pattern on a piece of paper taped to a wooden board. Can anyone help me out with getting  this lower? The weird thing is I used images I rendered from Blender, a 3d modeling software, in which there is no lens distortion and the board's coordinates are known for sure and I was able to get a RMS of 0.22 which is good. Using similar code though I cannot replicate those results with my webcam. Perhaps I am missing something. Thanks so much to everyone who takes a look at this. Here is the complete code:</p>
  
  <pre><code>import sys
  import os
  import numpy as np
  import cv2
  import time
  
  '''
  This module finds the intrinsic parameters of the camera. These parameters include
  the focal length, pixel aspect ratio, image center, and lens distortion (see wiki
  entry for "camera resectioning" for more detail). It is important to note that the
  parameters found by this class are independent of location and rotation of the camera.
  Thus, it only needs to be calculated once assuming the lens and focus of the camera is
  unaltered. The location and rotation matrix are defined by the extrinsic parameters.
  '''
  
  class Find_Intrinsics:
      '''Finds the intrinsic parameters of the camera.'''
      def __init__(self):
          #Import user input from Blender in the form of argv's 
          self.rows = int(sys.argv[1])
          self.cols = int(sys.argv[2])
          self.board_width_pxls = float(sys.argv[3])
          self.pxls_per_sq_unit = float(sys.argv[4])
          self.printer_scale = float(sys.argv[5])
  
  
      def find_calib_grid_points(self,cols,rows,board_width_pxls,pxls_per_sq_unit,printer_scale):
          '''Defines the distance of the board squares from each other and scale them.
  
              The scaling is to correct for the scaling of the printer. Most printers
              cannot print all the way to the end of the page and thus scale images to
              fit the entire image. If the user does not desire to maintain real world
              scaling, then an arbitrary distance is set. The 3rd value appended to
              calib_points signifies the depth of the points and is always zero because
              they are planar. 
          '''
          #should be dist for each square
          point_dist = (((board_width_pxls)/(pxls_per_sq_unit))*printer_scale)/(cols+2)
          calib_points = []
          for i in range(0,cols):
              for j in range(0,rows):
                  pointX = 0 + (point_dist*j)
                  pointY = 0 - (point_dist*i)
                  calib_points.append((pointX,pointY,0))    
          np_calib_points = np.array(calib_points,np.float32)
          return np_calib_points
  
  
      def main(self):
          print '---------------------------Finding Intrinsics----------------------------------'       
          np_calib_points = self.find_calib_grid_points(self.cols,self.rows,self.board_width_pxls,
                                                   self.pxls_per_sq_unit,self.printer_scale)
          pattern_size = (self.cols,self.rows)
          obj_points = []
          img_points = []        
  
          camera =  cv2.VideoCapture(0)
          found_count = 0
          while True:
              found_cam,img = camera.read()            
              h, w = img.shape[:2]
              print h,w
              gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
              found, corners = cv2.findChessboardCorners(img, pattern_size)            
  
              if found:            
                  term = ( cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT, 30, 0.1 )
                  cv2.cornerSubPix(gray_img, corners, (5, 5), (-1, -1), term)
  
                  cv2.drawChessboardCorners(img, pattern_size, corners, found)
                  found_count+=1
  
                  img_points.append(corners.reshape(-1, 2))
                  obj_points.append(np_calib_points)
  
              cv2.putText(img,'Boards found: '+str(found_count),(30,30), 
                  cv2.FONT_HERSHEY_DUPLEX, 0.8,(0,0,255,1))
              cv2.putText(img,'Press any key when finished',(30,h-30), 
                  cv2.FONT_HERSHEY_DUPLEX, 0.8,(0,0,255,1))
              cv2.imshow("webcam",img)
  
              if (cv2.waitKey (1000) != -1):
                  cv2.destroyAllWindows()
                  del(camera)
                  np_obj_points = np.array(obj_points)
                  print "Calibrating.Please be patient"
                  start = time.clock()
  
                  #OpenCV function to solve for camera matrix
                  try:
                      print obj_points[0:10]
                      rms, camera_matrix, dist_coefs, rvecs, tvecs = cv2.calibrateCamera(obj_points, img_points, (w, h))
                      print "RMS:", rms
                      print "camera matrix:\n", camera_matrix
                      print "distortion coefficients: ", dist_coefs
  
                      #Save the camera matrix and the distortion coefficients to the hard drive to use
                      #to find the extrinsics
                      #want to use same file directory as this file
                      #directory = os.path.dirname(os.path.realpath('Find_Intrinsics.py'))
                      np.save('C:\\Users\\Owner\\Desktop\\3D_Scanning\\Blender_3d_Scanning\\camera_matrix.npy',camera_matrix)
                      np.save('C:\\Users\\Owner\\Desktop\\3D_Scanning\\Blender_3d_Scanning\\dist_coefs.npy',dist_coefs)    
  
                      elapsed = (time.clock() - start)
                      print("Elapsed time: ", elapsed, " seconds") 
  
                      img_undistort = cv2.undistort(img,camera_matrix,dist_coefs)
                      cv2.namedWindow('Undistorted Image',cv2.WINDOW_NORMAL)#WINDOW_NORMAL used bc WINDOW_AUTOSIZE does not let you resize
                      cv2.resizeWindow('Undistorted Image',w,h)
                      cv2.imshow('Undistorted Image',img_undistort)
                      cv2.waitKey(0)
                      cv2.destroyAllWindows()
  
                      break
  
                  except:
                      print "\nSorry, an error has occurred. Make sure more than zero boards are found."
                      break
  
  if __name__ == '__main__' and len(sys.argv)== 6:
      Intrinsics = Find_Intrinsics()
      Intrinsics_main = Intrinsics.main()
  else:
      print "Incorrect number of args found. Make sure that the python27 filepath is entered correctly."
  print '--------------------------------------------------------------------------------'
  </code></pre>