Comment puis-je quantifier la différence entre deux images?

179

Voici ce que j'aimerais faire:

Je prends des photos avec une webcam à intervalles réguliers. Un peu comme une chose de laps de temps. Cependant, si rien n'a vraiment changé, c'est-à-dire que l'image se ressemble à peu près , je ne veux pas stocker le dernier instantané.

J'imagine qu'il existe un moyen de quantifier la différence, et je devrais déterminer empiriquement un seuil.

Je recherche la simplicité plutôt que la perfection. J'utilise python.

transporteur
la source

Réponses:

269

Idée générale

Option 1: chargez les deux images sous forme de tableaux (scipy.misc.imread ) et calculez une différence élément par élément (pixel par pixel). Calculez la norme de la différence.

Option 2: chargez les deux images. Calculez un vecteur de caractéristiques pour chacun d'eux (comme un histogramme). Calculez la distance entre les vecteurs d'entités plutôt que les images.

Cependant, certaines décisions doivent être prises en premier.

Des questions

Vous devez d'abord répondre à ces questions:

  • Les images ont-elles la même forme et la même dimension?

    Sinon, vous devrez peut-être les redimensionner ou les recadrer. La bibliothèque PIL vous aidera à le faire en Python.

    S'ils sont pris avec les mêmes paramètres et le même appareil, ils sont probablement les mêmes.

  • Les images sont-elles bien alignées?

    Sinon, vous souhaiterez peut-être exécuter d'abord la corrélation croisée pour trouver le meilleur alignement en premier. SciPy a des fonctions pour le faire.

    Si l'appareil photo et la scène sont fixes, les images sont susceptibles d'être bien alignées.

  • L'exposition des images est-elle toujours la même? (La luminosité / contraste est-il le même?)

    Sinon, vous voudrez peut- être normaliser les images.

    Mais attention, dans certaines situations, cela peut faire plus de mal que de bien. Par exemple, un seul pixel clair sur un fond sombre rendra l'image normalisée très différente.

  • Les informations de couleur sont-elles importantes?

    Si vous souhaitez remarquer des changements de couleur, vous aurez un vecteur de valeurs de couleur par point, plutôt qu'une valeur scalaire comme dans l'image en niveaux de gris. Vous avez besoin de plus d'attention lors de l'écriture de ce code.

  • Y a-t-il des bords distincts dans l'image? Sont-ils susceptibles de déménager?

    Si oui, vous pouvez d'abord appliquer l'algorithme de détection des contours (par exemple, calculer le gradient avec la transformée Sobel ou Prewitt, appliquer un certain seuil), puis comparer les contours de la première image aux contours de la seconde.

  • Y a-t-il du bruit dans l'image?

    Tous les capteurs polluent l'image avec une certaine quantité de bruit. Les capteurs bon marché ont plus de bruit. Vous souhaiterez peut-être appliquer une réduction du bruit avant de comparer les images. Le flou est l'approche la plus simple (mais pas la meilleure) ici.

  • Quel genre de changements voulez-vous remarquer?

    Cela peut affecter le choix de la norme à utiliser pour la différence entre les images.

    Pensez à utiliser la norme de Manhattan (la somme des valeurs absolues) ou la norme zéro (le nombre d'éléments non égal à zéro) pour mesurer à quel point l'image a changé. Le premier vous dira à quel point l'image est décalée, le second ne dira que combien de pixels diffèrent.

Exemple

Je suppose que vos images sont bien alignées, de même taille et de même forme, éventuellement avec une exposition différente. Pour plus de simplicité, je les convertis en niveaux de gris même s'il s'agit d'images couleur (RVB).

Vous aurez besoin de ces importations:

import sys

from scipy.misc import imread
from scipy.linalg import norm
from scipy import sum, average

Fonction principale, lire deux images, convertir en niveaux de gris, comparer et imprimer les résultats:

def main():
    file1, file2 = sys.argv[1:1+2]
    # read images as 2D arrays (convert to grayscale for simplicity)
    img1 = to_grayscale(imread(file1).astype(float))
    img2 = to_grayscale(imread(file2).astype(float))
    # compare
    n_m, n_0 = compare_images(img1, img2)
    print "Manhattan norm:", n_m, "/ per pixel:", n_m/img1.size
    print "Zero norm:", n_0, "/ per pixel:", n_0*1.0/img1.size

Comment comparer. img1et img2sont des tableaux 2D SciPy ici:

def compare_images(img1, img2):
    # normalize to compensate for exposure difference, this may be unnecessary
    # consider disabling it
    img1 = normalize(img1)
    img2 = normalize(img2)
    # calculate the difference and its norms
    diff = img1 - img2  # elementwise for scipy arrays
    m_norm = sum(abs(diff))  # Manhattan norm
    z_norm = norm(diff.ravel(), 0)  # Zero norm
    return (m_norm, z_norm)

Si le fichier est une image couleur, imreadrenvoie un tableau 3D, des canaux RVB moyens (le dernier axe du tableau) pour obtenir l'intensité. Pas besoin de le faire pour les images en niveaux de gris (par exemple .pgm):

def to_grayscale(arr):
    "If arr is a color image (3D array), convert it to grayscale (2D array)."
    if len(arr.shape) == 3:
        return average(arr, -1)  # average over the last axis (color channels)
    else:
        return arr

La normalisation est triviale, vous pouvez choisir de normaliser à [0,1] au lieu de [0,255]. arrest un tableau SciPy ici, donc toutes les opérations sont élémentaires:

def normalize(arr):
    rng = arr.max()-arr.min()
    amin = arr.min()
    return (arr-amin)*255/rng

Exécutez la mainfonction:

if __name__ == "__main__":
    main()

Vous pouvez maintenant mettre tout cela dans un script et exécuter deux images. Si nous comparons l'image à elle-même, il n'y a pas de différence:

$ python compare.py one.jpg one.jpg
Manhattan norm: 0.0 / per pixel: 0.0
Zero norm: 0 / per pixel: 0.0

Si nous floutons l'image et la comparons à l'original, il y a une différence:

$ python compare.py one.jpg one-blurred.jpg 
Manhattan norm: 92605183.67 / per pixel: 13.4210411116
Zero norm: 6900000 / per pixel: 1.0

PS Script compare.py complet .

Mise à jour: techniques pertinentes

Comme la question concerne une séquence vidéo, où les images sont susceptibles d'être presque les mêmes et que vous recherchez quelque chose d'inhabituel, j'aimerais mentionner quelques approches alternatives qui peuvent être pertinentes:

  • soustraction et segmentation d'arrière-plan (pour détecter les objets de premier plan)
  • flux optique clairsemé (pour détecter le mouvement)
  • comparer des histogrammes ou d'autres statistiques au lieu d'images

Je recommande fortement de jeter un œil au livre «Learning OpenCV», aux chapitres 9 (parties d'images et segmentation) et 10 (suivi et mouvement). Le premier enseigne à utiliser la méthode de soustraction d'arrière-plan, le second donne quelques informations sur les méthodes de flux optique. Toutes les méthodes sont implémentées dans la bibliothèque OpenCV. Si vous utilisez Python, je suggère d'utiliser OpenCV ≥ 2.3, et soncv2 module Python.

La version la plus simple de la soustraction d'arrière-plan:

  • apprendre la valeur moyenne μ et l'écart type σ pour chaque pixel de l'arrière-plan
  • comparer les valeurs de pixel actuelles à la plage de (μ-2σ, μ + 2σ) ou (μ-σ, μ + σ)

Des versions plus avancées prennent en compte des séries temporelles pour chaque pixel et gèrent des scènes non statiques (comme le déplacement d'arbres ou d'herbe).

L'idée du flux optique est de prendre deux images ou plus et d'attribuer un vecteur de vitesse à chaque pixel (flux optique dense) ou à certains d'entre eux (flux optique clairsemé). Pour estimer un flux optique clairsemé, vous pouvez utiliser la méthode Lucas-Kanade (elle est également implémentée dans OpenCV). Évidemment, s'il y a beaucoup de flux (moyenne élevée sur les valeurs maximales du champ de vitesse), alors quelque chose bouge dans le cadre et les images suivantes sont plus différentes.

La comparaison d'histogrammes peut aider à détecter des changements soudains entre des images consécutives. Cette approche a été utilisée dans Courbon et al, 2010 :

Similitude des images consécutives. La distance entre deux images consécutives est mesurée. S'il est trop élevé, cela signifie que la deuxième trame est corrompue et donc l'image est éliminée. La distance Kullback – Leibler , ou entropie mutuelle, sur les histogrammes des deux cadres:

$$ d (p, q) = \ somme_i p (i) \ log (p (i) / q (i)) $$

p et q sont les histogrammes des cadres est utilisé. Le seuil est fixé à 0,2.

sastanin
la source
RuntimeWarning: invalid value encountered in double_scalarsreturn (arr-amin)*255/rngValueError: array must not contain infs or NaNsz_norm = norm(diff.ravel(), 0)
J'obtiens
@BioGeek qui est si rngégal à zéro. Il suffit d'ajouter un chèque et de réglerrng = 1
haisi
76

Une solution simple:

Encodez l'image au format jpeg et recherchez un changement substantiel dans la taille du fichier .

J'ai implémenté quelque chose de similaire avec les miniatures vidéo et j'ai eu beaucoup de succès et d'évolutivité.

Keparo
la source
3
Il s'agit d'une solution très simple et très simple, bien meilleure que toute comparaison pixelisée. S'il y a un peu de bruit dans l'image de votre webcam ou si l'image est décalée ne serait-ce que d'un pixel, alors une comparaison directe détectera tous ces changements inutiles. Une approche plus robuste consisterait à calculer la transformation cosinus discrète, puis à comparer les images dans le domaine fréquentiel. L'utilisation de la compression JPEG comme celle-ci vous offre la plupart des avantages sans plonger dans la théorie de Fourier.
AndrewF
J'aime ça. Bien que d'autres solutions fonctionnent aussi, cela présente un grand avantage pour une situation courante: que faire si vous ne souhaitez pas enregistrer l'image "de base"? enregistrez simplement la taille du fichier sous forme de hachage, puis comparez uniquement les nombres avec la soustraction. Dans mon cas, j'ai 4 images, l'une d'elles est très similaire et les 3 autres sont absolument différentes. Échelle juste aux mêmes dimensions, en jpg et soustrait. Vraiment sympa.
Diego Andrés Díaz Espinoza
60

Vous pouvez comparer deux images à l'aide des fonctions de PIL .

import Image
import ImageChops

im1 = Image.open("splash.png")
im2 = Image.open("splash2.png")

diff = ImageChops.difference(im2, im1)

L'objet diff est une image dans laquelle chaque pixel est le résultat de la soustraction des valeurs de couleur de ce pixel dans la deuxième image de la première image. En utilisant l'image diff, vous pouvez faire plusieurs choses. Le plus simple est lediff.getbbox() fonction. Il vous indiquera le rectangle minimal qui contient tous les changements entre vos deux images.

Vous pouvez probablement implémenter des approximations des autres éléments mentionnés ici en utilisant également des fonctions de PIL.

elifiner
la source
2
Je veux enregistrer l'image de différence. signifie l'objet diff qui contient la différence des images. ow puis-je le sauvegarder?
Sagar
2
@Anthony vous pouvez appeler save () sur l'objet diff en spécifiant le nom de l'image. comme ceci: diff.save ("diff.png") il enregistrera l'image de différence pour vous.
Sagar
20

Deux méthodes populaires et relativement simples sont: (a) la distance euclidienne déjà suggérée, ou (b) l'intercorrélation normalisée. La corrélation croisée normalisée a tendance à être nettement plus robuste aux changements d'éclairage que la simple corrélation croisée. Wikipedia donne une formule pour l' intercorrélation normalisée . Des méthodes plus sophistiquées existent également, mais elles nécessitent un peu plus de travail.

En utilisant une syntaxe de type numpy,

dist_euclidean = sqrt (somme ((i1 - i2) ^ 2)) / i1.size

dist_manhattan = somme (abs (i1 - i2)) / i1.size

dist_ncc = somme ((i1 - moyenne (i1)) * (i2 - moyenne (i2))) / (
  (i1.size - 1) * stdev (i1) * stdev (i2))

en supposant que i1et i2sont des tableaux d'images 2D en niveaux de gris.

Monsieur Fooz
la source
3
Les fonctions de corrélation croisée des images sont intégrées à SciPy ( docs.scipy.org/doc/scipy/reference/generated/… ), et une version rapide utilisant la FFT est disponible en python stsci ( stsci.edu/resources/software_hardware/pyraf/ stsci_python )
endolith
14

Une chose triviale à essayer:

Rééchantillonnez les deux images en petites vignettes (par exemple 64 x 64) et comparez les vignettes pixel par pixel avec un certain seuil. Si les images originales sont presque les mêmes, les vignettes rééchantillonnées seront très similaires ou même exactement les mêmes. Cette méthode prend en charge le bruit qui peut survenir en particulier dans les scènes de faible éclairage. Ce sera peut-être même mieux si vous passez en niveaux de gris.

Ates Goral
la source
mais comment compareriez-vous les pixels?
transporteur
Une fois que vous avez les vignettes, vous pouvez simplement comparer les pixels un par un. Vous calculeriez la "distance" des valeurs RVB, si vous travaillez en couleur ou simplement la différence entre les tons de gris si vous êtes en niveaux de gris.
Ates Goral
1
"comparer les pixels un par un". Qu'est-ce que ça veut dire? Le test doit-il échouer si UN des 64 ^ 2 tests pixel par pixel échoue?
Federico A. Ramponi
Ce que je voulais dire par "comparer les vignettes pixel par pixel avec un certain seuil" est de proposer un algorithme flou pour comparer les pixels. Si la différence calculée (dépend de votre algorithme flou) dépasse un certain seuil, les images ne sont "pas les mêmes".
Ates Goral
1
Exemple très simple, sans «algorithme flou»: boucle parallèle à travers chaque pixel (comparez le pixel # n de l'image # 1 au pixel # n de l'image # 2), et ajoutez la différence de valeur à une variable
mk12
7

J'aborde spécifiquement la question de savoir comment calculer s'ils sont "suffisamment différents". Je suppose que vous pouvez comprendre comment soustraire les pixels un par un.

Tout d'abord, je prendrais un tas d'images sans que rien ne change, et je découvrirais la quantité maximale que tout pixel change simplement à cause des variations de la capture, du bruit dans le système d'imagerie, des artefacts de compression JPEG et des changements instantanés de l'éclairage. . Vous constaterez peut-être que des différences de 1 ou 2 bits sont à prévoir même lorsque rien ne bouge.

Ensuite, pour le test "réel", vous voulez un critère comme celui-ci:

  • idem si jusqu'à P pixels ne diffèrent pas plus de E.

Donc, peut-être, si E = 0,02, P = 1000, cela signifierait (approximativement) qu'il serait "différent" si un pixel unique change de plus de ~ 5 unités (en supposant des images 8 bits), ou si plus de 1000 les pixels avaient des erreurs du tout.

Il s'agit principalement d'une bonne technique de «triage» pour identifier rapidement des images suffisamment proches pour ne pas nécessiter un examen plus approfondi. Les images qui «échouent» peuvent alors davantage être une technique plus élaborée / coûteuse qui n'aurait pas de faux positifs si la caméra tremblait un peu, par exemple, ou était plus robuste aux changements d'éclairage.

Je lance un projet open source, OpenImageIO , qui contient un utilitaire appelé "idiff" qui compare les différences avec des seuils comme celui-ci (encore plus élaborés, en fait). Même si vous ne souhaitez pas utiliser ce logiciel, vous pouvez consulter la source pour voir comment nous l'avons fait. Elle est largement utilisée dans le commerce et cette technique de seuillage a été développée afin que nous puissions avoir une suite de tests pour les logiciels de rendu et de traitement d'image, avec des "images de référence" qui pourraient présenter de petites différences d'une plate-forme à l'autre ou lorsque nous avons apporté des modifications mineures à tha algorithmes, donc nous voulions une opération de "correspondance dans la tolérance".

Larry Gritz
la source
6

J'ai eu un problème similaire au travail, je réécrivais notre point de terminaison de transformation d'image et je voulais vérifier que la nouvelle version produisait le même ou presque le même résultat que l'ancienne version. Alors j'ai écrit ceci:

https://github.com/nicolashahn/diffimg

Qui fonctionne sur des images de même taille, et à un niveau par pixel, mesure la différence de valeurs à chaque canal: R, V, B (, A), prend la différence moyenne de ces canaux, puis fait la moyenne de la différence sur tous les pixels et renvoie un rapport.

Par exemple, avec une image 10x10 de pixels blancs, et la même image mais un pixel est devenu rouge, la différence à ce pixel est de 1/3 ou 0,33 ... (RVB 0,0,0 vs 255,0,0 ) et à tous les autres pixels est égal à 0. Avec un total de 100 pixels, 0,33 ... / 100 = une différence d'environ 0,33% dans l'image.

Je pense que cela fonctionnerait parfaitement pour le projet d'OP (je me rends compte que c'est un très vieux post maintenant, mais que je publie pour les futurs StackOverflowers qui veulent également comparer des images en python).

Nicolas
la source
5

La plupart des réponses données ne traiteront pas des niveaux d'éclairage.

Je normaliserais d'abord l'image à un niveau de lumière standard avant de faire la comparaison.

Loren Pechtel
la source
Si vous prenez des images périodiques et que vous avez des paires adjacentes différentes, vous pouvez probablement vous permettre de conserver la première après que quelqu'un a allumé les lumières.
walkytalky
5

Un autre moyen simple et agréable de mesurer la similitude entre deux images:

import sys
from skimage.measure import compare_ssim
from skimage.transform import resize
from scipy.ndimage import imread

# get two images - resize both to 1024 x 1024
img_a = resize(imread(sys.argv[1]), (2**10, 2**10))
img_b = resize(imread(sys.argv[2]), (2**10, 2**10))

# score: {-1:1} measure of the structural similarity between the images
score, diff = compare_ssim(img_a, img_b, full=True)
print(score)

Si d'autres sont intéressés par un moyen plus puissant de comparer la similitude des images, j'ai mis en place un didacticiel et une application Web pour mesurer et visualiser des images similaires à l'aide de Tensorflow.

duhaime
la source
3
Oui, skimagec'est vraiment agréable à utiliser pour cette application. J'utilise from skimage.measure import compare_ssim, compare_msebeaucoup. documents skimage.measure .
ximiki
3

Avez-vous vu l' algorithme pour trouver des images similaires ? Vérifiez-le pour voir des suggestions.

Je suggérerais une transformation en ondelettes de vos cadres (j'ai écrit une extension C pour cela en utilisant la transformation Haar); puis, en comparant les indices des plus grands facteurs d'ondelettes (proportionnellement) entre les deux images, vous devriez obtenir une approximation de similarité numérique.

tzot
la source
2

Je m'excuse s'il est trop tard pour répondre, mais depuis que j'ai fait quelque chose de similaire, j'ai pensé que je pourrais contribuer d'une manière ou d'une autre.

Peut-être qu'avec OpenCV vous pourriez utiliser la correspondance de modèles. En supposant que vous utilisez une webcam comme vous l'avez dit:

  1. Simplifier les images (seuillage peut-être?)
  2. Appliquer la correspondance de modèle et vérifier le max_val avec minMaxLoc

Astuce: max_val (ou min_val selon la méthode utilisée) vous donnera des nombres, de grands nombres. Pour obtenir la différence en pourcentage, utilisez un modèle correspondant à la même image - le résultat sera votre 100%.

Pseudo code pour illustrer:

previous_screenshot = ...
current_screenshot = ...

# simplify both images somehow

# get the 100% corresponding value
res = matchTemplate(previous_screenshot, previous_screenshot, TM_CCOEFF)
_, hundred_p_val, _, _ = minMaxLoc(res)

# hundred_p_val is now the 100%

res = matchTemplate(previous_screenshot, current_screenshot, TM_CCOEFF)
_, max_val, _, _ = minMaxLoc(res)

difference_percentage = max_val / hundred_p_val

# the tolerance is now up to you

J'espère que ça aide.

zanfranceschi
la source
1

La distance des mouvements de la Terre peut être exactement ce dont vous avez besoin. Cela peut cependant être un peu lourd à implémenter en temps réel.

shoosh
la source
Je n'ai pas vraiment l'impression que cette réponse répond bien: "Je recherche la simplicité plutôt que la perfection. J'utilise python."
PilouPili
Je pense que comme ce fil de questions reçoit beaucoup de trafic et que le titre qui attire la plupart des téléspectateurs est de savoir comment quantifier la différence entre deux images, il a de la valeur ici.
Danoram
1

Qu'en est-il du calcul de la distance Manhattan des deux images. Cela vous donne n * n valeurs. Ensuite, vous pouvez faire quelque chose comme une moyenne de ligne pour réduire à n valeurs et une fonction au-dessus pour obtenir une valeur unique.

Tobias
la source
1

J'ai eu beaucoup de chance avec des images jpg prises avec le même appareil photo sur un trépied en (1) simplifiant grandement (comme passer de 3000 pixels de large à 100 pixels de large ou même moins) (2) aplatissant chaque tableau jpg en un seul vector (3) corrélation par paires d'images séquentielles avec un algorithme de corrélation simple pour obtenir le coefficient de corrélation (4) coefficient de corrélation au carré pour obtenir r-carré (c'est-à-dire fraction de variabilité dans une image expliquée par la variation dans la suivante) (5) généralement dans mon application si r-carré <0,9, je dis que les deux images sont différentes et qu'il s'est passé quelque chose entre les deux.

C'est robuste et rapide dans mon implémentation (Mathematica 7)

Cela vaut la peine de jouer avec la partie de l'image qui vous intéresse et de vous concentrer sur cela en recadrant toutes les images dans cette petite zone, sinon un changement éloigné de la caméra mais important sera manqué.

Je ne sais pas comment utiliser Python, mais je suis sûr qu'il fait aussi des corrélations, non?

Cadran romain
la source
1

vous pouvez calculer l'histogramme des deux images, puis calculer le coefficient de Bhattacharyya , c'est un algorithme très rapide et je l'ai utilisé pour détecter les changements de plan dans une vidéo de cricket (en C en utilisant openCV)

vishalv2050
la source
Pourriez-vous calculer le coefficient sur les images elles-mêmes?
endolith
Vous devrez calculer les histogrammes pour les images (avec la taille du bac de l'histogramme selon les exigences).
vishalv2050
1

Découvrez comment les ondelettes Haar sont implémentées par isk-daemon . Vous pouvez utiliser son code C ++ imgdb pour calculer la différence entre les images à la volée:

isk-daemon est un serveur de base de données open source capable d'ajouter une recherche d'image basée sur le contenu (visuelle) à n'importe quel site Web ou logiciel lié à l'image.

Cette technologie permet aux utilisateurs de tout site Web ou logiciel lié à l'image d'esquisser sur un widget l'image qu'ils souhaitent trouver et de demander au site Web de leur répondre les images les plus similaires ou simplement de demander des photos plus similaires sur chaque page de détail d'image.

Ricardo Cabral
la source
1

J'ai eu le même problème et j'ai écrit un module python simple qui compare deux images de même taille en utilisant ImageChops d'oreiller pour créer une image diff noir / blanc et résume les valeurs de l'histogramme.

Vous pouvez obtenir ce score directement ou une valeur en pourcentage par rapport à un différentiel noir et blanc complet.

Il contient également une simple fonction is_equal, avec la possibilité de fournir un seuil flou sous (et incluant) l'image passe comme égale.

L'approche n'est pas très élaborée, mais elle est peut-être utile pour d'autres personnes aux prises avec le même problème.

https://pypi.python.org/pypi/imgcompare/

Datenhahn
la source
1

Une approche un peu plus fondée sur des principes consiste à utiliser un descripteur global pour comparer des images, comme GIST ou CENTRIST. Une fonction de hachage, comme décrit ici , fournit également une solution similaire.

Felix Goldberg
la source
1
import os
from PIL import Image
from PIL import ImageFile
import imagehash
  
#just use to the size diferent picture
def compare_image(img_file1, img_file2):
    if img_file1 == img_file2:
        return True
    fp1 = open(img_file1, 'rb')
    fp2 = open(img_file2, 'rb')

    img1 = Image.open(fp1)
    img2 = Image.open(fp2)

    ImageFile.LOAD_TRUNCATED_IMAGES = True
    b = img1 == img2

    fp1.close()
    fp2.close()

    return b





#through picturu hash to compare
def get_hash_dict(dir):
    hash_dict = {}
    image_quantity = 0
    for _, _, files in os.walk(dir):
        for i, fileName in enumerate(files):
            with open(dir + fileName, 'rb') as fp:
                hash_dict[dir + fileName] = imagehash.average_hash(Image.open(fp))
                image_quantity += 1

    return hash_dict, image_quantity

def compare_image_with_hash(image_file_name_1, image_file_name_2, max_dif=0):
    """
    max_dif: The maximum hash difference is allowed, the smaller and more accurate, the minimum is 0.
    recommend to use
    """
    ImageFile.LOAD_TRUNCATED_IMAGES = True
    hash_1 = None
    hash_2 = None
    with open(image_file_name_1, 'rb') as fp:
        hash_1 = imagehash.average_hash(Image.open(fp))
    with open(image_file_name_2, 'rb') as fp:
        hash_2 = imagehash.average_hash(Image.open(fp))
    dif = hash_1 - hash_2
    if dif < 0:
        dif = -dif
    if dif <= max_dif:
        return True
    else:
        return False


def compare_image_dir_with_hash(dir_1, dir_2, max_dif=0):
    """
    max_dif: The maximum hash difference is allowed, the smaller and more accurate, the minimum is 0.

    """
    ImageFile.LOAD_TRUNCATED_IMAGES = True
    hash_dict_1, image_quantity_1 = get_hash_dict(dir_1)
    hash_dict_2, image_quantity_2 = get_hash_dict(dir_2)

    if image_quantity_1 > image_quantity_2:
        tmp = image_quantity_1
        image_quantity_1 = image_quantity_2
        image_quantity_2 = tmp

        tmp = hash_dict_1
        hash_dict_1 = hash_dict_2
        hash_dict_2 = tmp

    result_dict = {}

    for k in hash_dict_1.keys():
        result_dict[k] = None

    for dif_i in range(0, max_dif + 1):
        have_none = False

        for k_1 in result_dict.keys():
            if result_dict.get(k_1) is None:
                have_none = True

        if not have_none:
            return result_dict

        for k_1, v_1 in hash_dict_1.items():
            for k_2, v_2 in hash_dict_2.items():
                sub = (v_1 - v_2)
                if sub < 0:
                    sub = -sub
                if sub == dif_i and result_dict.get(k_1) is None:
                    result_dict[k_1] = k_2
                    break
    return result_dict


def main():
    print(compare_image('image1\\815.jpg', 'image2\\5.jpg'))
    print(compare_image_with_hash('image1\\815.jpg', 'image2\\5.jpg', 7))
    r = compare_image_dir_with_hash('image1\\', 'image2\\', 10)
    for k in r.keys():
        print(k, r.get(k))


if __name__ == '__main__':
    main()
  • production:

    Faux
    Vrai
    image2 \ 5.jpg image1 \ 815.jpg
    image2 \ 6.jpg image1 \ 819.jpg
    image2 \ 7.jpg image1 \ 900.jpg
    image2 \ 8.jpg image1 \ 998.jpg
    image2 \ 9.jpg image1 \ 1012 .jpg

  • les exemples d'images:

    • 815.jpg
      815.jpg

    • 5.jpg
      5.jpg

admin
la source
0

Je pense que vous pouvez simplement calculer la distance euclidienne (c'est-à-dire sqrt (somme des carrés des différences, pixel par pixel)) entre la luminance des deux images, et les considérer comme égales si cela tombe sous un certain seuil empirique. Et vous feriez mieux de le faire en enveloppant une fonction C.

Federico A. Ramponi
la source
0

Il existe de nombreuses métriques pour évaluer si deux images ressemblent / à quoi elles ressemblent.

Je n'entrerai dans aucun code ici, car je pense que ce devrait être un problème scientifique, autre qu'un problème technique.

Généralement, la question est liée à la perception humaine sur les images, de sorte que chaque algorithme a son support sur les traits du système visuel humain.

Les approches classiques sont:

Prédicteur de différences visibles: un algorithme pour l'évaluation de la fidélité de l'image ( https://www.spiedigitallibrary.org/conference-proceedings-of-spie/1666/0000/Visible-differences-predictor--an-algorithm-for-the- évaluation de / 10.1117 / 12.135952.short? SSO = 1 )

Évaluation de la qualité de l'image: de la visibilité des erreurs à la similitude structurelle ( http://www.cns.nyu.edu/pub/lcv/wang03-reprint.pdf )

FSIM: Un indice de similarité des fonctionnalités pour l'évaluation de la qualité d'image ( https://www4.comp.polyu.edu.hk/~cslzhang/IQA/TIP_IQA_FSIM.pdf )

Parmi eux, SSIM (Image Quality Assessment: From Error Visibility to Structural Similarity) est le plus simple à calculer et sa surcharge est également faible, comme indiqué dans un autre article intitulé «Image Quality Assessment Based on Gradient Similarity» ( https: //www.semanticscholar .org / paper / Image-Quality-Assessment-Based-on-Gradient-Liu-Lin / 2b819bef80c02d5d4cb56f27b202535e119df988 ).

Il existe de nombreuses autres approches. Jetez un œil à Google Scholar et recherchez quelque chose comme «différence visuelle», «évaluation de la qualité de l'image», etc., si vous êtes intéressé / tenez vraiment à l'art.

cyfex
la source
0

Il existe une solution simple et rapide utilisant numpy en calculant l'erreur quadratique moyenne:

before = np.array(get_picture())
while True:
    now = np.array(get_picture())
    MSE = np.mean((now - before)**2)

    if  MSE > threshold:
        break

    before = now
Arian Soltani
la source