Извлечь матрицы преобразования и вращения из гомографии? - PullRequest
8 голосов
/ 12 сентября 2011

У меня есть 2 последовательных изображения с камеры, и я хочу оценить изменение положения камеры: two pictures with camera movement

Я рассчитываю оптический поток:

Const MAXFEATURES As Integer = 100
imgA = New Image(Of [Structure].Bgr, Byte)("pic1.bmp")
imgB = New Image(Of [Structure].Bgr, Byte)("pic2.bmp")
grayA = imgA.Convert(Of Gray, Byte)()
grayB = imgB.Convert(Of Gray, Byte)()
imagesize = cvGetSize(grayA)
pyrBufferA = New Emgu.CV.Image(Of Emgu.CV.Structure.Gray, Byte) _
    (imagesize.Width + 8, imagesize.Height / 3)
pyrBufferB = New Emgu.CV.Image(Of Emgu.CV.Structure.Gray, Byte) _
    (imagesize.Width + 8, imagesize.Height / 3)
features = MAXFEATURES
featuresA = grayA.GoodFeaturesToTrack(features, 0.01, 25, 3)
grayA.FindCornerSubPix(featuresA, New System.Drawing.Size(10, 10),
                       New System.Drawing.Size(-1, -1),
                       New Emgu.CV.Structure.MCvTermCriteria(20, 0.03))
features = featuresA(0).Length
Emgu.CV.OpticalFlow.PyrLK(grayA, grayB, pyrBufferA, pyrBufferB, _
                          featuresA(0), New Size(25, 25), 3, _
                          New Emgu.CV.Structure.MCvTermCriteria(20, 0.03D),
                          flags, featuresB(0), status, errors)
pointsA = New Matrix(Of Single)(features, 2)
pointsB = New Matrix(Of Single)(features, 2)
For i As Integer = 0 To features - 1
    pointsA(i, 0) = featuresA(0)(i).X
    pointsA(i, 1) = featuresA(0)(i).Y
    pointsB(i, 0) = featuresB(0)(i).X
    pointsB(i, 1) = featuresB(0)(i).Y
Next
Dim Homography As New Matrix(Of Double)(3, 3)
cvFindHomography(pointsA.Ptr, pointsB.Ptr, Homography, HOMOGRAPHY_METHOD.RANSAC, 1, 0)

, и он выглядит правильно, камера двигалась влево и вверх: optical flow Теперь я хочу выяснить, насколько камера двигалась и вращалась.Если я объявляю положение моей камеры и то, на что она смотрит:

' Create camera location at origin and lookat (straight ahead, 1 in the Z axis)
Location = New Matrix(Of Double)(2, 3)
location(0, 0) = 0 ' X location
location(0, 1) = 0 ' Y location
location(0, 2) = 0 ' Z location
location(1, 0) = 0 ' X lookat
location(1, 1) = 0 ' Y lookat
location(1, 2) = 1 ' Z lookat

Как рассчитать новую позицию и внешний вид?

Если я все делаю неправильно или если есть лучшееСпособ, любые предложения будут очень приветствоваться, спасибо!

Ответы [ 2 ]

8 голосов
/ 12 марта 2014

Для чистого вращения камеры R = A -1 HA.Чтобы доказать это, рассмотрим изображение на плоских гомографиях H1 = A и H2 = AR, где A - собственная матрица камеры.Тогда H12 = H2 * H1 -1 = A -1 RA, из которого вы можете получить R

Труднее оценить перевод камеры.Если камера переводит, вы должны сначала найти фундаментальную матрицу (не гомографию): x T Fx = 0, а затем преобразовать ее в существенную матрицу E = A T FA;Затем вы можете разложить E на вращение и перевести E = t x R, где t x означает векторную матрицу произведений.Разложение не очевидно, см. это .

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

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

5 голосов
/ 12 сентября 2011

Хорошо, что вы смотрите на это в простых терминах Задача теоремы Пифагора a ^ 2 + b ^ 2 = c ^ 2.Однако, когда дело доходит до приложений, основанных на камере, вещи не очень легко точно определить.Вы нашли половину деталей, которые вам нужны для "a", однако найти "b" или "c" намного сложнее.

Краткий ответ

В принципе это невозможно сделать с помощью одной камеры.Но это можно сделать с двумя камерами.

Долгосрочный ответ (Мысль, которую я объясню более подробно, без каламбура)

Я попробуюи объясните, скажем, мы выбрали две точки на нашем изображении и переместили камеру влево.Мы знаем, что расстояние от камеры каждой точки B1 составляет 20 мм, а точка B2 составляет 40 мм.Теперь давайте предположим, что мы обрабатываем изображение, и наши измерения составляют A1 (0,2) и A2 (0,4), они связаны с B1 и B2 соответственно.Теперь А1 и А2 не являются измерениями;это пиксели движения.

Теперь нам нужно умножить изменение A1 и A2 на вычисленную константу, которая будет расстоянием реального мира в B1 и B2.ПРИМЕЧАНИЕ: каждый из них отличается в зависимости от измерения B *.Все это относится к Углу зрения или чаще называется полем зрения в фотографии на разных расстояниях.Вы можете точно рассчитать константу, если вы знаете размер каждого пикселя на ПЗС камеры и число f объектива, которое у вас внутри камеры.

Я думаю, что это не так на разных расстоянияхВы должны поместить объект, длина которого вам известна, и посмотреть, сколько пикселей он занимает.Крупным планом вы можете использовать линейку, чтобы сделать вещи проще.С этими измерениями.Вы берете эти данные и формируете кривую с линией наилучшего соответствия.Где ось X будет расстоянием до объекта, а ось Y будет константой отношения пикселей к расстоянию, на которое вы должны умножить свое движение.

Так как же нам применить эту кривую.Ну, это угадайка.Теоретически, чем больше измерение движения A *, тем ближе объект к камере.В нашем примере наши соотношения для A1> A2 говорят 5 мм и 3 мм соответственно, и теперь мы знаем, что точка B1 сместилась на 10 мм (2x5 мм), а B2 сместилась на 6 мм (2x6 мм).Но давайте посмотрим правде в глаза - мы никогда не узнаем B, и мы никогда не сможем определить, составляет ли перемещенное расстояние 20 пикселей близкого объекта, который не движется далеко, или того, что объект далеко перемещается на большое расстояние.Вот почему такие вещи, как Xbox Kinect, используют дополнительные датчики для получения информации о глубине, которую можно привязать к объектам на изображении.

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

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

Приветствия

Крис

[EDIT]

Я собирался добавить комментарий, ноэто проще из-за большого объема информации:

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

Уравнение, с которого вам нужно начать, относится к полю зрения ( FOV ):

o / d = i / f

Где:

f равно фокусному расстоянию объектива, обычно указанному в мм (т.е. 18 28 30 50 - стандартные примеры)

d - это расстояние до объекта от объектива, полученное из данных kinect.

o - это размер объекта (или «поле зрения», перпендикулярный и разделенный пополам оптической осью).

i - размер изображения (или «ограничитель поля», перпендикулярный и разделенный пополам оптической осью).

Нам нужно вычислить i , где o - наше неизвестное значение, поэтому для i (который является диагональным измерением),

Нам понадобится размер пикселя на ПЗС, который будет в микрометрах или микронах. Вам понадобится выяснить эту информацию, поскольку мы будем считать, что она равна 14um, что является стандартным для камеры сканирования среднего диапазона.

Итак, сначала нам нужно определить размер по горизонтали ( ih ), который представляет собой количество пикселей ширины камеры, умноженное на размер пикселя ccd (мы будем использовать 640 x 320)

так: ih = 640 * 14um = 8960um

   = 8960/1000 = 8.96mm

Теперь нам нужно i вертикальный размер ( iv ) тот же процесс, но высота

так: iv = (320 * 14um) / 1000 = 4,48 мм

Теперь i находится по теореме Пифагора Теорема Пифагора a ^ 2 + b ^ 2 = c ^ 2

так: i = sqrt (ih ^ 2 _ iv ^ 2)

  = 10.02 mm

Теперь предположим, что у нас объектив 28 мм. Опять же, это точное значение нужно будет выяснить. Таким образом, наше уравнение переставлено, чтобы дать нам o :

o = (i * d) / f

Помните, o будет диагональю (предположим, что объект или точка находятся на расстоянии 50 мм):

o = (10,02 * 50 мм) / 28 мм

17.89mm

Теперь нам нужно определить o горизонтальное измерение ( oh ) и o вертикальное измерение ( ov ), так как это даст нам расстояние на пиксель, на которое переместился объект. Теперь, когда FOV α CCD или i прямо пропорционально o , мы получим соотношение k

k = ввод / вывод

= 10.02 / 17.89 

= 0.56

так:

o горизонтальный размер ( oh ):

о = ih / k

= 8,96 мм / 0,56 = 16 мм на пиксель

o вертикальный размер ( ov ):

ов = iv / k

= 4,48 мм / 0,56 = 8 мм на пиксель

Теперь у нас есть необходимые нам константы, давайте использовать их в качестве примера. Если наш объект на 50 мм перемещается из положения (0,0) в (2,4), то измерения в реальной жизни:

(2 * 16 мм, 4 * 8 мм) = (32 мм, 32 мм)

Опять же, теорема Пифагора: a ^ 2 + b ^ 2 = c ^ 2

Общее расстояние = sqrt (32 ^ 2 + 32 ^ 2)

           = 45.25mm

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

Надеюсь, это поможет вам,

Приветствие Chris

...