web-dev-qa-db-fra.com

Vérification de la similitude des images avec OpenCV

OpenCV prend-il en charge la comparaison de deux images, en renvoyant une valeur (peut-être un pourcentage) indiquant la similitude de ces images? Par exemple. 100% seraient retournés si la même image était passée deux fois, 0% seraient retournés si les images étaient totalement différentes.

J'ai déjà lu beaucoup de sujets similaires ici sur StackOverflow. J'ai aussi fait pas mal de recherches sur Google. Malheureusement, je n'ai pas pu trouver de réponse satisfaisante.

130
Boris

C'est un sujet énorme, avec des réponses de 3 lignes de code à des magazines de recherche entiers.

Je vais décrire les techniques les plus courantes et leurs résultats.

Comparer les histogrammes

Une des méthodes les plus simples et les plus rapides. Proposé il y a plusieurs décennies comme moyen de trouver des similitudes d'image. L'idée est qu'une forêt aura beaucoup de vert et un visage humain beaucoup de rose, ou autre. Donc, si vous comparez deux images avec des forêts, vous obtenez une similitude entre les histogrammes, car vous avez beaucoup de vert dans les deux.

Inconvénient: c'est trop simpliste. Une banane et une plage auront le même aspect, car elles sont toutes les deux jaunes.

Méthode OpenCV: compareHist ()

Correspondance de modèle

Un bon exemple ici matchTemplate trouve la bonne correspondance . Il convolue l'image de recherche avec celle recherchée. Il est généralement utilisé pour trouver des parties d'image plus petites dans une plus grande.

Inconvénients: il ne renvoie que de bons résultats avec des images identiques, même taille et orientation.

Méthode OpenCV: matchTemplate ()

Correspondance des fonctionnalités

Considéré comme l’un des moyens les plus efficaces de rechercher des images. Un certain nombre de caractéristiques sont extraites d’une image, de manière à garantir que les mêmes caractéristiques seront reconnues à nouveau, même lorsqu’elles sont pivotées, redimensionnées ou asymétriques. Les fonctionnalités extraites de cette manière peuvent être comparées à d'autres ensembles de fonctionnalités d'image. Une autre image présentant une proportion élevée d'éléments correspondant à la première est considérée comme représentant la même scène.

La recherche de l’homographie entre les deux ensembles de points vous permettra également de déterminer la différence relative d’angle de prise de vue entre les images originales ou la quantité de chevauchement.

Il existe un certain nombre de tutoriels/exemples OpenCV à ce sujet et une vidéo de Nice ici . Un module OpenCV complet (features2d) lui est dédié.

Inconvénients: il peut être lent. Ce n'est pas parfait.


À propos du site OpenCV Q & A , je parle de la différence entre les descripteurs de caractéristiques, qui sont excellents lorsque l'on compare des images entières et des descripteurs de texture, qui sont utilisés pour identifier des objets tels que des visages humains ou des voitures dans une image.

189
Sam

Pour faire correspondre des images identiques (même taille/orientation)

// Compare two images by getting the L2 error (square-root of sum of squared error).
double getSimilarity( const Mat A, const Mat B ) {
if ( A.rows > 0 && A.rows == B.rows && A.cols > 0 && A.cols == B.cols ) {
    // Calculate the L2 relative error between images.
    double errorL2 = norm( A, B, CV_L2 );
    // Convert to a reasonable scale, since L2 error is summed across all pixels of the image.
    double similarity = errorL2 / (double)( A.rows * A.cols );
    return similarity;
}
else {
    //Images have a different size
    return 100000000.0;  // Return a bad value
}

Source

30
Kiran

La solution de Sam devrait suffire. J'ai utilisé une combinaison de différence d'histogramme et d'appariement de modèle car aucune méthode ne fonctionnait pour moi 100% du temps. J'ai toutefois accordé moins d'importance à la méthode de l'histogramme. Voici comment j'ai implémenté un simple script python.

import cv2

class CompareImage(object):

    def __init__(self, image_1_path, image_2_path):
        self.minimum_commutative_image_diff = 1
        self.image_1_path = image_1_path
        self.image_2_path = image_2_path

    def compare_image(self):
        image_1 = cv2.imread(self.image_1_path, 0)
        image_2 = cv2.imread(self.image_2_path, 0)
        commutative_image_diff = self.get_image_difference(image_1, image_2)

        if commutative_image_diff < self.minimum_commutative_image_diff:
            print "Matched"
            return commutative_image_diff
        return 10000 //random failure value

    @staticmethod
    def get_image_difference(image_1, image_2):
        first_image_hist = cv2.calcHist([image_1], [0], None, [256], [0, 256])
        second_image_hist = cv2.calcHist([image_2], [0], None, [256], [0, 256])

        img_hist_diff = cv2.compareHist(first_image_hist, second_image_hist, cv2.HISTCMP_BHATTACHARYYA)
        img_template_probability_match = cv2.matchTemplate(first_image_hist, second_image_hist, cv2.TM_CCOEFF_NORMED)[0][0]
        img_template_diff = 1 - img_template_probability_match

        # taking only 10% of histogram diff, since it's less accurate than template method
        commutative_image_diff = (img_hist_diff / 10) + img_template_diff
        return commutative_image_diff


    if __== '__main__':
        compare_image = CompareImage('image1/path', 'image2/path')
        image_difference = compare_image.compare_image()
        print image_difference
6
Priyanshu Chauhan