2013-03-27 2 views
2

Je tente de calibrer ma webcam en utilisant opencv cv2 en python. J'utilise les fonctions cv2.findChessboardCorners et cv2.calibrateCamera. Cependant, ma racine moyenne renvoyée par la fonction calibrateCamera semble très élevée. Il est toujours autour de 50, peu importe combien de cadres avec des panneaux trouvés sont utilisés. J'ai lu que les bonnes valeurs vont de 0-1. J'utilise un damier noir et blanc 5x8 sur un morceau de papier collé à une planche de bois. Quelqu'un peut-il m'aider à obtenir plus bas? Ce qui est bizarre, c'est que j'ai utilisé des images de Blender, un logiciel de modélisation 3D dans lequel il n'y a pas de distorsion de l'objectif et les coordonnées du tableau sont sûres et j'ai pu obtenir un RMS de 0.22. En utilisant un code similaire, je ne peux pas reproduire ces résultats avec ma webcam. Peut-être qu'il me manque quelque chose. Merci beaucoup à tous ceux qui y jettent un coup d'œil. Voici le code complet:La racine du carré pour l'étalonnage de la caméra OpenCV est trop élevée

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 '--------------------------------------------------------------------------------' 

Répondre

1

Wow, je ne sais pas ce qu'il est d'avoir des moments aha (ou Doh moments si vous regardez les Simpsons!) Juste après l'affichage sur stackoverflow haha. Celui-ci était une erreur de tête d'os. J'ai réussi à gâcher la construction du paramètre obj_points pour la fonction calibrateCamera. OpenCV prend le premier point en haut à gauche et passe par ligne, de gauche à droite, jusqu'à arriver au dernier point (en bas à droite). En tant que tel, ma fonction find_calib_grid_points était erronée. Voici le code correct juste au cas où quelqu'un d'autre se fait trébucher à ce sujet, bien que ce soit probablement peu probable:

for j in range(0,rows): 
      for i in range(0,cols): 
       pointX = 0 + (point_dist*i) 
       pointY = 0 - (point_dist*j) 
       calib_points.append((pointX,pointY,0))  
     np_calib_points = np.array(calib_points,np.float32) 

Merci à tous ceux qui ont regardé et m'a envoyé des messages psychiques pour que je puisse comprendre cela à droite haha . Ils ont travaillé! Mon RMS était de 0,33!

Questions connexes