вычисление внешней матрицы с помощью opencv - PullRequest
2 голосов
/ 18 марта 2019

Я использую opencv для калибровки моей веб-камеры.Итак, что я сделал, так это закрепил мою веб-камеру на буровой установке, чтобы она оставалась статичной, и я использовал шаблон калибровки шахматной доски, переместил его перед камерой и использовал обнаруженные точки для вычисления калибровки.Итак, это то, что мы можем найти во многих примерах opencv (https://docs.opencv.org/3.1.0/dc/dbb/tutorial_py_calibration.html)

). Это дает мне встроенную матрицу камеры и компонент вращения и перемещения для отображения каждого из этих видов шахматной доски из пространства шахматной доски в мир.пробел.

Однако меня интересует глобальная внешняя матрица, т. е. после того, как я удалил шахматную доску, я хочу иметь возможность указать точку на сцене изображения, т. е. x, y, ее высоту идает мне положение в мировом пространстве. Насколько я понимаю, для этого мне нужна как внутренняя, так и внешняя матрицы. Как следует отсюда вычислять внешнюю матрицу? Могу ли я использовать измерения, которые я уже собрал изШаг калибровки шахматной доски для вычисления внешней матрицы?

1 Ответ

2 голосов
/ 21 марта 2019

Позвольте мне поместить некоторый контекст. Рассмотрим следующую картину (от https://docs.opencv.org/2.4/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html):

enter image description here

К камере «прикреплена» жесткая система отсчета (Xc, Yc, Zc). Успешная калибровка , которую вы успешно выполнили, позволяет преобразовать точку (Xc, Yc, Zc) в ее проекцию на изображении (u, v) и точку (u, v) на изображении в луч в (Xc, Yc, Zc) (вы можете получить его только с коэффициентом масштабирования).

На практике вы хотите поместить камеру во внешнюю «мировую» систему отсчета, назовем ее (X, Y, Z). Затем происходит жесткое преобразование, представленное матрицей вращения R и вектором перевода T , таким что:

|Xc|    |X|
|Yc|= R |Y| + T
|Zc|    |Z|

Это внешняя калибровка (которую можно записать также в виде матрицы 4x4, это то, что вы называете внешней матрицей).

Теперь ответ. Чтобы получить R и T , вы можете сделать следующее:

  1. Исправьте свою систему отсчета мира, например, земля может быть плоскостью (x, y), и выберите для нее начало координат.

  2. Установите некоторые точки с известными координатами в этой системе отсчета, например, точки в квадратной сетке в полу.

  3. Сделайте снимок и получите соответствующие координаты 2D-изображения.

  4. Используйте solvePnP для получения поворота и перемещения со следующими параметрами:

    • objectPoints: трехмерные точки в системе отсчета мира.
    • imagePoints: соответствующие 2D точки на изображении в том же порядке , что и objectPoints.
    • cameraMatris: встроенная матрица, которую вы уже имеете.
    • distCoeffs: коэффициенты искажения, которые у вас уже есть.
    • rvec , tvec : это будут выходы.
    • useExtrinsicGuess: false
    • flags: вы можете использовать CV_ITERATIVE
  5. Наконец, получите R от rvec с функцией Родригес .

Вам понадобится как минимум 3 неколлинеарных точки с соответствующими 3D-2D координатами, чтобы решение executePnP ( link ), но чем больше, тем лучше. Чтобы получить очки хорошего качества, вы можете напечатать большой рисунок шахматной доски, положить его ровно на пол и использовать в качестве сетки. Важно то, что рисунок не слишком мал на изображении (чем больше, тем стабильнее будет ваша калибровка).

И, очень важно : для внутренней калибровки вы использовали шахматную фигуру с квадратами определенного размера, но вы сказали алгоритму (который выполняет тип executePnP для каждого шаблона), что размер каждого квадрата составляет 1 . Это не является явным, но выполняется в строке 10 примера кода, где сетка построена с координатами 0,1,2, ...:

objp [:,: 2] = np.mgrid [0: 7,0: 6] .T.reshape (-1,2)

И масштаб мира для внешней калибровки должен соответствовать этому, поэтому у вас есть несколько возможностей:

  1. Используйте тот же масштаб, например, используя ту же сетку или измеряя координаты вашей "мировой" плоскости в том же масштабе. В этом случае ваш «мир» не будет в правильном масштабе.

  2. Рекомендуется: повторить внутреннюю калибровку с правильной шкалой, что-то вроде:

    objp [:,: 2] = (size_of_a_square * np.mgrid [0: 7,0: 6]). T.reshape (-1,2)

    Где size_of_a_square - это реальный размер квадрата.

  3. (Не сделал этого, но теоретически возможно, сделайте это, если вы не можете сделать это 2) Повторно используйте внутреннюю калибровку, масштабируя fx и fy. Это возможно, потому что камера видит все с точностью до масштабного коэффициента, и заявленный размер квадрата только изменяет fx и fy (и T в позе для каждого квадрата, но это другая история). Если фактический размер квадрата равен L , замените fx и fy на L fx и L fy перед вызовом solvePnP.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...