opencv charuco相机校准无法正确失真

时间:2019-04-15 12:57:55

标签: opencv camera-calibration aruco

我无法让charuco相机校准正常工作。据我所知,我做的一切正确,但是最终的未失真图像比预期的要扭曲得多。它确实可以在4x4板上工作,但是校正后的面积太小,因此我需要使事情在7x7板上工作。如果有人可以看到我在做什么,那么非常感谢您的帮助,此刻我有些困惑。这样的话:

我设置了4个摄像机,每个摄像机都需要校准。 每个摄像机我都有11张charuco板7x7_1000的图片,所以总共有44张图片

这些是原始图像(适用于所有相机):

image description

根据我在本教程中所了解的*,并不是所有标记都必须是可见的,才能进行charuco相机校准(这是charuco bord的全部思想)据我所知,源图像很好

我为每个摄像机检索一组图像的标记和内插的棋盘角,并将其提供给v2.aruco.calibrateCameraCharuco函数。一切似乎都很好,因为这张只有一个标记的图像显示了:

image description

所以我继续调用cv2.undistort函数,但是结果不是我期望的:

image description

这是我根据教程中的示例编写的代码:

def draw_charuco_board( filename, board, size=(2000, 2000) ):
    imboard = board.draw(size)
    cv2.imwrite(filename, imboard)


def detect_charuco_corners( full_board_image_gray, board ):
    parameters = cv2.aruco.DetectorParameters_create()
    return cv2.aruco.detectMarkers(full_board_image_gray, board.dictionary, parameters=parameters)


def charuco_camera_calib( board, filename_glob_pattern, do_flip=False, flip_axis=0 ):
    """
    calibrates the camera using the charuco board
    @see https://docs.opencv.org/trunk/d9/d6a/group__aruco.html#ga54cf81c2e39119a84101258338aa7383
    @see https://github.com/opencv/opencv_contrib/blob/master/modules/aruco/samples/calibrate_camera_charuco.cpp
    """
    charuco_corners = []
    charuco_ids = []
    calib_corners = []
    calib_ids = []
    fns = glob.glob(filename_glob_pattern)
    size = None
    for fn in fns:
        image = cv2.imread(fn, flags=cv2.IMREAD_UNCHANGED)
        image_size = tuple(image.shape[:2][::-1])
        if size is None:
            size = image_size
        elif not image_size == size:
            raise RuntimeError( "charuco_camera_calib:images are not the same size. previous: {} last: {}\n\tlast image: {}".format(size,image_size,fn))
        image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
        if do_flip:
            image = cv2.flip(image, flip_axis)
        corners, ids, _ = detect_charuco_corners( image, board )
        charuco_corners.append(np.array(corners))
        charuco_ids.append(np.array(ids))

        if len(corners):
            # refine the detection
            for i, corner in enumerate(corners):
                criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_COUNT, 30, 0.1)
                cv2.cornerSubPix(image, corner,
                                winSize = (10,10),
                                zeroZone = (-1,-1),
                                criteria = criteria)
            # interpolate to find all the chessboard corners
            retval, chessboard_corners, chessboard_ids = cv2.aruco.interpolateCornersCharuco( corners, ids, image, board )
            if chessboard_corners is not None and chessboard_ids is not None:
                calib_corners.append(np.array(chessboard_corners))
                calib_ids.append(np.array(chessboard_ids))
        else:
            raise RuntimeError( "charuco_camera_calib:could not get any markers from image: {}".format(fn))

    retval, camera_matrix, dist_coeffs, rvecs, tvecs = cv2.aruco.calibrateCameraCharuco( np.array(calib_corners), np.array(calib_ids), board, size, None, None )

    new_camera_matrix, roi = cv2.getOptimalNewCameraMatrix(
        camera_matrix, dist_coeffs, size, 1, size
    )
    # map_x, map_y = cv2.initUndistortRectifyMap(
    #     camera_matrix, dist_coeffs, None, new_camera_matrix, size, cv2.CV_32FC1
    # )

    for i, fn in enumerate(fns):
        image = cv2.imread(fn, flags=cv2.IMREAD_UNCHANGED)
        image = cv2.aruco.drawDetectedMarkers(image, charuco_corners[i], charuco_ids[i])
        image = cv2.drawChessboardCorners(image, (6,6), calib_corners[i], True)
        image = cv2.undistort(image, camera_matrix, dist_coeffs)
        # image = cv2.remap(image, map_x, map_y, cv2.INTER_LINEAR)
        new_fn = fn.replace(".png", "_recified.png")
        cv2.imwrite(new_fn, image)

    return camera_matrix, dist_coeffs

该板是使用

创建的
charuco_board = calibrate.create_charuco_board( dict_name=cv2.aruco.DICT_7X7_1000, squares_x=7, squares_y=7, square_length=40, marker_size=30 )

然后依次为每个摄像机的所有图像使用glob模式调用charuco_camera_calib,由于图像的方向正确,图像翻转功能被关闭。

正如我说的, 我将不胜感激,因为我不知道这里出了什么问题,

乔纳森

*)tutorial_aruco_calibration

1 个答案:

答案 0 :(得分:0)

好吧,我终于解决了它。问题是,如果我可能滥用该术语,则输入图像太“稀疏”。木炭板应覆盖相机的整个视野​​,而不仅仅是中央。将这些图像添加到混合中可以解决该问题。