Нужна помощь в понимании ошибки для cv2.undistortPoints()

Я пытаюсь триангулировать точки с проектора и камеры, используя структурированный свет в OpenCV Python. В этом процессе у меня есть список кортежей, которые соответствуют один к одному между камерой и проектором. Я передаю это в cv2.undistortedPoints(), как показано ниже:

camera_normalizedPoints = cv2.undistortPoints(camera_points, camera_K, camera_d)

Однако python выдает следующую ошибку, и я не могу понять, что означает эта ошибка.

camera_normalizedPoints = cv2.undistortPoints(camera_points, camera_K, camera_d) cv2.error: /home/base/opencv_build/opencv/modules/imgproc/src/undistort.cpp:312: error: (-215) CV_IS_MAT(_src) && CV_IS_MAT(_dst) && (_src->rows == 1 || _src->cols == 1) && (_dst->rows == 1 || _dst->cols == 1) && _src->cols + _src->rows - 1 == _dst->rows + _dst->cols - 1 && (CV_MAT_TYPE(_src->type) == CV_32FC2 || CV_MAT_TYPE(_src->type) == CV_64FC2) && (CV_MAT_TYPE(_dst->type) == CV_32FC2 || CV_MAT_TYPE(_dst->type) == CV_64FC2) in function cvUndistortPoints

Любая помощь с благодарностью.

Благодарю.

1 ответ

Решение

К сожалению, документация не всегда четко описывает форму ввода в Python, и undistortPoints() еще даже нет документации по Python.

Точки ввода должны быть массивом с формой (n_points, 1, n_dimensions), Так что если у вас есть 2D координаты, они должны быть в форме (n_points, 1, 2), Или для 3D-координат они должны быть в форме (n_points, 1, 3), Это верно для большинства функций OpenCV. AFAIK, этот формат будет работать для всех функций OpenCV, в то время как некоторые функции OpenCV также будут принимать точки в форме (n_points, n_dimensions), Я считаю, что лучше всего держать все в соответствии и в формате (n_points, 1, n_dimensions),

Для ясности это означает, что массив из четырех 32-битных плавающих 2D точек будет выглядеть так:

points = np.array([[[x1, y1]], [[x2, y2]], [[x3, y3]], [[x4, y4]]], dtype=np.float32)

Если у вас есть массив, который имеет форму (n_points, n_dimensions) Вы можете расширить это с np.newaxis:

>>> points = np.array([[1, 2], [3, 4], [5, 6], [7, 8]])
>>> points.shape
(4, 2)
>>> points = points[:, np.newaxis, :]
>>> points.shape
(4, 1, 2)

или с np.expand_dims():

>>> points = np.array([[1, 2], [3, 4], [5, 6], [7, 8]])
>>> points.shape
(4, 2)
>>> points = np.expand_dims(points, 1)
>>> points.shape
(4, 1, 2)

или с различными заказами np.transpose() в зависимости от порядка ваших размеров. Например, если ваша форма (1, n_points, n_dimensions) Затем вы хотите поменять ось 0 с осью 1, чтобы получить (n_points, 1, n_dimensions), так points = np.transpose(points, (1, 0, 2)) изменил бы оси, чтобы сначала поместить ось 1, затем ось 0, затем ось 2, чтобы новая форма была правильной.


Если вы думаете, что это нечетный формат для точек, это если вы рассматриваете только список точек, но разумно, если вы думаете о точках как о координатах изображения. Если у вас есть изображение, то координаты каждой точки на изображении определяются (x, y) пара, как:

(0, 0)    (1, 0)    (2, 0)    ...
(0, 1)    (1, 1)    (2, 1)    ...
(0, 2)    (1, 2)    (2, 2)    ...
...

Здесь имеет смысл поместить каждую координату в отдельный канал двухканального массива, чтобы получить один 2D-массив x-координат и один 2D-массив y-координат, например:

Канал 0 (координаты х):

0    1    2    ...
0    1    2    ...
0    1    2    ...
...

Канал 1 (координаты y):

0    0    0    ...
1    1    1    ...
2    2    2    ...
...

Вот почему каждая координата находится на отдельном канале.


Некоторые другие функции OpenCV, которые требуют этот формат, включают cv2.transform() а также cv2.perspectiveTransform(), на который я отвечал на идентичные вопросы раньше, здесь и здесь соответственно.

Я также достигаю этой проблемы, и я беру некоторое время, чтобы исследовать, наконец, понять.

В открытой системе операция искажения выполняется перед матрицей камеры, поэтому порядок обработки следующий: image_distorted ->camera_matrix -> un-distort function->camera_matrix-> обратно к image_undistorted.

Так что вам нужно небольшое исправление и camera_K снова.

camera_normalizedPoints = cv2.undistortPoints (camera_points, camera_K, camera_d, cv2.Mat.sye (3,3), camera_K)

Forumla:

Другие вопросы по тегам