2013-03-04 16 views
6

Próbuję utworzyć program C++, w którym na liście znajduje się wiele obrazów w porównaniu do jednego obrazu wejściowego. Mam wszystko działa, a program tworzy mecze DMatch.OpenCV: Porównanie wielu obrazów za pomocą ORB

Teraz próbuję ustalić, która z listy obrazów porównywanych z obrazem źródłowym najlepiej pasuje. Najpierw próbowałem to zrobić, porównując po prostu liczbę dopasowań między obrazami, ale problem polega na tym, że wygenerowany obraz ma wiele kluczowych punktów; oni również mają dużo meczów, przynajmniej w moim programie.

Jak zatem określić, która z obrazów najlepiej pasuje do obrazu źródłowego? Używam tej pętli określić mecze, ale to naprawdę nie działa:

vector< vector<DMatch> > filteredMatches; 
vector<int> goodIds; 
Ptr<DescriptorMatcher> matcher(new BFMatcher(NORM_HAMMING, false)); 

printf("bad matches: "); 

for(size_t i = 0; i < images.size();i++){ 
    vector<DMatch> matches, good_matches; 

    matcher->clear(); 
    matcher->match(images[i], tex_des, matches); 
    if(matches.size() < 8){ 
     printf("F%d,", (int)i + 1); 
     continue; 
    } 

    double min_dist = 100; 

    for(size_t j = 0; j < matches.size(); j++){ 
     double dist = matches[j].distance; 
     if(dist < min_dist) 
      min_dist = dist; 
    } 

    if(min_dist > 50.0){ 
     printf("D%d,", (int)i + 1); 
     continue; 
    } 

    double good_dist = min_dist * 3; 
    for(size_t j = 0; j < matches.size(); j++){ 
     if(matches[j].distance < good_dist) 
      good_matches.push_back(matches[j]); 
    } 

    size_t size = good_matches.size(); 
    if(size < 8){ 
     printf("M%d,", (int)i + 1); 
     continue; 
    } 

    vector<Point2f> srcPoints(size); 
    vector<Point2f> dstPoints(size); 

    for(size_t j = 0; j < size; j++){ 
     srcPoints[j] = destination[good_matches[j].trainIdx].pt;  
     dstPoints[j] = keyPoints[i][good_matches[j].queryIdx].pt; 
    } 

    vector<unsigned char> inliersMask(srcPoints.size()); 
    Mat H = findHomography(srcPoints, dstPoints, CV_FM_RANSAC, 3.0, inliersMask); 

    vector<DMatch> inliers; 
    for(size_t j = 0; j < inliersMask.size(); j++){ 
     if(inliersMask[j]){ 
      inliers.push_back(good_matches[j]); 
     } 
    } 
    if(inliers.size() < 4){ 
     printf("S%d,", (int)i + 1); 
     continue; 
    } 

    filteredMatches.push_back(inliers); 
    goodIds.push_back((int)i); 

    H.release(); 
} 

printf(" good matches: "); 

int best = -1; 
int amount = 0; 
for(size_t i = 0; i < filteredMatches.size(); i++){ 
    int size = (int)filteredMatches.at(i).size(); 
    if(size < 8) continue; 

    printf("%d,", goodIds[i] + 1); 

    if(amount < size){ 
     amount = size; 
     best = i; 
    } 
} 

if(best >= 0) printf(" best match on image: %d, keypoints: %d, ", goodIds[best] + 1, amount); 

Jeśli ktoś może wskazać mi funkcji lub logiką muszę używać będę bardzo wdzięczny!

+0

Co to jest problem z powiedzeniem "Mecz z największą liczbą inline to mój najlepszy mecz."? –

+0

To była pierwsza rzecz, o której myślałem, ale kiedy spróbowałem, nie uzyskałem dokładnych wyników. – tversteeg

+0

OK, więc obrazy (nawet te fałszywe) są całkiem podobne, jak sądzę. Jaka jest dokładność, jeśli bierzesz średnią odległość wszystkich meczów lub wszystkich inklosów? Czy możesz umieścić przykładowe zdjęcia, jeśli to się nie powiedzie? –

Odpowiedz

0

krótki poszukiwanie problemu dostarczył mi następujący wpis w sekcjach OpenCV odpowiedź:

/CV Answer forum

co wydaje się dostarczyć odpowiedzi na pytania, które wydają się mieć. Aby odfiltrować wyniki otrzymane zgodnie z sugestią w odpowiedzi, przyjrzę się algorytmowi RANSAC, aby znaleźć najlepsze wyniki w doborze meczu.

RANSAC desctiption Wikipedia

Przynajmniej to powinien wskazać we właściwym kierunku.

+0

Jeśli spojrzysz na mój kod, zobaczysz, że już korzystam z RANSAC. – tversteeg

0

To zależy od tego, jaki obraz znajduje się na liście. Nie możesz mieć jednego rozwiązania dla każdego problemu ze wzrokiem na świecie. Na przykład projekt, nad którym pracuję, musi rozpoznawać materiał na zdjęciach ścian. Nie można po prostu porównać go z innym obrazem ściany z innym materiałem i mieć nadzieję na dopasowanie.

W moim przypadku potrzebowałem stworzyć deskryptory. Descriptors to algorytm, którego wartość wyjściowa może być porównywana z inną wartością innego obrazu. Istnieje wiele deskryptorów dostępnych już w openCV takich jak LBP, SURF itp. Mówiąc prościej, nie porównujesz już obrazu, porównujesz wartość wyjściową deskryptora obrazu 1 z wartością deskryptora wszystkich obraz na liście.

Musisz wybrać deskryptory używane przez twoje oczy/mózg, aby znaleźć dopasowanie w prawdziwym życiu. Na przykład, jeśli dopasowanie jest oparte na kolorze, można użyć CLD lub DCD. Jeśli dopasowanie jest oparte na fakturze, użyj LBP. Możesz również zrobić to, co zrobiłem w moim projekcie i użyć wielu deskryptorów i użyć uczenia maszynowego z wyszkolonymi algorytmami danych, aby znaleźć najlepsze dopasowanie.

Podsumowując, nie ma srebrnej kuli, która naprawi wszystkie problemy ze wzrokiem. Musisz dostosować swoje rozwiązanie do problemu.

Mam nadzieję, że pomoże!

1

Nie ma żadnej prostej odpowiedzi. Aby uzyskać lepsze wyniki, musisz zaimplementować pewien rodzaj transformacji i tworzyć klastrowanie na przekształconej mapie, zamiast tylko sumować odległości. To trudne, a nawet publishable.

W przeciwnym razie konieczne będzie stosowanie bardziej praktycznych technik, takich jak filtrowanie wymiarów i histogramów. Możesz rzucić okiem na OpenCV's stitcher, wyizolować moduł, który cię interesuje, i dostosować kod źródłowy do swoich potrzeb.

Powiązane problemy