Folgendes möchte ich tun:
Ich fotografiere in regelmäßigen Abständen mit einer Webcam. Irgendwie wie eine Zeitraffersache. Wenn sich jedoch nichts wirklich geändert hat, das heißt, das Bild sieht ziemlich gleich aus, möchte ich nicht den neuesten Schnappschuss speichern.
Ich stelle mir vor, es gibt eine Möglichkeit, den Unterschied zu quantifizieren, und ich müsste empirisch einen Schwellenwert bestimmen.
Ich suche eher nach Einfachheit als nach Perfektion. Ich benutze Python.
Antworten:
Grund Idee
Option 1: Laden Sie beide Bilder als Arrays (
scipy.misc.imread
) und berechnen Sie eine elementweise Differenz (Pixel für Pixel). Berechnen Sie die Norm der Differenz.Option 2: Laden Sie beide Bilder. Berechnen Sie für jeden einen Merkmalsvektor (wie ein Histogramm). Berechnen Sie den Abstand zwischen Merkmalsvektoren anstelle von Bildern.
Zunächst müssen jedoch einige Entscheidungen getroffen werden.
Fragen
Sie sollten diese Fragen zuerst beantworten:
Haben Bilder die gleiche Form und Dimension?
Wenn nicht, müssen Sie möglicherweise die Größe ändern oder sie zuschneiden. Die PIL-Bibliothek hilft dabei in Python.
Wenn sie mit denselben Einstellungen und demselben Gerät aufgenommen werden, sind sie wahrscheinlich gleich.
Sind die Bilder gut ausgerichtet?
Wenn nicht, möchten Sie möglicherweise zuerst eine Kreuzkorrelation ausführen, um zuerst die beste Ausrichtung zu finden. SciPy hat Funktionen, um dies zu tun.
Wenn die Kamera und die Szene stillstehen, sind die Bilder wahrscheinlich gut ausgerichtet.
Ist die Belichtung der Bilder immer gleich? (Ist Helligkeit / Kontrast gleich?)
Wenn nicht, möchten Sie möglicherweise Bilder normalisieren .
Aber seien Sie vorsichtig, in manchen Situationen kann dies mehr falsch als gut sein. Beispielsweise macht ein einzelnes helles Pixel auf einem dunklen Hintergrund das normalisierte Bild sehr unterschiedlich.
Ist Farbinformation wichtig?
Wenn Sie Farbänderungen bemerken möchten, haben Sie einen Vektor mit Farbwerten pro Punkt anstelle eines Skalarwerts wie im Graustufenbild. Sie benötigen mehr Aufmerksamkeit beim Schreiben eines solchen Codes.
Gibt es deutliche Kanten im Bild? Bewegen sie sich wahrscheinlich?
Wenn ja, können Sie zuerst den Kantenerkennungsalgorithmus anwenden (z. B. den Gradienten mit Sobel- oder Prewitt-Transformation berechnen, einen bestimmten Schwellenwert anwenden) und dann die Kanten des ersten Bildes mit den Kanten des zweiten Bilds vergleichen.
Gibt es Rauschen im Bild?
Alle Sensoren verschmutzen das Bild mit etwas Rauschen. Kostengünstige Sensoren haben mehr Rauschen. Möglicherweise möchten Sie eine Rauschunterdrückung anwenden, bevor Sie Bilder vergleichen. Unschärfe ist hier der einfachste (aber nicht der beste) Ansatz.
Welche Art von Änderungen möchten Sie bemerken?
Dies kann sich auf die Wahl der Norm auswirken, die für den Unterschied zwischen Bildern verwendet werden soll.
Verwenden Sie die Manhattan-Norm (die Summe der absoluten Werte) oder die Null-Norm (die Anzahl der Elemente ungleich Null), um zu messen, wie stark sich das Bild geändert hat. Ersteres zeigt an, um wie viel das Bild abweicht, letzteres zeigt nur, wie viele Pixel sich unterscheiden.
Beispiel
Ich gehe davon aus, dass Ihre Bilder gut ausgerichtet sind, dieselbe Größe und Form haben, möglicherweise mit unterschiedlicher Belichtung. Der Einfachheit halber konvertiere ich sie in Graustufen, auch wenn es sich um Farbbilder (RGB) handelt.
Sie benötigen diese Importe:
Hauptfunktion, zwei Bilder lesen, in Graustufen konvertieren, Ergebnisse vergleichen und drucken:
Wie zu vergleichen.
img1
undimg2
sind hier 2D SciPy Arrays:Wenn es sich bei der Datei um ein Farbbild handelt, wird
imread
ein 3D-Array mit durchschnittlichen RGB-Kanälen (der letzten Array-Achse) zurückgegeben, um die Intensität zu erhalten. Für Graustufenbilder (z. B..pgm
) ist dies nicht erforderlich :Die Normalisierung ist trivial. Sie können auch die Normalisierung auf [0,1] anstelle von [0,255] wählen.
arr
ist hier ein SciPy-Array, daher sind alle Operationen elementweise:Führen Sie die
main
Funktion aus:Jetzt können Sie dies alles in ein Skript einfügen und zwei Bilder ausführen. Wenn wir das Bild mit sich selbst vergleichen, gibt es keinen Unterschied:
Wenn wir das Bild verwischen und mit dem Original vergleichen, gibt es einen Unterschied:
PS Das gesamte Skript compare.py .
Update: relevante Techniken
Da es sich bei der Frage um eine Videosequenz handelt, bei der die Frames wahrscheinlich fast gleich sind und Sie nach etwas Ungewöhnlichem suchen, möchte ich einige alternative Ansätze erwähnen, die relevant sein können:
Ich empfehle dringend, das Buch „Learning OpenCV“ in den Kapiteln 9 (Bildteile und Segmentierung) und 10 (Verfolgung und Bewegung) zu lesen. Ersteres lehrt die Verwendung der Hintergrundsubtraktionsmethode, letzteres gibt einige Informationen zu optischen Flussmethoden. Alle Methoden sind in der OpenCV-Bibliothek implementiert. Wenn Sie Python verwenden, empfehle ich die Verwendung von OpenCV ≥ 2.3 und seines
cv2
Python-Moduls.Die einfachste Version der Hintergrundsubtraktion:
In fortgeschritteneren Versionen werden Zeitreihen für jedes Pixel berücksichtigt und nicht statische Szenen (wie sich bewegende Bäume oder Gras) verarbeitet.
Die Idee des optischen Flusses besteht darin, zwei oder mehr Bilder aufzunehmen und jedem Pixel (dichter optischer Fluss) oder einigen von ihnen (geringer optischer Fluss) einen Geschwindigkeitsvektor zuzuweisen. Um den spärlichen optischen Fluss abzuschätzen, können Sie die Lucas-Kanade-Methode verwenden (sie ist auch in OpenCV implementiert). Wenn viel Fluss fließt (hoher Durchschnitt über den Maximalwerten des Geschwindigkeitsfelds), bewegt sich offensichtlich etwas im Rahmen, und nachfolgende Bilder sind unterschiedlicher.
Der Vergleich von Histogrammen kann helfen, plötzliche Änderungen zwischen aufeinanderfolgenden Bildern zu erkennen. Dieser Ansatz wurde in Courbon et al., 2010, verwendet :
quelle
RuntimeWarning: invalid value encountered in double_scalars
auf Linie 44 (return (arr-amin)*255/rng
) und eineValueError: array must not contain infs or NaNs
auf Linie 30 (z_norm = norm(diff.ravel(), 0)
)rng
gleich Null ist.rng = 1
Eine einfache Lösung:
Codieren Sie das Bild als JPEG und achten Sie auf eine wesentliche Änderung der Dateigröße .
Ich habe etwas Ähnliches mit Video-Miniaturansichten implementiert und hatte viel Erfolg und Skalierbarkeit.
quelle
Sie können zwei Bilder mit Funktionen von PIL vergleichen .
Das Diff-Objekt ist ein Bild, in dem jedes Pixel das Ergebnis der Subtraktion der Farbwerte dieses Pixels im zweiten Bild vom ersten Bild ist. Mit dem Diff-Bild können Sie verschiedene Dinge tun. Das einfachste ist die
diff.getbbox()
Funktion. Es zeigt Ihnen das minimale Rechteck, das alle Änderungen zwischen Ihren beiden Bildern enthält.Sie können wahrscheinlich auch Approximationen der anderen hier erwähnten Dinge implementieren, indem Sie Funktionen von PIL verwenden.
quelle
Zwei beliebte und relativ einfache Methoden sind: (a) der bereits vorgeschlagene euklidische Abstand oder (b) normalisierte Kreuzkorrelation. Die normalisierte Kreuzkorrelation ist gegenüber Lichtänderungen deutlich robuster als die einfache Kreuzkorrelation. Wikipedia gibt eine Formel für die normalisierte Kreuzkorrelation an . Es gibt auch ausgefeiltere Methoden, die jedoch viel mehr Arbeit erfordern.
Unter Verwendung einer numpy-ähnlichen Syntax
unter der Annahme, dass
i1
undi2
2D-Graustufenbild-Arrays sind.quelle
Eine triviale Sache zu versuchen:
Probieren Sie beide Bilder erneut in kleinen Miniaturansichten (z. B. 64 x 64) aus und vergleichen Sie die Miniaturansichten Pixel für Pixel mit einem bestimmten Schwellenwert. Wenn die Originalbilder fast identisch sind, sind die neu abgetasteten Miniaturansichten sehr ähnlich oder sogar genau gleich. Diese Methode berücksichtigt Rauschen, das insbesondere bei schlechten Lichtverhältnissen auftreten kann. Es kann sogar besser sein, wenn Sie Graustufen gehen.
quelle
Ich gehe speziell auf die Frage ein, wie zu berechnen ist, ob sie "unterschiedlich genug" sind. Ich gehe davon aus, dass Sie herausfinden können, wie Sie die Pixel einzeln subtrahieren.
Zuerst würde ich eine Reihe von Bildern aufnehmen, ohne dass sich etwas ändert, und herausfinden, wie viel sich ein Pixel maximal ändert, nur aufgrund von Variationen bei der Aufnahme, Rauschen im Bildgebungssystem, JPEG-Komprimierungsartefakten und Änderungen der Beleuchtung von Moment zu Moment . Vielleicht werden Sie feststellen, dass 1 oder 2 Bit Unterschiede zu erwarten sind, auch wenn sich nichts bewegt.
Dann möchten Sie für den "echten" Test ein Kriterium wie das folgende:
Wenn also E = 0,02, P = 1000, würde dies (ungefähr) bedeuten, dass es "anders" wäre, wenn sich ein einzelnes Pixel um mehr als ~ 5 Einheiten ändert (unter der Annahme von 8-Bit-Bildern) oder wenn mehr als 1000 Pixel hatten überhaupt Fehler.
Dies ist hauptsächlich als gute "Triage" -Technik gedacht, um Bilder schnell zu identifizieren, die nah genug sind, um nicht weiter untersucht zu werden. Die Bilder, die "versagen", können dann eher zu einer aufwändigeren / teureren Technik führen, die keine Fehlalarme aufweist, wenn die Kamera beispielsweise etwas wackelt oder robuster gegenüber Beleuchtungsänderungen ist.
Ich führe ein Open-Source-Projekt, OpenImageIO , aus, das ein Dienstprogramm namens "idiff" enthält, das Unterschiede mit solchen Schwellenwerten vergleicht (eigentlich sogar noch ausgefeilter). Auch wenn Sie diese Software nicht verwenden möchten, sollten Sie sich die Quelle ansehen, um zu sehen, wie wir es gemacht haben. Es wird häufig kommerziell verwendet, und diese Schwellenwerttechnik wurde entwickelt, damit wir eine Testsuite für Rendering- und Bildverarbeitungssoftware mit "Referenzbildern" haben können, die von Plattform zu Plattform oder bei geringfügigen Änderungen geringfügige Unterschiede aufweisen können Als Algorithmen wollten wir eine Operation "Übereinstimmung innerhalb der Toleranz".
quelle
Ich hatte ein ähnliches Problem bei der Arbeit, ich schrieb unseren Endpunkt für die Bildtransformation neu und wollte überprüfen, ob die neue Version dieselbe oder fast dieselbe Ausgabe wie die alte Version erzeugt. Also habe ich folgendes geschrieben:
https://github.com/nicolashahn/diffimg
Bei Bildern gleicher Größe und auf Pixelebene wird die Wertdifferenz auf jedem Kanal gemessen: R, G, B (, A), die durchschnittliche Differenz dieser Kanäle und dann die Differenz über gemittelt alle Pixel und gibt ein Verhältnis zurück.
Beispiel: Bei einem 10x10-Bild mit weißen Pixeln und demselben Bild, aber einem Pixel, das sich in Rot geändert hat, beträgt der Unterschied bei diesem Pixel 1/3 oder 0,33 ... (RGB 0,0,0 gegenüber 255,0,0 ) und bei allen anderen Pixeln ist 0. Bei insgesamt 100 Pixeln ist 0,33 ... / 100 = ein Bildunterschied von ~ 0,33%.
Ich glaube, dass dies perfekt für das OP-Projekt funktionieren würde (mir ist klar, dass dies jetzt ein sehr alter Beitrag ist, aber ein Beitrag für zukünftige StackOverflowers, die auch Bilder in Python vergleichen möchten).
quelle
Die meisten Antworten beziehen sich nicht auf die Beleuchtungsstärke.
Ich würde das Bild zuerst auf ein Standardlichtniveau normalisieren, bevor ich den Vergleich durchführe.
quelle
Eine weitere schöne, einfache Möglichkeit, die Ähnlichkeit zwischen zwei Bildern zu messen:
Wenn andere an einer leistungsstärkeren Methode zum Vergleichen der Bildähnlichkeit interessiert sind, habe ich ein Tutorial und eine Web- App zum Messen und Visualisieren ähnlicher Bilder mit Tensorflow zusammengestellt.
quelle
skimage
ist wirklich schön für diese Anwendung zu verwenden. Ich benutzefrom skimage.measure import compare_ssim, compare_mse
viel. skimage.measure docs .Haben Sie den Algorithmus zum Finden ähnlicher Bilder gesehen ? Probieren Sie es aus, um Vorschläge zu sehen.
Ich würde eine Wavelet-Transformation Ihrer Frames vorschlagen (ich habe eine C-Erweiterung dafür mit der Haar-Transformation geschrieben); Wenn Sie dann die Indizes der größten (proportionalen) Wavelet-Faktoren zwischen den beiden Bildern vergleichen, sollten Sie eine numerische Ähnlichkeitsnäherung erhalten.
quelle
Ich entschuldige mich, wenn dies zu spät ist, um zu antworten, aber da ich etwas Ähnliches getan habe, dachte ich, ich könnte irgendwie dazu beitragen.
Vielleicht könnten Sie mit OpenCV Template Matching verwenden. Angenommen, Sie verwenden eine Webcam wie gesagt:
Tipp: max_val (oder min_val je nach verwendeter Methode) gibt Ihnen Zahlen, große Zahlen. Um den prozentualen Unterschied zu ermitteln, verwenden Sie eine Vorlagenübereinstimmung mit demselben Bild. Das Ergebnis sind 100%.
Pseudocode zur Veranschaulichung:
Ich hoffe es hilft.
quelle
Die Entfernung der Erdbewegungsmaschinen könnte genau das sein, was Sie brauchen. Die Implementierung in Echtzeit kann jedoch sehr schwierig sein .
quelle
Was ist mit der Berechnung der Manhattan-Entfernung der beiden Bilder ? Das gibt Ihnen n * n Werte. Dann könnten Sie so etwas wie einen Zeilendurchschnitt machen, um auf n Werte zu reduzieren, und eine Funktion darüber, um einen einzelnen Wert zu erhalten.
quelle
Ich hatte viel Glück mit JPG-Bildern, die mit derselben Kamera auf einem Stativ aufgenommen wurden, indem ich (1) stark vereinfachte (z. B. von 3000 Pixel Breite auf 100 Pixel Breite oder noch weniger) (2) jedes JPG-Array zu einem einzigen reduzierte Vektor (3) paarweise korrelierende sequentielle Bilder mit einem einfachen Korrelationsalgorithmus, um den Korrelationskoeffizienten zu erhalten (4) Quadrieren des Korrelationskoeffizienten, um das r-Quadrat zu erhalten (dh Bruchteil der Variabilität in einem Bild, erklärt durch Variation im nächsten) (5) allgemein in meiner Anwendung Wenn r-square <0,9 ist, sind die beiden Bilder unterschiedlich und dazwischen ist etwas passiert.
Dies ist robust und schnell in meiner Implementierung (Mathematica 7)
Es lohnt sich, mit dem Teil des Bildes herumzuspielen, an dem Sie interessiert sind, und sich darauf zu konzentrieren, indem Sie alle Bilder auf diesen kleinen Bereich zuschneiden. Andernfalls wird eine von der Kamera entfernte, aber wichtige Änderung übersehen.
Ich weiß nicht, wie man Python benutzt, bin mir aber sicher, dass es auch Korrelationen gibt, nein?
quelle
Sie können das Histogramm beider Bilder berechnen und dann den Bhattacharyya-Koeffizienten berechnen . Dies ist ein sehr schneller Algorithmus, und ich habe ihn verwendet, um Schussänderungen in einem Cricket-Video zu erkennen (in C mit openCV).
quelle
Sehen Sie sich an, wie Haar Wavelets von isk-daemon implementiert werden . Sie können den imgdb C ++ - Code verwenden, um den Unterschied zwischen Bildern im laufenden Betrieb zu berechnen:
quelle
Ich hatte das gleiche Problem und schrieb ein einfaches Python-Modul, das zwei Bilder gleicher Größe mit ImageChops von pillow vergleicht, um ein Schwarz / Weiß-Diff-Bild zu erstellen und die Histogrammwerte zusammenzufassen.
Sie können entweder diese Punktzahl direkt oder einen Prozentwert im Vergleich zu einem vollständigen Schwarz-Weiß-Diff erhalten.
Es enthält auch eine einfache is_equal-Funktion mit der Möglichkeit, einen Fuzzy-Schwellenwert unter (und einschließlich) dem Bild als gleich zu liefern.
Der Ansatz ist nicht sehr ausgefeilt, aber vielleicht von Nutzen für andere da draußen, die mit dem gleichen Problem zu kämpfen haben.
https://pypi.python.org/pypi/imgcompare/
quelle
Ein etwas prinzipiellerer Ansatz besteht darin, einen globalen Deskriptor zum Vergleichen von Bildern wie GIST oder CENTRIST zu verwenden. Eine Hash - Funktion, wie hier , bietet auch eine ähnliche Lösung.
quelle
Ausgabe:
Falsch
Wahr
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
die Beispielbilder:
815.jpg
5.jpg
quelle
Ich denke, Sie könnten einfach den euklidischen Abstand (dh sqrt (Summe der Quadrate der Differenzen, Pixel für Pixel)) zwischen der Luminanz der beiden Bilder berechnen und sie als gleich betrachten, wenn dieser unter einen empirischen Schwellenwert fällt. Und Sie sollten es besser tun, wenn Sie eine C-Funktion einschließen.
quelle
Es gibt viele Metriken, mit denen bewertet werden kann, ob und wie zwei Bilder aussehen.
Ich werde hier auf keinen Code eingehen, da ich denke, dass es sich um ein wissenschaftliches Problem handeln sollte, das kein technisches Problem ist.
Im Allgemeinen bezieht sich die Frage auf die Wahrnehmung des Menschen auf Bildern, sodass jeder Algorithmus seine Unterstützung für die Merkmale des menschlichen visuellen Systems hat.
Klassische Ansätze sind:
Prädiktor für sichtbare Unterschiede: Ein Algorithmus zur Bewertung der Bildtreue ( https://www.spiedigitallibrary.org/conference-proceedings-of-spie/1666/0000/Visible-differences-predictor--an-algorithm-for-the- Einschätzung von / 10.1117 / 12.135952.short? SSO = 1 )
Bewertung der Bildqualität: Von der Fehlersichtbarkeit zur strukturellen Ähnlichkeit ( http://www.cns.nyu.edu/pub/lcv/wang03-reprint.pdf )
FSIM: Ein Feature-Ähnlichkeitsindex für die Bewertung der Bildqualität ( https://www4.comp.polyu.edu.hk/~cslzhang/IQA/TIP_IQA_FSIM.pdf )
Unter diesen ist SSIM (Bildqualitätsbewertung: Von der Fehlersichtbarkeit zur strukturellen Ähnlichkeit) am einfachsten zu berechnen, und der Overhead ist ebenfalls gering, wie in einem anderen Artikel "Bewertung der Bildqualität basierend auf Gradientenähnlichkeit" ( https: //www.semanticscholar) berichtet .org / paper / Bildqualitätsbewertung basierend auf dem Gradienten Liu-Lin / 2b819bef80c02d5d4cb56f27b202535e119df988 ).
Es gibt noch viele andere Ansätze. Werfen Sie einen Blick auf Google Scholar und suchen Sie nach "visuellen Unterschieden", "Bildqualitätsbewertung" usw., wenn Sie an der Kunst interessiert sind / sich wirklich für sie interessieren.
quelle
Es gibt eine einfache und schnelle Lösung mit numpy durch Berechnung des mittleren quadratischen Fehlers:
quelle