繁体   English   中英

OpenCV摄像机校准的均方根过高

[英]Root Mean Square for OpenCV Camera Calibration is too High

我正在尝试在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 '--------------------------------------------------------------------------------'

哇,我不知道在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!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM