Понимание неискажения openCV

Я получаю изображения глубины tof camera через MATLAB. поставляемые драйверы камеры tof для вычисления координат x, y, z из изображения глубины используют функцию openCV, которая реализована в MATLAB через mex-файлы.

Но позже я больше не могу использовать эти драйверы и функции openCV, поэтому мне нужно реализовать преобразование 2d в 3d самостоятельно, включая компенсацию радиального искажения. Я уже разобрался с параметрами камеры и вычисление координат x,y,z каждого пикселя изображения глубины работает. До сих пор я решаю неявные уравнения неискажения с помощью метода Ньютона (который не очень быстр...). Но я хочу реализовать неискажение функции openCV.

... и есть моя проблема: я не очень понимаю это, и я надеюсь, что вы можете мне помочь. как оно на самом деле работает? Пытался поискать по форуму, но не нашел полезных тем по этому делу.

Привет!


person bluhub    schedule 22.02.2014    source источник


Ответы (2)


Уравнения проекции 3D-точки [X; Y; Z] на 2D-точку изображения [u; v] представлены на страница документации по калибровке камеры :

уравнения проекции opencv
(источник: opencv.org)

В случае дисторсии объектива уравнения нелинейны и зависят от 3–8 параметров (от k1 до k6, p1 и p2). Следовательно, обычно требуется нелинейный алгоритм решения (например, метод Ньютона, алгоритм Левенберга-Марквардта и т. д.), чтобы обратить такую ​​модель и оценить неискаженные координаты по искаженным. И это то, что используется за функцией undistortPoints, с настроенными параметрами, делающими оптимизацию быстрой, но немного неточной.

Однако в конкретном случае коррекции объектива изображения (в отличие от точечной коррекции) существует гораздо более эффективный подход, основанный на известном приеме повторной выборки изображения. Этот трюк заключается в том, что для того, чтобы получить допустимую интенсивность для каждого пикселя вашего целевого изображения, вы должны преобразовать координаты в целевом изображении в координаты в исходном изображении, а не наоборот, как можно было бы интуитивно ожидать. В случае коррекции дисторсии объектива это означает, что вам фактически не нужно инвертировать нелинейную модель, а просто применять ее.

В основном алгоритм функции undistort следующий. Для каждого пикселя целевого изображения с коррекцией объектива выполните:

  • Преобразуйте координаты пикселя (u_dst, v_dst) в нормализованные координаты (x', y'), используя обратную калибровочную матрицу K,
  • Примените модель искажения объектива, как показано выше, чтобы получить искаженные нормализованные координаты (x'', y''),
  • Преобразование (x'', y'') в искаженные координаты пикселей (u_src, v_src) с помощью калибровочной матрицы K,
  • Используйте выбранный вами метод интерполяции, чтобы найти интенсивность/глубину, связанную с координатами пикселя (u_src, v_src) в исходном изображении, и назначьте эту интенсивность/глубину текущему целевому пикселю.

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

person BConic    schedule 22.02.2014
comment
спасибо за ответ, я уже читал о таком подходе. но я действительно не понимаю. зачем мне коверкать и без того искаженные нормализованные координаты? при каком предположении он применяется? Не могли бы вы предоставить более подробную информацию об этом шаге? - person bluhub; 23.02.2014
comment
зачем мне коверкать и без того искаженные нормализованные координаты? › на самом деле, вы конвертируете пиксельные координаты неискаженного изображения (u_dst, v_dst) в пиксельные координаты искаженного изображения (u_src, v_src), чтобы получить интенсивность/глубину, которые должны быть назначены неискаженному пикселю. - person BConic; 23.02.2014
comment
Хорошо, спасибо .. Я думаю, я понимаю идею, стоящую за этим. но если я это сделаю, не пренебрегаю ли я определенным количеством значений глубины на границе изображения? - person bluhub; 23.02.2014
comment
Не обязательно, так как вы можете построить свое целевое изображение по своему желанию: вы можете увеличить его размер и изменить начало координат, если вы примете это во внимание при сопоставлении с нормализованными координатами. - person BConic; 23.02.2014
comment
ок спасибо пока! Для дальнейшей обработки мне просто нужны координаты x, y, z пикселей. прежде чем я решу, какое обратное моделирование я буду реализовывать, не могли бы вы рассказать мне, как работает оптимизация функции undistortPoints? - person bluhub; 23.02.2014
comment
Я упомянул об этом в своем ответе, хотя я не уверен, какой вариант нелинейной оптимизации реализован. Вы можете изучить реализацию в файле undistort.cpp из модуля imgproc. - person BConic; 23.02.2014
comment
хорошо, спасибо! Вы помните какую-нибудь (академическую) статью/справку, на которой основана настройка параметров в undistort.cpp? - person bluhub; 27.02.2014
comment
Я не думаю, что для этого есть статья, это просто настройка количества итераций и пороговой точности для итеративного метода, чтобы найти компромисс между скоростью и точностью для ваших нужд. Если вам нужна высокая точность, вы можете посмотреть code.google.com/p/ceres. -solver, легкий и мощный нелинейный решатель, с которым легко начать работу. - person BConic; 27.02.2014

Приведенный выше ответ правильный, но обратите внимание, что координаты UV находятся в пространстве экрана и центрированы вокруг (0,0) вместо реальных координат UV.

Источник: собственная повторная реализация с использованием Python/OpenGL. Код:

def correct_pt(uv, K, Kinv, ds):
   uv_3=np.stack((uv[:,0],uv[:,1],np.ones(uv.shape[0]),),axis=-1)
   [email protected]
   r=np.linalg.norm(xy_,axis=-1)
   coeff=(1+ds[0]*(r**2)+ds[1]*(r**4)+ds[4]*(r**6));
   xy__=xy_*coeff[:,np.newaxis]
   return ([email protected])[:,0:2]
person Benedikt Kantz    schedule 19.08.2020