2014-04-24 17 views
11

Sto provando a verificare la calibrazione della mia fotocamera, quindi vorrei rettificare le immagini di calibrazione. Mi aspetto che ciò comporti l'utilizzo di una chiamata a warpPerspective ma non vedo una funzione ovvia che prende la matrice della telecamera, e i vettori di rotazione e di traduzione per generare la matrice prospettica per questa chiamata.OpenCV: ottieni la matrice prospettica dalla traslazione e rotazione

In sostanza, voglio eseguire la procedura descritta here (vedere in particolare le immagini verso la fine), ma a partire da un modello di fotocamera noto e posa.

Esiste una semplice funzione che richiama i parametri intrinseci ed estrinseci della telecamera e calcola la matrice prospettica per l'uso in warpPerspective?

Chiamerò warpPerspective dopo aver chiamato undistort sull'immagine.

In linea di principio, ho potuto ricavare la soluzione risolvendo il sistema di equazioni definite nella parte superiore della opencv camera calibration documentation dopo aver specificato il vincolo Z=0, ma capire che ci deve essere una routine in scatola che mi permetterà di ortorettificazione mie immagini di prova .

Nelle mie ricerche, trovo difficile guadare tutti i risultati di calibrazione stereo - Ho solo una telecamera, ma voglio rettificare l'immagine sotto il vincolo che sto guardando solo un modello di prova planare .

+0

Così, rettificare cosa si intende rimuovere gli effetti di rotazione?Significato, hai solo una vista, non due viste l'una rispetto all'altra, che vuoi correggere (allinea le linee epipolari). –

+0

@DavidNilosek sì, ho un'immagine obliqua di una serie di cerchi di calibrazione, mi piacerebbe recuperare la vista "dall'alto verso il basso". – Dave

+0

Sto cercando di pensarci, ma sfortunatamente sto per scadere. Prova a usare l'inverso della matrice di rotazione come matrice prospettica per warpPerspective, se funziona, posso scrivere qualcosa che lo spieghi un po 'meglio. –

risposta

13

In realtà non è necessario coinvolgere una telecamera ortografica. Ecco come è possibile ottenere la trasformazione prospettiva appropriata.

Se la calibrazione della telecamera utilizzando cv::calibrateCamera, si ottiene una matrice telecamera K un vettore di distorsione della lente coefficienti D per la fotocamera e, per ogni immagine che si è utilizzato, un vettore di rotazione rvec (che è possibile convertire in una matrice 3x3 R utilizzando cv::rodrigues, doc e un vettore di traduzione T. Si consideri una di queste immagini e gli associati R e T. Dopo aver chiamato cv::undistort usando i coefficienti di distorsione, l'immagine sarà come se fosse stata acquisita da una telecamera della matrice di proiezione K * [ R | T ].

Fondamentalmente (come intuito @DavidNilosek), si desidera annullare la rotazione e ottenere l'immagine come se fosse stata acquisita dalla matrice di proiezione del modulo K * [ I | -C ] dove C=-R.inv()*T è la posizione della telecamera. Per questo, si deve applicare la seguente trasformazione:

Hr = K * R.inv() * K.inv() 

L'unico potenziale problema è che l'immagine deformata potrebbe andare al di fuori della parte visibile del piano dell'immagine. Quindi, è possibile utilizzare un dizionario aggiuntivo per risolvere il problema, come segue:

 [ 1 0 |   ] 
Ht = [ 0 1 | -K*C/Cz ] 
    [ 0 0 |   ] 

dove Cz è il componente C sull'asse Oz.

Infine, con le definizioni sopra, H = Ht * Hr è una trasformazione prospettica rettificante per l'immagine considerata.

+1

Per ottenere l'immagine centrata dovevo fare quanto segue: let 'u0 = -K * C/Cz' (la parte tradotta di' Ht' sopra); spostalo di metà della dimensione dell'immagine in ingresso: 'u [0] = u0 [0] - image_size [0]', 'u [1] = u0 [1] -image_size [1]', 'u [2] = u0 [2] 'e quindi usare questo vettore' u' spostato al posto di '-K * C/Cz' nella costruzione di Ht. Questo è legato al fatto che l'origine del mio sistema di coordinate del mondo è al centro della mia griglia di calibrazione – Dave

+0

Ci sono dei tipi nei frammenti di codice del mio commento precedente: spostamento di 1/2 della dimensione dell'immagine. – Dave

+0

Bello, questa è una buona spiegazione –

1

Si tratta di un abbozzo di ciò che intendo per "risolvere il sistema di equazioni" (in Python):

import cv2 
import scipy # I use scipy by habit; numpy would be fine too 
#rvec= the rotation vector 
#tvec = the translation *emphasized text*matrix 
#A = the camera intrinsic 

def unit_vector(v): 
    return v/scipy.sqrt(scipy.sum(v*v)) 

(fx,fy)=(A[0,0], A[1,1]) 
Ainv=scipy.array([ [1.0/fx, 0.0, -A[0,2]/fx], 
        [ 0.0, 1.0/fy, -A[1,2]/fy], 
        [ 0.0, 0.0,  1.0] ], dtype=scipy.float32) 
R=cv2.Rodrigues(rvec) 
Rinv=scipy.transpose(R) 

u=scipy.dot(Rinv, tvec) # displacement between camera and world coordinate origin, in world coordinates 


# corners of the image, for here hard coded 
pixel_corners=[ scipy.array(c, dtype=scipy.float32) for c in [ (0+0.5,0+0.5,1), (0+0.5,640-0.5,1), (480-0.5,640-0.5,1), (480-0.5,0+0.5,1)] ] 
scene_corners=[] 
for c in pixel_corners: 
    lhat=scipy.dot(Rinv, scipy.dot(Ainv, c)) #direction of the ray that the corner images, in world coordinates 
    s=u[2]/lhat[2] 
    # now we have the case that (s*lhat-u)[2]==0, 
    # i.e. s is how far along the line of sight that we need 
    # to move to get to the Z==0 plane. 
    g=s*lhat-u 
    scene_corners.append((g[0], g[1])) 

# now we have: 4 pixel_corners (image coordinates), and 4 corresponding scene_coordinates 
# can call cv2.getPerspectiveTransform on them and so on.. 
+0

Sospetto che questo sia un modo inelegante per ottenere lo stesso effetto della risposta di @ AldurDisciple – Dave

Problemi correlati