2012-06-28 35 views
20

To pytanie jest na funkcje OpenCV findHomography, getPerspectiveTransform & getAffineTransformfindHomography, getPerspectiveTransform, & getAffineTransform

  1. Jaka jest różnica między findHomography i getPerspectiveTransform?. Moje zrozumienie z dokumentacji jest takie, że getPerspectiveTransform oblicza transformację za pomocą 4 odpowiedników (która jest minimalna wymagana do obliczenia transformacji homografii/perspektywy), gdzie jako findHomography oblicza transformację, nawet jeśli podajesz więcej niż 4 odpowiedniki (prawdopodobnie używając czegoś takiego jak najmniejsze kwadraty metoda?). Czy to prawda? (w tym przypadku jedynym powodem OpenCV nadal kontynuuje wspieranie getPerspectiveTransform powinno być dziedzictwo?)

  2. Moim następnym problemem jest to, że chcę wiedzieć, czy istnieje odpowiednik findHomography obliczania pokrewieństwa transformacji? tj. funkcja wykorzystująca najmniejsze kwadraty lub równoważną, niezawodną metodę obliczania i transformacji afinicznej. Zgodnie z dokumentacją getAffineTransform przyjmuje tylko 3 odpowiedniki (co jest min wymagane do obliczenia transformacji afinicznej).

Best,

+1

Może [estimateRigidTransform] (http://docs.opencv.org/modules/video/doc/motion_analysis_and_object_tracking.html # estimaterigidtransform) pasowałoby do twoich potrzeb. – cgat

Odpowiedz

24

Q # 1: prawo, findHomography próbuje znaleźć najlepszy przekształcać pomiędzy dwoma zestawami punktów. Wykorzystuje coś mądrzejszego niż najmniejsze kwadraty, zwane RANSAC, które ma możliwość odrzucania wartości odstających - jeśli co najmniej 50% + 1 punktów danych jest w porządku, RANSAC zrobi wszystko, aby je znaleźć i zbudować niezawodną transformację.

The getPerspectiveTransform ma wiele przydatnych powodów, aby zostać - jest podstawą dla findHomography i jest przydatny w wielu sytuacjach, w których masz tylko 4 punkty, i wiesz, że są prawidłowe. FindHomography jest zwykle używana z setami punktów wykrywanych automatycznie - możesz znaleźć wiele z nich, ale z małą pewnością. getPerspectiveTransform jest dobry, gdy wybierasz na pewno 4 rogi - jak ręczne oznaczanie lub automatyczne wykrywanie prostokąta.

Q # 2 Nie ma odpowiednika dla transformacji afinicznych. Możesz użyć findHomography, ponieważ transformacje afiniczne są podzbiorem homografii.

8

Zgadzam się ze wszystkim, co napisał @vasile. Chcę tylko dodać kilka uwag:

getPerspectiveTransform() i getAffineTransform() są przeznaczone do pracy na lub punktów (odpowiednio), które są uznanych za poprawne odpowiedniki. Na prawdziwych zdjęciach wykonanych za pomocą prawdziwego aparatu fotograficznego można uzyskać zgodność z dokładnością, a nie z automatycznym ani ręcznym oznaczaniem odpowiednich punktów.

Zawsze występują wartości odstające. Wystarczy spojrzeć na prosty przypadek, który chce dopasować krzywą poprzez punkty (np. Przyjąć generatywne równanie z szumem y1 = f(x) = 3.12x + gauss_noise lub y2 = g(x) = 0.1x^2 + 3.1x + gauss_noise): znacznie łatwiej będzie znaleźć dobrą funkcję kwadratową, aby oszacować punkty w obu przypadkach, niż dobry liniowy. Kwadrat może być przesadą, ale w większości przypadków nie będzie (po usunięciu wartości odstających), a jeśli chcesz dopasować linię prostą, lepiej upewnij się, że jest to właściwy model, w przeciwnym razie uzyskasz nieprzydatne wyniki.

Powiedział, że jeśli są potężnie pewien że affine przekształcać jest słuszna, oto propozycja:

  • użycie findHomography, że ma RANSAC włączone do funkcjonalności, aby pozbyć wartości odstające i uzyskać wstępne oszacowanie transformacji obrazu: wybierz 3 poprawne dopasowania-korespondencje (pasujące do znalezionej homografii) lub prześlij 3 punkty z pierwszego obrazu na drugie (przy użyciu homografii).
  • użyj tych 3 dopasowań (które są tak bliskie, jak tylko możesz uzyskać) w getAffineTransform()
  • zawiń to wszystko w swoim własnym findAffine(), jeśli chcesz - i voila!
+0

Czy istnieje sposób, aby znaleźć najlepszą matrycę "Affine"? Chcę wymusić ostatni rząd homografii na [0, 0, 1]. – Royi

+1

@ Drazick "Algorytm", który napisałem, prawie to robi - wykorzystuje metodę findHomography, aby pozbyć się wartości odstających, dzięki czemu nie trzeba kodować własnego RANSAC, i można użyć getAffineTransform() w dowolnych 3 punktach do uzyskać zbliżone do najlepszego afinię. Alternatevley, możesz zakodować własny algorytm RANSAC z getAffineTransform() zamiast getPerspectiveTransform() jako podstawową funkcję. – penelope

+0

@penleope, znalazłem rozwiązanie, jak znaleźć najlepszą (l2 mądry) transformację afiniczną za pomocą SVD w sposób podobny do tego, jak oceniasz najlepszą homografię. – Royi

3

Re Q # 2, estimateRigidTransform jest oversampled odpowiednikiem getAffineTransform. Nie wiem, czy było to w OCV, kiedy zostało to po raz pierwszy opublikowane, ale jest dostępne w wersji 2.4.

1

Istnieje proste rozwiązanie do znalezienia transformacji afinicznej dla układu nadmiernie określonych równań.

  1. Należy zauważyć, że w ogóle afinicznych przekształcić znajduje rozwiązanie na określony układ równań liniowych Ax = B za pomocą pseudo odwrotności lub podobną techniką tak

x = (AA t) -1t B

Ponadto, jest obsługiwane w funkcji rdzenia OpenCV za pomocą prostego połączenia rozwiązania (a, B, X).

  1. zapoznać się z kodeksem affine przekształcić w OpenCV/modułów/imgproc/src/imgwarp.cpp: to naprawdę tylko dwie rzeczy:

    a. przegrupowuje dane wejściowe, aby utworzyć system Ax = B;

    b. następnie wywołuje rozwiązanie (A, B, X);

UWAGA: zignoruj ​​komentarze funkcji w kodzie openCV - są one mylące i nie odzwierciedlają rzeczywistej kolejności elementów w macierzach. Jeśli rozwiązywania [u, v]”= Afiniczna * [x, y, 1] Przegrupowanie:

  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 

Wszystko, co musisz zrobić, to dodać więcej punktów. Aby praca Solve (A, B, X) działała na nadmiernie zdeterminowanym systemie, dodaj parametr DECOMP_SVD. Aby zobaczyć powerpoint slajdy na temat, użyj tego link. Jeśli chcesz dowiedzieć się więcej o pseudoodwrocie w kontekście widzenia komputerowego, najlepszym źródłem jest: ComputerVision, patrz rozdział 15 i dodatek C.

Jeśli nadal nie jesteś pewien, jak dodać więcej punktów, zobacz mój Kod poniżej

// 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;