2012-06-28 9 views
20

Questa domanda è sulle funzioni OpenCV findHomography, getPerspectiveTransform & getAffineTransformfindHomography, getPerspectiveTransform, e getAffineTransform

  1. Qual è la differenza tra findHomography e getPerspectiveTransform?. La mia comprensione dalla documentazione è che getPerspectiveTransform calcola la trasformazione utilizzando 4 corrispondenze (che è il minimo richiesto per calcolare una trasformazione di omografia/prospettiva) dove findHomography calcola la trasformazione anche se si forniscono più di 4 corrispondenze (presumibilmente usando qualcosa come un minimo di quadrati metodo?). È corretto? (nel qual caso l'unico motivo per OpenCV continua a sostenere getPerspectiveTransform dovrebbe essere l'eredità?)

  2. La mia prossima preoccupazione è che io voglio sapere se c'è un equivalente per findHomography per il calcolo di una trasformazione affine? cioè una funzione che utilizza un minimi quadrati o un metodo robusto equivalente per calcolare e affinare la trasformazione. Secondo la documentazione getAffineTransform accetta solo 3 corrispondenze (che è il minimo richiesto per calcolare una trasformazione affine).

migliore,

+1

Forse [estimateRigidTransform] (http://docs.opencv.org/modules/video/doc/motion_analysis_and_object_tracking.html # estimaterigidtransform) si adatta alle tue esigenze. – cgat

risposta

24

Q # 1: A destra, il findHomography cerca di trovare il miglior trasformare tra due insiemi di punti. Usa qualcosa di più intelligente dei minimi quadrati, chiamato RANSAC, che ha la capacità di respingere i valori anomali: se almeno il 50% + 1 dei tuoi punti dati è OK, RANSAC farà del suo meglio per trovarli e creare una trasformazione affidabile.

Il getPerspectiveTransform ha un sacco di motivi utili per rimanere - è la base per findHomography, ed è utile in molte situazioni in cui si hanno solo 4 punti, e si sa che sono quelli corretti. La findHomography viene solitamente utilizzata con insiemi di punti rilevati automaticamente: è possibile trovarne molti, ma con un livello di sicurezza basso. getPerspectiveTransform è buono quando si conoscono 4 angoli, come la marcatura manuale o il rilevamento automatico di un rettangolo.

Q # 2 Non esiste un equivalente per le trasformazioni affini. Puoi utilizzare findHomography, perché le trasformazioni affini sono un sottoinsieme di omografie.

8

Concordo con tutto ciò che @vasile ha scritto. Voglio solo aggiungere alcune osservazioni:

getPerspectiveTransform() e getAffineTransform() sono pensati per lavorare su o punti (rispettivamente), che sono noti per essere corrispondenze corrette. Sulle immagini reali scattate con una fotocamera reale, è possibile ottenere mai corrispondenze accurate, non con la marcatura automatica o manuale dei punti corrispondenti.

Ci sono sempre valori anomali. Basta guardare il caso semplice di voler adattare una curva attraverso punti (ad esempio, prendere un'equazione generativa con rumore y1 = f(x) = 3.12x + gauss_noise o y2 = g(x) = 0.1x^2 + 3.1x + gauss_noise): sarà molto più facile trovare una buona funzione quadratica per stimare i punti in entrambi i casi, rispetto un buon lineare. Il quadratico potrebbe essere eccessivo, ma nella maggior parte dei casi non lo sarà (dopo aver rimosso i valori anomali), e se vuoi seguire una linea retta, è meglio essere sicuri che sia il modello giusto, altrimenti otterrai risultati inutilizzabili.

Detto questo, se si è potentemente sicuri che trasformazione affine è quella giusta, ecco un suggerimento:

  • uso findHomography, che ha RANSAC incorporato per la funzionalità, per sbarazzarsi di i valori anomali e ottenere una stima iniziale della trasformazione dell'immagine
  • selezionare 3 corrispondenze-corrispondenze corrette (corrispondenti all'omografia trovata), o riproiettare 3 punti dalla 1a immagine al 2o (utilizzando l'omografia)
  • usa quelle 3 corrispondenze (che sono il più vicino possibile per correggere come si può ottenere) in getAffineTransform()
  • avvolgere tutto ciò nel proprio findAffine() se si desidera - e voilà!
+0

C'è un modo per trovare la migliore matrice "Affine"? Voglio forzare l'ultima riga dell'omografia a essere [0, 0, 1]. – Royi

+1

@Drazick L'algoritmo che ho scritto fa quasi questo: usa findHomography per eliminare i valori anomali e in modo da non dover codificare il proprio RANSAC e quindi è possibile utilizzare getAffineTransform() su qualsiasi 3 punti per ottenere un affine da vicino a quello migliore. Alternatevley, potresti codificare il tuo algoritmo RANSAC con getAffineTransform() invece di getPerspectiveTransform() come funzione principale. – penelope

+0

@penleope, ho trovato una soluzione su come trovare la migliore trasformazione affine (l2 saggio) usando SVD in un modo simile al modo in cui si stima la migliore omografia. – Royi

3

Re Q # 2, stimaRigidTransform è l'equivalente sovracampionato di getAffineTransform. Non so se era in OCV quando è stato postato per la prima volta, ma è disponibile in 2.4.

1

Esiste una soluzione semplice per trovare la trasformazione Affine per il sistema di equazioni eccessivamente determinate.

  1. noti che, in generale, una trasformazione affine trova una soluzione al sistema sovra-determinato di equazioni lineari Ax = B utilizzando una pseudo-inversa o una tecnica simile, così

x = (AA t) -1 un t B

Inoltre, questo viene gestito nella funzionalità di base OpenCV da una semplice chiamata per risolvere (a, B, X).

  1. Familiarizzare con il codice di trasformazione affine in OpenCV/modules/ImgProc/src/imgwarp.cpp: lo fa davvero solo due cose:

    a. riordina gli ingressi per creare un sistema Ax = B;

    b. quindi chiama solve (A, B, X);

NOTA: ignorare i commenti funzione nel codice OpenCV - sono confuse e non riflettono l'ordinamento effettivo degli elementi nelle matrici. Se si sta risolvendo [u, v]’= Affine * [x, y, 1] il riarrangiamento è:

  x1 y1 1 0 0 1 
     0 0 0 x1 y1 1 
     x2 y2 1 0 0 1 
    A = 0 0 0 x2 y2 1 
     x3 y3 1 0 0 1 
     0 0 0 x3 y3 1 

    X = [Affine11, Affine12, Affine13, Affine21, Affine22, Affine23]’ 

     u1 v1 
    B = u2 v2 
     u3 v3 

Tutto quello che dovete fare è aggiungere più punti. Per fare in modo che Solve (A, B, X) funzioni su un sistema sovradeterminato, aggiungi il parametro DECOMP_SVD. Per vedere le diapositive di PowerPoint sull'argomento, usa questo link. Se desideri saperne di più sulla pseudo-inversa nel contesto della visione artificiale, la migliore fonte è: ComputerVision, vedi capitolo 15 e appendice C.

Se non sei ancora sicuro di come aggiungere altri punti vedi il mio codice qui sotto:

// extension for n points; 
cv::Mat getAffineTransformOverdetermined(const Point2f src[], const Point2f dst[], int n) 
{ 
    Mat M(2, 3, CV_64F), X(6, 1, CV_64F, M.data); // output 
    double* a = (double*)malloc(12*n*sizeof(double)); 
    double* b = (double*)malloc(2*n*sizeof(double)); 
    Mat A(2*n, 6, CV_64F, a), B(2*n, 1, CV_64F, b); // input 

    for(int i = 0; i < n; i++) 
    { 
     int j = i*12; // 2 equations (in x, y) with 6 members: skip 12 elements 
     int k = i*12+6; // second equation: skip extra 6 elements 
     a[j] = a[k+3] = src[i].x; 
     a[j+1] = a[k+4] = src[i].y; 
     a[j+2] = a[k+5] = 1; 
     a[j+3] = a[j+4] = a[j+5] = 0; 
     a[k] = a[k+1] = a[k+2] = 0; 
     b[i*2] = dst[i].x; 
     b[i*2+1] = dst[i].y; 
    } 

    solve(A, B, X, DECOMP_SVD); 
    delete a; 
    delete b; 
    return M; 
} 

// call original transform 
vector<Point2f> src(3); 
vector<Point2f> dst(3); 
src[0] = Point2f(0.0, 0.0);src[1] = Point2f(1.0, 0.0);src[2] = Point2f(0.0, 1.0); 
dst[0] = Point2f(0.0, 0.0);dst[1] = Point2f(1.0, 0.0);dst[2] = Point2f(0.0, 1.0); 
Mat M = getAffineTransform(Mat(src), Mat(dst)); 
cout<<M<<endl; 
// call new transform 
src.resize(4); src[3] = Point2f(22, 2); 
dst.resize(4); dst[3] = Point2f(22, 2); 
Mat M2 = getAffineTransformOverdetermined(src.data(), dst.data(), src.size()); 
cout<<M2<<endl; 
Problemi correlati