web-dev-qa-db-fra.com

Comparaison de deux images avec OpenCV en Java

J'essaie de comparer deux images (déterminer si elles sont similaires ou non) en utilisant la bibliothèque OpenCV. J'ai configuré l'encapsuleur Java et trouvé plusieurs tutoriels (principalement en C/C++) que je tente de réécrire en Java. J'utilise l'approche de détection de fonctionnalités.

Le problème est que l'algorithme que j'ai actuellement ne produit aucun résultat raisonnable (il affirme que deux images similaires n'ont rien en commun et trouve des correspondances entre deux autres images complètement différentes). Quelqu'un pourrait-il suggérer comment utiliser le matcher openCV pour produire des résultats raisonnables?

Ceci est mon code pour la comparaison d'images

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);
    }
  }

Malheureusement, les algorithmes tels que SURF et SIFT n'étant pas disponibles dans l'encapsuleur Java, j'utilise donc ORB. Je n’ai que peu d’expérience en vision par ordinateur, j’essaie simplement de faire fonctionner cet algorithme de comparaison simple pour obtenir des résultats raisonnables. Je serais heureux pour toute aide!

EDIT: Mon cas d'utilisation exécute cet algorithme contre des images prises sous différents angles. J'ai mis à jour mon code pour qu'il soit mieux formaté.

Exemples d'images à comparer:

 enter image description here  enter image description here

15
Smajl

Juste mes deux cents:

  1. Il existe un accès à SURF et SIFT en Java: openCV DescriptorExtractor Reference . J'ai essayé l'implémentation de FREAK il y a trois ans et j'ai découvert qu'il y avait un changement dans le descripteur binaire lorsque openCV les transfère à Java. Il se peut que ORB soit soumis au même problème. Avez-vous comparé les données des descripteurs de c ou c ++ à celles du côté de Java?

  2. Le correcteur de force brute trouve la meilleure caractéristique correspondant à l'image de train pour CHAQUE fonctionnalité dans l'image de requête. Même si cela a l'air complètement différent. Vous devez passer au crible les allumettes et abandonner les mauvaises. Il existe plusieurs stratégies, une solution facile serait de prendre les 20% des meilleurs matchs au maximum (mais cela ne fera pas perdre TOUT). Progressive Sample Consensus a très bien fonctionné dans ma configuration.

  3. L'utilisation de fonctionnalités pour comparer la similarité des images présente des pièges. Le nombre et la qualité des fonctionnalités varient en fonction de la taille et du contenu de l'image, ce qui rend difficile la comparaison globale des images (au cas où vous voudriez savoir laquelle des deux images ressemble le plus à une référence que l'autre). Vous pouvez estimer une transformation d'une image à l'autre avec Calib3d.findHomography(obj, scene, CV_RANSAC); et utiliser une différence de pixels normalisée des zones qui se chevauchent.
5
Gilfoyle

Comme indiqué dans cette SO question , le moyen le plus simple et le plus simple consiste à comparer les histogrammes. Si votre algorithme doit uniquement fonctionner pour un ensemble de données spécifique, essayez d'utiliser différents canaux de couleur pour voir où les images de votre ensemble partagent le plus de similitudes. 

L’approche par histogramme peut sembler peu pratique, mais compte tenu de la similitude des couleurs de vos images, je pense que cela pourrait être utile.

Après avoir comparé les histogrammes de vos deux images dans Photoshop:

 histogram comparison

0
mmarkman