OPENCV-校准鱼眼镜头误差(条件矩阵不良)



我正在尝试按照以下说明来校准鱼眼镜头https://medium.com/@kennethjiang/calibrate-fisheye-lens-usis-using-opencv-333b05afa0b0您可以在哪里找到我用于校准部分的完整代码。

我到达了:

N_OK = len(objpoints)
K = np.zeros((3, 3))
D = np.zeros((4, 1))
rvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_OK)]
tvecs = [np.zeros((1, 1, 3), dtype=np.float64) for i in range(N_OK)]  
rms, _, _, _, _ = 
    cv2.fisheye.calibrate(
        objpoints,
        imgpoints,
        gray.shape[::-1],
        K,
        D,
        rvecs,
        tvecs,
        calibration_flags,
        (cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-3)
    )
print("Found " + str(N_OK) + " valid images for calibration")
print("DIM=" + str(_img_shape[::-1]))
print("K=np.array(" + str(K.tolist()) + ")")
print("D=np.array(" + str(D.tolist()) + ")")

我得到此错误:

Traceback (most recent call last)
<ipython-input-10-deaca9981fe4> in <module>()
     13         tvecs,
     14         calibration_flags,
---> 15         (cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-3)
     16     )
     17 print("Found " + str(N_OK) + " valid images for calibration")
error: C:ciopencv_1512688052760workmodulescalib3dsrcfisheye.cpp:1414: 
error: (-3) CALIB_CHECK_COND - Ill-conditioned matrix for input array 0 in 
function cv::internal::CalibrateExtrinsics

我不明白发生了什么,我只能在互联网周围找到如此少的信息,有人经历了类似的事情并知道如何解决这个问题吗?

谢谢

这些是我正在使用的棋盘板的图像:

  • https://i.stack.imgur.com/gohig.jpg
  • https://i.stack.imgur.com/kja3o.jpg
  • https://i.stack.imgur.com/xbizh.jpg
  • https://i.stack.imgur.com/uq9gr.jpg
  • https://i.stack.imgur.com/n8alj.jpg
  • https://i.stack.imgur.com/jmmmz.jpg
  • https://i.stack.imgur.com/qj8wn.jpg
  • https://i.stack.imgur.com/nmifq.jpg
  • https://i.stack.imgur.com/sqhdd.jpg
  • https://i.stack.imgur.com/dnbud.jpg
  • https://i.stack.imgur.com/vftoo.jpg
  • https://i.stack.imgur.com/lhkf5.jpg

我认为这是因为您的变量校准_flags具有calib_check_cond集。尝试禁用此标志。没有它,我就可以不介绍您的图像(请参见下面的链接(。

我不确定此检查是什么(文档不是很明确(。该旗帜拒绝我的GoPro Hero 3的一些图像。即使可以看到棋盘并检测到棋盘。在我的情况下,20个图像不是通过此测试。此图像在靠近左边框的棋盘上。

  • https://i.stack.imgur.com/m2wf6.jpg
  • https://i.stack.imgur.com/kitrz.jpg
  • https://i.stack.imgur.com/mhhyn.jpg
  • https://i.stack.imgur.com/psiyg.jpg
  • https://i.stack.imgur.com/drxsl.jpg
  • https://i.stack.imgur.com/ddze1.jpg
  • https://i.stack.imgur.com/b6l8f.jpg
  • https://i.stack.imgur.com/9mrak.jpg
  • https://i.stack.imgur.com/wymg5.jpg
  • https://i.stack.imgur.com/rmj5q.jpg
  • https://i.stack.imgur.com/k8k8y.jpg
  • https://i.stack.imgur.com/miber.jpg

¹在OPENCV版本中> = 3.4.1错误消息告诉您哪个图像未通过测试

我没有在python中找到代码,因此我在边缘上用棋盘手动检查图像,然后一个一个删除它们,直到错误消失。

正如@Ahmadiah所述,当棋盘落在图像边缘附近时,"条件疾病"的事情可能发生。处理此操作的一种方法是,一一删除图像,并在导致校准失败时重试。这是我们这样做的示例:

def calibrate_fisheye(all_image_points, all_true_points, image_size):
    """ Calibrate a fisheye camera from matching points.
    :param all_image_points: Sequence[Array(N, 2)[float32]] of (x, y) image coordinates of the points.  (see  cv2.findChessboardCorners)
    :param all_true_points: Sequence[Array(N, 3)[float32]] of (x,y,z) points.  (If from a grid, just put (x,y) on a regular grid and z=0)
        Note that each of these sets of points can be in its own reference frame,
    :param image_size: The (size_y, size_x) of the image.
    :return: (rms, mtx, dist, rvecs, tvecs) where
        rms: float - The root-mean-squared error
        mtx: array[3x3] A 3x3 camera intrinsics matrix
        dst: array[4x1] A (4x1) array of distortion coefficients
        rvecs: Sequence[array[N,3,1]] of estimated rotation vectors for each set of true points
        tvecs: Sequence[array[N,3,1]] of estimated translation vectors for each set of true points
    """
    assert len(all_true_points) == len(all_image_points)
    all_true_points = list(all_true_points)  # Because we'll modify it in place
    all_image_points = list(all_image_points)
    while True:
        assert len(all_true_points) > 0, "There are no valid images from which to calibrate."
        try:
            rms, mtx, dist, rvecs, tvecs = cv2.fisheye.calibrate(
                objectPoints=[p[None, :, :] for p in all_true_points],
                imagePoints=[p[:, None, :] for p in all_image_points],
                image_size=image_size,
                K=np.zeros((3, 3)),
                D=np.zeros((4, 1)),
                flags=cv2.fisheye.CALIB_RECOMPUTE_EXTRINSIC + cv2.fisheye.CALIB_CHECK_COND + cv2.fisheye.CALIB_FIX_SKEW,
                criteria=(cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-6),
            )
            print('Found a calibration based on {} well-conditioned images.'.format(len(all_true_points)))
            return rms, mtx, dist, rvecs, tvecs
        except cv2.error as err:
            try:
                idx = int(err.message.split('array ')[1][0])  # Parse index of invalid image from error message
                all_true_points.pop(idx)
                all_image_points.pop(idx)
                print("Removed ill-conditioned image {} from the data.  Trying again...".format(idx))
            except IndexError:
                raise err

我的openCV版本是4.0 ,我通过此方法

将其滑过
rms, _, _, _, _ = 
cv2.fisheye.calibrate(
    objpoints,
    imgpoints,
    #gray.shape[::-1],
    gray.shape,
    K,
    D,
    rvecs,
    tvecs,
    calibration_flags,
    (cv2.TERM_CRITERIA_EPS+cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-3)
)