Извлечь матрицы преобразования и вращения из гомографии?

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

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

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)

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

' 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

Как мне рассчитать новую позицию и взгляд?

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


person smirkingman    schedule 12.09.2011    source источник
comment
Я предлагаю награду в размере 500 за ответ на этот вопрос stackoverflow.com/questions/7414809/   -  person smirkingman    schedule 14.09.2011


Ответы (2)


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

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

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

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

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

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

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

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

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

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

Ваше здоровье

Крис

[РЕДАКТИРОВАТЬ]

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

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

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

o / d = i / f

Где:

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

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

o - размер объекта (или "поле зрения", перпендикулярное оптической оси и деленное на нее пополам).

i - размер изображения (или "полевой упор", перпендикулярный оптической оси и деленный на нее пополам).

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

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

Итак, сначала нам нужно определить i горизонтальный размер (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

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

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

= 10.02 / 17.89 

= 0.56

so:

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

ой = ih / k

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

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

ov = iv / k

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

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

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

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

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

           = 45.25mm

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

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

Ура Крис

person Chris    schedule 12.09.2011
comment
Спасибо за то, что нашли время и за подробный ответ. У меня есть встроенная камера, и поэтому (я думаю) моя проблема такая же, как и с двумя камерами. Насколько я понимаю, гомография выражает то, где camera2 будет относительно camera1, выраженная различной длиной красных линий между функциями. Предполагая хорошие характеристики (и игнорируя на данный момент закрытую геометрию), этот набор линий может быть результатом только данного движения. Судя по калибровке камеры на странице 191 книги OpenCV, это кажется выполнимым, но мой триггер слишком плох. Вы правильно догадались, это Kinect ›;-) - person smirkingman; 12.09.2011
comment
Привет, я предоставил вам необходимые вычисления в ответе, для которого требуется информация о глубине от Kinect. Я надеюсь, что ПЗС-матрица и размер пикселя доступны где-нибудь в Интернете. Надеюсь, поможет - person Chris; 13.09.2011
comment
Спасибо, Крис, это делает вещи НАМНОГО яснее (почему все остальные всегда так усложняют?). Я начал с изображения, надеясь использовать оптический поток, чтобы помочь мне «позиционировать» данные глубины, очевидно, что я не могу получить реальные расстояния от изображения, как вы показываете. Теперь у меня есть данные о глубине, переведенные в реальный мир (облако точек [X, Y, Z] в миллиметрах). Я все еще нахожу перевод + вращение и понимаю, что мне нужна настройка пакета. Есть идеи, где я мог бы найти пример в .NET (C # или VB, C не по делу)? Еще раз спасибо :) - person smirkingman; 13.09.2011
comment
Мне действительно нужно решение этой проблемы. Я назначил награду за ответ на этот вопрос stackoverflow.com/questions/4520865 / - person smirkingman; 13.09.2011
comment
Привет, я посмотрю на это, и если найду ответ, я дам вам знать, но я не уверен, что смогу вам помочь, извините, позаботьтесь - person Chris; 13.09.2011
comment
Попробуйте этот документ, я думаю, он должен относиться к вашей работе, и быстрое сканирование может дать вам несколько подходов к решению, а информация о проективных преобразованиях кажется полезной graphics.cs.wisc.edu/Papers/1997/Gle97/trackFinal.pdf - person Chris; 14.09.2011
comment
Я предлагаю награду в размере 500 за ответ на этот аналогичный вопрос stackoverflow.com/questions/7414809/ - person smirkingman; 14.09.2011

Для чистого поворота камеры 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 означает матрицу векторного произведения. Разложение неочевидно, см. это.

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

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

person Vlad    schedule 12.03.2014
comment
Это очень хороший и лаконичный ответ, спасибо! Он заслужил бы гораздо больше +1. - person jhegedus; 10.03.2015
comment
h12 - это гомография или 1 по 2 или иначе, т.е. p1 = h12 * p2 или p2 = h12 * p1 @Vlad - person Garvita Tiwari; 12.09.2016
comment
Могу я спросить, что на самом деле означает до масштабирования? Означает ли это, что масштаб считается единым? - person Färid Alijani; 14.06.2019