Высокие среднеквадратичные значения от cv2.stereoCalibrate, несмотря на низкие среднеквадратичные значения от cv2.calibrateCamera - PullRequest
0 голосов
/ 11 апреля 2020

Я пытаюсь откалибровать и исправить набор стереокамер. Для каждой камеры у меня есть 50 кадров шахматной доски в разных местах вокруг рамки изображения, например: enter image description here

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

def find_cb_corners(images, pattern_size=(9, 6), wait_time=500, show_img=False):
    # 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((np.prod(pattern_size), 3), np.float32)
    objp[:, :2] = np.indices(pattern_size).T.reshape(-1, 2)

    objpoints = []
    imgpoints = []

    for fname in images:
        img = cv2.imread(fname)
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

        # Implement findChessboardCorners here
        ret, corners = cv2.findChessboardCorners(gray, patternSize=pattern_size)

        # If found, add object points, image points (after refining them)
        if ret is True:
            objpoints.append(objp)

            cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria)
            imgpoints.append(corners)

            if show_img is True:
                # Draw and display the corners
                img = cv2.drawChessboardCorners(img, pattern_size, corners, ret)

                cv2.imshow("img", img)
                cv2.waitKey(wait_time)

    return objpoints, imgpoints

Найдя objpoints и imgpoints для левой и правой камеры, я калибрую каждую в отдельности с помощью

retval, mtx[0], dist[0], _, _ = cv2.calibrateCamera(
    objpoints, imgpoints[0], frame_left.shape[::-1], None, None, criteria=criteria
)

. При этом возвращаются среднеквадратичные ошибки повторного проецирования 0,23 и 0,24. что, как я понимаю, приемлемо. После этого я передаю найденные матрицы камеры и коэффициенты искажения в stereoCalibrate

retval, mtx_new[0], dist_new[0], mtx_new[1], dist_new[1], R, T, E, F, = cv2.stereoCalibrate(
    objpoints,
    imgpoints[0],
    imgpoints[1],
    mtx[0],
    dist[0],
    mtx[1],
    dist[1],
    frame_left.shape[::-1],
    criteria=criteria,
    flags=cv2.CALIB_USE_INTRINSIC_GUESS + cv2.CALIB_FIX_PRINCIPAL_POINT,
)

, что возвращает среднеквадратичную ошибку повторного проецирования 78, что, очевидно, является проблематичным c. Кроме того, матрицы камер, найденные из cv2.stereoCalibrate для левой камеры, не имеют смысла:

mtx[0] = [[1.20941916e+03 0.00000000e+00 6.21956811e+02]
 [0.00000000e+00 6.53373036e+02 3.72723914e+02]
 [0.00000000e+00 0.00000000e+00 1.00000000e+00]] # Left camera

mtx[1] = [[947.26614045   0.         647.57411009]
 [  0.         735.81086121 372.87329114]
 [  0.           0.           1.        ]] # Right camera

Мне трудно понять, что калибровка работает нормально для каждой камеры отдельно, но при попытке при объединении камеры получается плохо, примерно то же самое происходит, если я пытаюсь вызвать cv2.getOptimalNewCameraMatrix, то же самое происходит, то есть roi=[0, 0, 0, 0]. Я читал в Интернете, что для камер с экстремальными радиальными искажениями процедуры калибровки opencv могут дать сбой, но я не уверен, что это так.

Есть ли что-то, что я неправильно понял?

...