【问题标题】:Strange results with OpenCV camera calibrationOpenCV 相机校准的奇怪结果
【发布时间】:2021-06-25 13:39:48
【问题描述】:

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

然后我想在不裁剪任何内容的情况下查看图像的未失真版本,我得到了这个:

这显然没有任何意义。我曾尝试对另一组校准图像做同样的事情,并且成功了:

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

以下是相关代码:

# 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()

【问题讨论】:

  • 第一组校准图像(全部)是什么样的?
  • 根据我的经验,calibrateCamera 函数会在给定样本的图像区域内进行优化,因此请尝试放置校准图案以覆盖尽可能多的图像!
  • @DanMašek 我的校准图像看起来都不错(网格在正确的位置)。我有很多图像在非常相似的地方(冗余)我删除了一些,结果变得更好了。虽然不知道原因.. 多余的图像应该不重要吧?
  • 冗余图像“有点”;有效地使这些图像(以及这些图像中棋盘图案的位置)更加重要。 Micka 的观点也很重要。确保校准网格尽可能多地填充图像很重要,或者至少在边界附近有一些棋盘的图片。

标签: python opencv


【解决方案1】:

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

这个问题是中心附近的失真很小,而边界处的失真很大。因此,大的失真不会对图像的中心产生太大影响。等效地,从图像中心估计失真的一个小错误可能会导致对失真的总体估计非常错误。

冗余图像“有点”重要;它有效地使这些图像(以及这些图像中棋盘图案的位置)更加重要。

【讨论】:

    【解决方案2】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-09-17
      • 2018-07-15
      • 2013-01-28
      • 2014-10-23
      • 1970-01-01
      • 2012-04-18
      • 2016-12-29
      • 2020-04-29
      相关资源
      最近更新 更多