OpenCV相机校准的奇怪结果

时间:2016-04-03 15:51:25

标签: python opencv

我正在按照OpenCV tutorial校准我的GoPro。为了校准,我有一堆图片,棋盘位于不同的位置。然后我在棋盘上绘制3D轴,一切看起来都很好,校准似乎很好:

Axis successfully plotted

然后我想看到没有裁剪任何东西的图像的未失真版本,我得到了这个:

enter image description here

这显然没有任何意义。我试图用另一组校准图像做同样的事情并且它起作用了:

enter image description here

我不明白为什么它不能用于第一组图片。有什么想法吗?

以下是相关代码:

# termination criteria
criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001)

# prepare object points, like (0,0,0), (1,0,0), (2,0,0) ....,(6,5,0)
objp = np.zeros((9*6,3), np.float32)
objp[:,:2] = np.mgrid[0:9,0:6].T.reshape(-1,2)

# Arrays to store object points and image points from all the images.
objpoints = [] # 3d point in real world space
imgpoints = [] # 2d points in image plane.

files = os.listdir('frames')
for fname in files:
    g = re.match('frame(\d+).png',fname)
    n = g.groups()[0]
    if n not in numbers:
        os.remove('frames/%s'%fname)
        continue
    img = cv2.imread('frames/%s'%fname)
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    # Find the chess board corners
    ret, corners = cv2.findChessboardCorners(gray, (9,6),None)

    # If found, add object points, image points (after refining them)
    if ret == True:
        corners2 = cv2.cornerSubPix(gray,corners,(11,11),(-1,-1),criteria)
        img = cv2.drawChessboardCorners(img, (9,6), corners2,ret)
        objpoints.append(objp)
        imgpoints.append(corners2)
        cv2.imshow('img',img)
        cv2.waitKey(1)
cv2.destroyAllWindows()

ret, K, D, rvecs, tvecs = cv2.calibrateCamera(objpoints, imgpoints, gray.shape[::-1],None,None)
# K: intrinsic matrix - camera matrix
# D: Distortion coefficients 

#Compute reconstruction error
mean_error = 0
for i in xrange(len(objpoints)):
    imgpoints2, _ = cv2.projectPoints(objpoints[i], rvecs[i], tvecs[i], K, D)
    error = cv2.norm(imgpoints[i],imgpoints2, cv2.NORM_L2)/len(imgpoints2)
    mean_error += error

print "total error: ", mean_error/len(objpoints)

ret, rvec, tvec = cv2.solvePnP(objp, corners2, K, D)

# project 3D points to image plane Using openCV
imgpts, jac = cv2.projectPoints(axis, rvec, tvec, K, D)
img = draw(img,corners2,imgpts)
cv2.imshow('img',img)
k = cv2.waitKey(0) & 0xff

f = file('camera.pkl','wb')
cPickle.dump((K,D,rvec,tvec),f)
f.close()


#get the Undistorted image
h,  w = img.shape[:2]
newcameraK, roi=cv2.getOptimalNewCameraMatrix(K,D,(w,h),1,(w,h))

dst = cv2.undistort(img, K, D, None, newcameraK)

plt.figure()
plt.axis("off")
plt.imshow(cv2.cvtColor(dst,cv2.COLOR_BGR2RGB))
plt.show()

2 个答案:

答案 0 :(得分:0)

Micka的观点很重要;确保校准网格尽可能多地填充图像很重要,或者至少有一些棋盘格靠近边界的图片。

这个问题是中心附近的变形很小而边界处的变形很大。因此,大的失真不会非常影响图像的中心。同样地,从图像中心估计失真的小误差导致可能非常错误的失真总体估计。

冗余图像很重要"一点点&#34 ;;它有效地使这些图像(因此,棋盘图案在这些图像中的位置)更加重要。

答案 1 :(得分:0)

我也观察到了同样的效果,但更奇怪:

当我使用 getOptimalTransformationMatrix 时,我得到的图像也有像上面那样强烈的圆形失真效果。改变 alpha 也不能解决它。但是:当我在没有 getOptimalTransformationMatrix 的情况下使用相同的失真/校准结果(所以我使用与相机校准结果相同的 fx/fy/cx/cy)时,我在不失真方面得到了非常好的结果......非常奇怪......

会不会是在某些情况下 getOptimalTransformationMatrix 函数有问题?我的校准(图像等)看起来很好,点也在边缘