калибровка камеры opencv charuco не будет правильно искажаться - PullRequest
0 голосов
/ 15 апреля 2019

У меня проблемы с настройкой калибровки камеры charuco. Насколько я знаю, я все делаю правильно, но окончательные неискаженные изображения намного более искажены, чем ожидалось. Он работает с доской 4x4, но тогда выпрямляемая область слишком мала, поэтому мне нужно заставить все работать с доской 7x7. Если есть кто-то, кто может видеть, что я делаю неправильно, помощь очень ценится, я немного застрял на данный момент. Итак, вот случай:

У меня есть 4 камеры, каждая из которых должна быть откалибрована. У меня есть 11 изображений платы Чаруко 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 )

и затем вызывается charuco_camera_calib с шаблоном глобуса для всех изображений для каждой камеры по очереди, переворот изображения отключается, поскольку изображения ориентированы правильно.

Как я уже сказал, я бы сильно оценил бы любую помощь, так как я в растерянности от того, что здесь происходит не так,

Jonathan

*) tutorial_aruco_calibration

1 Ответ

0 голосов
/ 15 апреля 2019

ну, я наконец-то решил это.Проблема заключалась в том, что входные изображения были слишком «редкими», если я могу злоупотреблять этим термином.Доска Чаруко должна охватывать все поля зрения камеры, а не только центр.Добавление этих изображений в микс решило проблему.

...