2016-01-13 29 views
15

Sto cercando di confrontare due immagini (determinare se sono simili o meno) utilizzando la libreria OpenCV. Ho configurato il wrapper java e ho trovato diversi tutorial (principalmente in C/C++) che sto cercando di riscrivere in Java. Sto usando l'approccio di rilevamento delle funzionalità.Confronto di due immagini con OpenCV in Java

Il problema è che l'algoritmo che attualmente ho non produce risultati ragionevoli (afferma che due immagini simili non hanno nulla in comune e trova corrispondenze tra altre due immagini che sono completamente diverse). Qualcuno potrebbe suggerire come dovrei usare il matcher openCV per produrre risultati ragionevoli?

Questo è il mio codice per il confronto delle immagini

private static void compareImages(String path1, String path2) { 
    System.out.println(path1 + "-" + path2); 

    FeatureDetector detector = FeatureDetector.create(FeatureDetector.ORB); 
    DescriptorExtractor descriptor = DescriptorExtractor.create(DescriptorExtractor.ORB); 

    DescriptorMatcher matcher = DescriptorMatcher.create(DescriptorMatcher.BRUTEFORCE_HAMMING); 

    // first image 
    Mat img1 = Imgcodecs.imread(path1, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE); 
    Mat descriptors1 = new Mat(); 
    MatOfKeyPoint keypoints1 = new MatOfKeyPoint(); 

    detector.detect(img1, keypoints1); 
    descriptor.compute(img1, keypoints1, descriptors1); 

    // second image 
    Mat img2 = Imgcodecs.imread(path2, Imgcodecs.CV_LOAD_IMAGE_GRAYSCALE); 
    Mat descriptors2 = new Mat(); 
    MatOfKeyPoint keypoints2 = new MatOfKeyPoint(); 

    detector.detect(img2, keypoints2); 
    descriptor.compute(img2, keypoints2, descriptors2); 

    // match these two keypoints sets 
    MatOfDMatch matches = new MatOfDMatch(); 
    matcher.match(descriptors1, descriptors2, matches); 

    for (DMatch m : matches.toArray()) { 
     // how to use these values to detect the similarity? They seem to be way off 
     // all of these values are in range 50-80 which seems wrong to me 
     System.out.println(m.distance); 
    } 
    } 

Purtroppo, algoritmi come SURF e SIFT non sono disponibili nella confezione java così sto usando ORB. Ho poca o nessuna esperienza con la visione artificiale, sto solo cercando di far funzionare questo semplice algoritmo di confronto per produrre risultati ragionevoli. Sarei felice per qualsiasi aiuto!

MODIFICA: Il mio caso d'uso sta eseguendo questo algoritmo contro le immagini prese da diverse angolazioni. Ho aggiornato il mio codice per essere formattato meglio.

immagini di esempio per confrontare:

enter image description here enter image description here

+0

[potrebbero essere utili] (http://stackoverflow.com/questions/15544158/error-matching-with-orb-in- android) – GPPK

+0

L'algoritmo nel collegamento sembra essere esattamente lo stesso di quello che ho qui ... produce ancora risultati molto scarsi. Vorrei solo caricare due immagini e produrre una sorta di valore che indichi la loro somiglianza – Smajl

+0

solo una nota: ho provato a ricamare due immagini con la classe 'cv :: Stitcher' che utilizza internamente' xfeatures2d :: SURF' e la stitting non è riuscita. Penso che questo significhi che è difficile identificare la sfumatura delle immagini di SURF – sturkmen

risposta

5

Solo i miei due centesimi:

  1. C'è l'accesso a SURF e SIFT in Java: openCV DescriptorExtractor Reference. Ho provato l'implementazione FREAK tre anni fa e ho scoperto che ci sono dei cambiamenti nel descrittore binario quando openCV li passa a Java. Potrebbe essere che ORB è soggetto allo stesso problema. Hai confrontato i dati dei descrittori da c o C++ a quelli sul lato java?

  2. L'uguaglianza forza bruta trova la migliore funzione di abbinamento dall'immagine del treno per OGNI caratteristica nell'immagine della query. Anche se sembra completamente diverso. Devi setacciare le partite e rilasciare quelle cattive. Esistono diverse strategie, una facile sarebbe prendere solo il 20% migliore delle partite (ma questo non diminuirà TUTTI gli outlier). Progressive Sample Consensus ha funzionato molto bene nella mia configurazione.

  3. Utilizzo di funzionalità per confrontare la somiglianza di immagine ha le insidie. Il conteggio delle caratteristiche e la qualità variano a seconda della dimensione e del contenuto dell'immagine, il che rende difficile il confronto delle immagini a livello globale (nel caso in cui voglia sapere quale delle due immagini sia più simile a un riferimento rispetto all'altra). È possibile stimare una trasformazione da un'immagine all'altra con Calib3d.findHomography(obj, scene, CV_RANSAC); e utilizzare una differenza di pixel normalizzata delle aree sovrapposte.
+0

Grazie per la risposta. Per quanto riguarda SURF e SIFT - sono elencati nell'enum degli algoritmi disponibili ma se provate ad usarli, ottenete un'eccezione "non supportata". Dovrei usare una versione precedente di OpenCV per accedervi. Sarei molto felice se potessi fornire qualche codice Java di esempio che funzioni meglio del mio perché ogni strategia per valutare le somiglianze di immagine che ho provato ha prodotto risultati molto scarsi. A questo punto, sono davvero bloccato: / – Smajl

0

Come indicato in this SO Question, il modo più semplice e diretto consiste nel confrontare gli istogrammi. Se il tuo algoritmo deve funzionare solo per un set di dati specifico, prova a utilizzare canali di colore diversi per vedere dove le immagini del tuo set condividono la maggior somiglianza.

L'approccio dell'istogramma potrebbe sembrare poco pratico, ma data la somiglianza dei colori delle immagini credo che ciò potrebbe essere di qualche utilità.

Dopo aver confrontato gli istogrammi vostri due immagini in Photoshop:

histogram comparison