Как правильно искажать точки, снятые с помощью камеры «рыбий глаз» в OpenCV в Python? - PullRequest
1 голос
/ 10 апреля 2020

ИНФОРМАЦИЯ:

Я откалибровал камеру и обнаружил, что внутренняя матрица камеры (K) и ее коэффициенты искажения (d) следующие:

import numpy as np
K = np.asarray([[556.3834638575809,0,955.3259939726225],[0,556.2366649196925,547.3011305411478],[0,0,1]])
d = np.asarray([[-0.05165940570900624],[0.0031093602070252167],[-0.0034036648250202746],[0.0003390345044343793]])

Отсюда я могу неискажать свое изображение, используя следующие три строки:

final_K = cv2.fisheye.estimateNewCameraMatrixForUndistortRectify(K, d, (1920, 1080), np.eye(3), balance=1.0)

map_1, map_2 = cv2.fisheye.initUndistortRectifyMap(K, d, np.eye(3), final_K, (1920, 1080), cv2.CV_32FC1)

undistorted_image = cv2.remap(image, map_1, map_2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)

Полученные неискаженные изображения выглядят правильными Левое изображение искажено, правое не искажено , но когда я пытаюсь неискажать точки изображения, используя cv2.remap(), точки не отображаются в том же месте, что и соответствующий им пиксель на изображении. Я обнаружил точки калибровочной доски на левом изображении, используя

ret, corners = cv2.findChessboardCorners(gray, (6,8),cv2.CALIB_CB_ADAPTIVE_THRESH+cv2.CALIB_CB_FAST_CHECK+cv2.CALIB_CB_NORMALIZE_IMAGE)
corners2 = cv2.cornerSubPix(gray, corners, (3,3), (-1,-1), (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.1))

, а затем переназначил эти точки следующим образом:

remapped_points = []
for corner in corners2:
    remapped_points.append(
                (map_1[int(corner[0][1]), int(corner[0][0])], map_2[int(corner[0][1]), int(corner[0][0])])
            )

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

Кроме того, я не смог получить правильные результаты, используя cv2.fisheye.undistortPoints() , У меня есть следующая функция для удаления искаженных точек:

def undistort_list_of_points(point_list, in_K, in_d):
    K = np.asarray(in_K)
    d = np.asarray(in_d)
    # Input can be list of bbox coords, poly coords, etc.
    # TODO -- Check if point behind camera?
    points_2d = np.asarray(point_list)

    points_2d = points_2d[:, 0:2].astype('float32')
    points2d_undist = np.empty_like(points_2d)
    points_2d = np.expand_dims(points_2d, axis=1)

    result = np.squeeze(cv2.fisheye.undistortPoints(points_2d, K, d))

    fx = K[0, 0]
    fy = K[1, 1]
    cx = K[0, 2]
    cy = K[1, 2]

    for i, (px, py) in enumerate(result):
        points2d_undist[i, 0] = px * fx + cx
        points2d_undist[i, 1] = py * fy + cy

    return points2d_undist

Это изображение показывает результаты при искажении с использованием вышеуказанной функции.

(это все работает в OpenCV 4.2 .0 в Ubuntu 18.04 в Python 3.6.8)

ВОПРОСЫ

Почему это переопределение координат изображения не работает должным образом? Я неправильно использую map_1 и map_2?

Почему результаты использования cv2.fisheye.undistortPoints() отличаются от результатов использования map_1 и map_2?

...