我正在尝试使用Python中的OpenCV cv2校准我的单个网络摄像头。我正在使用cv2.findChessboardCorners和cv2.calibrateCamera函数。然而,从calibrateCamera函数返回的均方根误差似乎非常高。无论使用多少帧找到的棋盘,它始终在50左右。我读到好的值范围在0-1之间。我在木板上贴了一张5x8的黑白格子图案纸片。有谁能帮我降低这个均方根误差?奇怪的是,我使用了Blender渲染的图像(一款3D建模软件),其中没有镜头畸变,并且该板的坐标肯定已知,我能够得到一个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 '--------------------------------------------------------------------------------'