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.
Réponses:
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:
Fonction principale, lire deux images, convertir en niveaux de gris, comparer et imprimer les résultats:
Comment comparer.
img1
etimg2
sont des tableaux 2D SciPy ici:Si le fichier est une image couleur,
imread
renvoie 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
):La normalisation est triviale, vous pouvez choisir de normaliser à [0,1] au lieu de [0,255].
arr
est un tableau SciPy ici, donc toutes les opérations sont élémentaires:Exécutez la
main
fonction: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:
Si nous floutons l'image et la comparons à l'original, il y a une différence:
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:
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 son
cv2
module Python.La version la plus simple de la soustraction d'arrière-plan:
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 :
la source
RuntimeWarning: invalid value encountered in double_scalars
return (arr-amin)*255/rng
ValueError: array must not contain infs or NaNs
z_norm = norm(diff.ravel(), 0)
rng
égal à zéro. Il suffit d'ajouter un chèque et de réglerrng = 1
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é.
la source
Vous pouvez comparer deux images à l'aide des fonctions de PIL .
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 le
diff.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.
la source
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,
en supposant que
i1
eti2
sont des tableaux d'images 2D en niveaux de gris.la source
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.
la source
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:
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".
la source
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).
la source
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.
la source
Un autre moyen simple et agréable de mesurer la similitude entre deux images:
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.
la source
skimage
c'est vraiment agréable à utiliser pour cette application. J'utilisefrom skimage.measure import compare_ssim, compare_mse
beaucoup. documents skimage.measure .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.
la source
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:
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:
J'espère que ça aide.
la source
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.
la source
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.
la source
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?
la source
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)
la source
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:
la source
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/
la source
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.
la source
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
5.jpg
la source
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.
la source
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.
la source
Il existe une solution simple et rapide utilisant numpy en calculant l'erreur quadratique moyenne:
la source