2011-09-12 10 views
8

Ho 2 immagini consecutive da una fotocamera e voglio stimare la variazione di fotocamera pongono: two pictures with camera movementMatrici di trasformazione e rotazione dell'estrazione dall'omografia?

ho calcolare il flusso ottico:

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) 

e sembra giusto, la fotocamera spostato verso sinistra e verso l'alto: optical flow Ora voglio scoprire quanto la telecamera è stata spostata e ruotata. Se dichiaro la posizione della mia videocamera e quello che sta guardando:

' 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 

Come si calcola la nuova posizione e lookat?

Se sto facendo tutto questo male o se c'è un metodo migliore, qualsiasi suggerimento sarebbe molto gradito, grazie!

+0

Sto offrendo una taglia di 500 per la risposta a questa domanda http://stackoverflow.com/questions/7414809/extract-projective-homography-from-two-kinect-depth-maps – smirkingman

risposta

5

Beh, quello che stai vedendo è in termini semplici a Pythagorean theorem problem a^2 + b^2 = c^2. Tuttavia, quando si tratta di applicazioni basate su telecamere, le cose non sono molto facili da determinare con precisione. Hai trovato la metà dei dettagli di cui hai bisogno per "a", tuttavia trovare "b" o "c" è molto più difficile.

La risposta breve

Fondamentalmente non può essere fatto con una sola telecamera. Ma può essere fatto con due fotocamere.

Il prolisso Risposta (Ho pensato di spiegare in modo più approfondito, senza giochi di parole)

Cercherò di spiegare, dicono selezioniamo due punti all'interno della nostra immagine e spostare la telecamera a sinistra. Sappiamo che la distanza dalla telecamera di ciascun punto B1 è 20 mm e il punto B2 è 40 mm. Ora assumiamo che elaboriamo l'immagine e la nostra misurazione è A1 è (0,2) e A2 è (0,4) questi sono correlati a B1 e B2 rispettivamente. Ora A1 e A2 non sono misure; sono pixel di movimento.

Quello che ora dobbiamo fare è moltiplicare il cambiamento in A1 e A2 di una costante calcolata che sarà la distanza del mondo reale in B1 e B2. NOTA: Ognuno di questi è diverso in base alla misurazione B *. Tutto ciò si riferisce a Angle of view o più comunemente chiamato campo visivo nella fotografia a diverse distanze. È possibile calcolare con precisione la costante se si conoscono le dimensioni di ciascun pixel sul CCD della fotocamera e il numero f dell'obiettivo che si trova all'interno della fotocamera.

Mi aspetto che non sia così, quindi a distanze diverse è necessario posizionare un oggetto di cui si conosce la lunghezza e vedere quanti pixel occupa. Da vicino puoi usare un righello per semplificare le cose. Con queste misure. Prendi questi dati e forma una curva con una linea di miglior adattamento. Dove l'asse X sarà la distanza dell'oggetto e l'asse Y sarà la costante del rapporto tra pixel e distanza che devi moltiplicare per movimento.

Quindi, come si applica questa curva. Beh, è ​​un lavoro da indovinare. In teoria maggiore è la misurazione del movimento A * più l'oggetto è vicino alla fotocamera. Nel nostro esempio i nostri rapporti per A1> A2 dicono rispettivamente 5 mm e 3 mm e ora sappiamo che il punto B1 si è spostato di 10 mm (2x5 mm) e B2 si è spostato di 6 mm (2x6 mm). Ma diciamocelo: non sapremo mai B e non saremo mai in grado di dire se una distanza spostata è di 20 pixel di un oggetto vicino non in movimento lontano o di un oggetto lontano che si muove molto lontano. Questo è il motivo per cui Xbox Kinect utilizza sensori aggiuntivi per ottenere informazioni di profondità che possono essere legate agli oggetti all'interno dell'immagine.

Quello che si tenta di tentare con due fotocamere è che la distanza tra queste telecamere è nota, il movimento può essere calcolato in modo più accurato (efficacemente senza utilizzare un sensore di profondità). La matematica dietro questo è estremamente complessa e suggerirei di cercare alcuni articoli di giornale sull'argomento. Se vuoi che spieghi la teoria, posso tentare di farlo.

Tutta la mia esperienza deriva dalla progettazione di acquisizione video ad alta velocità e elaborazione delle immagini per il mio PHD quindi fidati, non può essere fatto con una telecamera, mi dispiace. Spero che questo aiuti.

Acclamazioni

Chris

[EDIT]

Stavo per aggiungere un commento, ma questo è più facile a causa della mole di informazioni:

Dal momento che è il Kinect Immagino che tu abbia alcune informazioni approfondite pertinenti associate a ciascun punto, se non hai bisogno di capire come ottenere questo.

L'equazione è necessario iniziare con è per il campo visivo (FOV):

O/D = I/F

Dove:

f è uguale alla lunghezza focale dell'obiettivo solitamente espressa in mm (ad esempio 18 28 30 50 sono esempi standard)

d è la distanza dell'oggetto dalla lente raccolti dai dati kinect

o è la dimensione dell'oggetto (o "campo visivo" perpendicolare e attraversata dall'asse ottico).

i è la dimensione dell'immagine (o "campo fermo" perpendicolare e bisecato dall'asse ottico).

abbiamo bisogno di calcolare i, dove o è il nostro sconosciuto così per i (che è la diagonale),

avremo bisogno la dimensione del pixel sul CCD questo a micrometri o μm è necessario trovare queste informazioni, Per sapere lo prenderemo come 14um che è standard per una camera di scansione dell'area midrange.

Quindi prima dobbiamo elaborare i dimensione orizzontale (ih) che è il numero di pixel della larghezza della telecamera moltiplicato per la dimensione del pixel ccd (useremo 640 x 320)

così: ih = 640 * 14um = 8960um

= 8960/1000 = 8.96mm 

Ora abbiamo bisogno i dimensione verticale (iv ) stesso processo, ma altezza

così: iv = (320 * 14um)/1000 = 4,48 millimetri

Ora i è trovato dai teorema di Pitagora teorema di Pitagora a^2 + b^2 = c^2

così: i = sqrt (ih^2 _ iv^2)

= 10.02 mm 

ora ci supponiamo di avere un obiettivo 28 mm. Ancora una volta, questo valore esatto dovrà essere scoperto. Così la nostra equazione è riarrangiato per darci o è:

o = (i * d)/f

Ricordati o sarà diagonale (si suppone di oggetto o punto è 50mm di distanza):

o = (10,02 millimetri * 50mm)/28mm

17.89mm 

Ora abbiamo bisogno calcolare la dimensione orizzontale (oh) e la dimensione verticale (ov) in quanto ciò ci darà la distanza per pixel spostata dall'oggetto. Ora come FOV α CCD o i è direttamente proporzionale alla o lavoreremo un rapporto k

k = I/O

= 10.02/17.89 

= 0.56 

così:

o dimensione orizzontale (oh):

oh = ih/k

= 8,96 millimetri/0.56 = 16 millimetri per pixel

o dimensione verticale (ov):

ov = iv/k

= 4,48 millimetri/0,56 = 8 mm al pixel

Ora abbiamo le costanti che richiediamo, usiamole in un esempio. Se il nostro oggetto a 50mm si sposta dalla posizione (0,0) a (2,4) quindi le misurazioni nella vita reale sono:

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

Anche in questo caso, un teorema di Pitagora: a^2 + b^2 = c^2

distanza totale = sqrt (32^2 + 32^2)

  = 45.25mm 

complicato lo so, ma una volta che hai questo in un programma è più facile. Quindi per ogni punto dovrai ripetere almeno la metà del processo come d cambierà quindi o per ogni punto esaminato.

Spero che questo ti porta sulla strada,

Acclamazioni Chris

+0

Grazie per il tempo e la risposta dettagliata. Ho la fotocamera intrinseca e quindi (penso) che il mio problema è lo stesso di avere 2 telecamere.La mia comprensione è che l'omografia esprime dove camera2 sarebbe relativa alla camera1, espressa dalle lunghezze variabili delle linee rosse tra le caratteristiche. Assumendo buone caratteristiche (e ignorando la geometria occlusa per il momento), quell'insieme di linee può solo risultare dal movimento dato. Dalla calibrazione della telecamera alla pagina 191 del libro OpenCV, sembra fattibile, ma il mio trig è troppo povero. Hai giustamente intuito, è un Kinect> ;-) – smirkingman

+0

Ciao, ti ho fornito i calcoli richiesti all'interno della risposta che richiede l'informazione di profondità da Kinect. Mi auguro che il CCD e la dimensione dei pixel siano disponibili altrove sul Web. Spero che aiuti – Chris

+0

Grazie Chris, questo rende le cose MOLTO più chiare (perché tutti gli altri lo rendono sempre così complicato?). Ho iniziato con l'immagine, sperando di usare il flusso ottico per aiutarmi a "posizionare" i dati di profondità, chiaramente non posso ricavare distanze dal mondo reale dall'immagine, come mostri. Ora ho i dati di profondità, tradotti nel mondo reale (una nuvola di punti [X, Y, Z] in millimetri). Sono ancora dopo aver trovato la traduzione + rotazione e ho capito che quello di cui ho bisogno è la regolazione del fascio. Qualche idea in cui potrei trovare un esempio in .NET (C# o VB, C non è per oggetto)? Grazie ancora :) – smirkingman

8

Per pura rotazione della macchina fotografica R = A -1 HA. Per dimostrarlo, consideriamo l'immagine per il piano delle omografie H1 = A e H2 = AR, dove A è una matrice intrinseca della telecamera. Poi H12 = H2 * H1 -1 = Un -1 RA, da cui è possibile ottenere R

traduzione fotocamera è più difficile da stimare. Se la fotocamera si traduce devi prima trovare una matrice fondamentale (non l'omografia): x T Fx = 0 e quindi convertirla in una matrice essenziale E = A T FA; Quindi è possibile scomporre E in rotazione e tradurre E = t x R, dove t x indica una matrice di prodotto vettoriale. La decomposizione non è ovvia, vedi this.

La rotazione ottenuta sarà esatta mentre il vettore di traduzione può essere trovato solo su scala. Intuitivamente questo ridimensionamento significa che dalle sole due immagini non si può veramente dire se gli oggetti sono vicini e piccoli o molto lontani e grandi. Per disambiguare possiamo usare oggetti familiari, distanza nota tra due punti, ecc.

Infine, notare che un sistema visivo umano ha un problema simile: sebbene "conosciamo" la distanza tra i nostri occhi, quando sono convergenti su l'oggetto la disparità è sempre zero e dalla sola disparità non possiamo dire quale sia la distanza. La visione umana si basa sulla triangolazione dal segnale di versione degli occhi per calcolare la distanza assoluta.

+0

Questa è una risposta molto bella e concisa, grazie! Meriterebbe molto di più +1. – jhegedus

+0

h12 è omografia o 1 wrt 2 o altrimenti i.e p1 = h12 * p2 o p2 = h12 * p1 @Vlad –

Problemi correlati