3

我正在尝试在 python 中使用 opencv cv2 校准我的单个网络摄像头。我正在使用 cv2.findChessboardCorners 和 cv2.calibrateCamera 函数。但是,我从 calibrateCamera 函数返回的均方根似乎非常高。无论使用多少带有找到板的框架,它总是在 50 左右。我读到好的值范围是 0-1。我在一张贴在木板上的纸上使用 5x8 黑白棋盘格图案。谁能帮我把这个降低?奇怪的是我使用了从 3D 建模软件 Blender 渲染的图像,其中没有镜头失真,并且板的坐标是肯定的,我能够获得 0.22 的 RMS,这很好。使用类似的代码虽然我无法用我的网络摄像头复制这些结果。也许我错过了一些东西。非常感谢所有看到这个的人。这是完整的代码:

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

1 回答 1

2

哇,我不知道在 stackoverflow 上发布后立即拥有 aha 时刻(或者,doh!如果你看《辛普森一家》的时刻)是什么意思,哈哈。这是一个彻头彻尾的错误。我设法弄乱了 calibrateCamera 函数的 obj_points 参数的构造。OpenCV 将第一个点放在左上角,然后从左到右遍历每一,直到到达最后一个点(右下角)。因此,我的 find_calib_grid_points 函数是错误的。这是正确的代码,以防其他人被绊倒,尽管这可能不太可能:

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)

感谢所有看到这个并向我发送通灵信息的人,所以我可以弄清楚这个哈哈。他们工作了!我的 RMS 是 0.33!

于 2013-03-27T23:38:03.843 回答