Wie kann ich den Unterschied zwischen zwei Bildern quantifizieren?

177

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.

Träger
quelle
Siehe auch
Anoyz

Antworten:

267

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:

import sys

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

Hauptfunktion, zwei Bilder lesen, in Graustufen konvertieren, Ergebnisse vergleichen und drucken:

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

Wie zu vergleichen. img1und img2sind hier 2D SciPy Arrays:

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)

Wenn es sich bei der Datei um ein Farbbild handelt, wird imreadein 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 :

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

Die Normalisierung ist trivial. Sie können auch die Normalisierung auf [0,1] anstelle von [0,255] wählen. arrist hier ein SciPy-Array, daher sind alle Operationen elementweise:

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

Führen Sie die mainFunktion aus:

if __name__ == "__main__":
    main()

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:

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

Wenn wir das Bild verwischen und mit dem Original vergleichen, gibt es einen Unterschied:

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

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:

  • Hintergrundsubtraktion und -segmentierung (zur Erkennung von Vordergrundobjekten)
  • spärlicher optischer Fluss (zur Bewegungserkennung)
  • Vergleichen von Histogrammen oder anderen Statistiken anstelle von Bildern

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 cv2Python-Moduls.

Die einfachste Version der Hintergrundsubtraktion:

  • Lernen Sie den Mittelwert μ und die Standardabweichung σ für jedes Pixel des Hintergrunds
  • Vergleichen Sie die aktuellen Pixelwerte mit dem Bereich von (μ-2σ, μ + 2σ) oder (μ-σ, μ + σ).

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 :

Ähnlichkeit aufeinanderfolgender Frames. Der Abstand zwischen zwei aufeinanderfolgenden Bildern wird gemessen. Wenn es zu hoch ist, bedeutet dies, dass das zweite Bild beschädigt ist und somit das Bild entfernt wird. Der Kullback-Leibler-Abstand oder die gegenseitige Entropie in den Histogrammen der beiden Bilder:

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

Dabei sind p und q die Histogramme der Frames. Der Schwellenwert ist auf 0,2 festgelegt.

Sastanin
quelle
Ich bekomme eine RuntimeWarning: invalid value encountered in double_scalarsauf Linie 44 ( return (arr-amin)*255/rng) und eine ValueError: array must not contain infs or NaNsauf Linie 30 ( z_norm = norm(diff.ravel(), 0))
BioGeek
@BioGeek das heißt, wenn rnggleich Null ist. rng = 1
Fügen Sie
76

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.

Keparo
quelle
3
Dies ist eine sehr einfache Lösung und viel besser als jeder pixelweise Vergleich. Wenn das Bild Ihrer Webcam ein wenig Rauschen enthält oder wenn das Bild nur um ein Pixel verschoben ist, werden durch einen direkten Vergleich all diese bedeutungslosen Änderungen erfasst. Ein robusterer Ansatz wäre, die diskrete Cosinustransformation zu berechnen und dann die Bilder im Frequenzbereich zu vergleichen. Wenn Sie eine solche JPEG-Komprimierung verwenden, erhalten Sie die meisten Vorteile, ohne in die Fourier-Theorie einzutauchen.
AndrewF
Mag ich. Obwohl auch andere Lösungen funktionieren, hat dies einen großen Vorteil für eine häufige Situation: Was ist, wenn Sie das "Basis" -Image nicht speichern möchten? Speichern Sie einfach die Dateigröße als Hash und vergleichen Sie dann nur Zahlen mit Subtraktion. In meinem Fall habe ich 4 Bilder, eines davon ist sehr ähnlich und die anderen 3 sind absolut unterschiedlich. Skalieren Sie einfach auf die gleichen Abmessungen, um JPG zu erstellen und zu subtrahieren. Wirklich nett.
Diego Andrés Díaz Espinoza
60

Sie können zwei Bilder mit Funktionen von PIL vergleichen .

import Image
import ImageChops

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

diff = ImageChops.difference(im2, im1)

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.

Elifiner
quelle
2
Ich möchte das Differenzbild speichern. bedeutet das Diff-Objekt, das den Unterschied von Bildern enthält. Wie speichere ich es?
Sagar
2
@Anthony Sie können save () für ein diff-Objekt aufrufen und den Bildnamen angeben. wie folgt: diff.save ("diff.png") speichert das Differenzbild für Sie.
Sagar
20

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

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

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

dist_ncc = Summe ((i1 - Mittelwert (i1)) * (i2 - Mittelwert (i2))) / (
  (i1.size - 1) * stdev (i1) * stdev (i2))

unter der Annahme, dass i1und i22D-Graustufenbild-Arrays sind.

Herr Fooz
quelle
3
Bildkreuzkorrelationsfunktionen sind in SciPy ( docs.scipy.org/doc/scipy/reference/generated/… ) integriert, und eine schnelle Version mit der FFT ist in stsci python verfügbar ( stsci.edu/resources/software_hardware/pyraf/). stsci_python )
Endolith
14

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.

Ates Goral
quelle
aber wie würden Sie die Pixel vergleichen?
Träger
Sobald Sie die Miniaturansichten haben, können Sie die Pixel einfach einzeln vergleichen. Sie würden den "Abstand" der RGB-Werte berechnen, wenn Sie in Farbe arbeiten, oder nur den Unterschied zwischen den Grautönen, wenn Sie in Graustufen arbeiten.
Ates Goral
1
"Vergleichen Sie die Pixel einzeln". Was bedeutet das? Sollte der Test fehlschlagen, wenn EINER der 64 ^ 2 Pixel-pro-Pixel-Tests fehlschlägt?
Federico A. Ramponi
Was ich mit "Pixel für Pixel mit einem bestimmten Schwellenwert vergleichen" gemeint habe, ist, einen Fuzzy-Algorithmus zum Vergleichen der Pixel zu entwickeln. Wenn die berechnete Differenz (abhängig von Ihrem Fuzzy-Algorithmus) einen bestimmten Schwellenwert überschreitet, sind die Bilder "nicht gleich".
Ates Goral
1
Sehr einfaches Beispiel ohne den "Fuzzy-Algorithmus": Parallele Schleife durch jedes Pixel (vergleiche Pixel Nr. N von Bild Nr. 1 mit Pixel Nr. N von Bild Nr. 2) und addiere die Wertdifferenz zu einer Variablen
mk12
7

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:

  • Gleich, wenn sich bis zu P Pixel um nicht mehr als E unterscheiden.

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".

Larry Gritz
quelle
6

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).

nicolashahn
quelle
5

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.

Loren Pechtel
quelle
Wenn Sie periodische Bilder aufnehmen und benachbarte Paare unterscheiden, können Sie es sich wahrscheinlich leisten, das erste zu behalten, nachdem jemand das Licht eingeschaltet hat.
Walkytalky
5

Eine weitere schöne, einfache Möglichkeit, die Ähnlichkeit zwischen zwei Bildern zu messen:

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)

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.

duhaime
quelle
3
Ja, skimageist wirklich schön für diese Anwendung zu verwenden. Ich benutze from skimage.measure import compare_ssim, compare_mseviel. skimage.measure docs .
Ximiki
3

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.

tzot
quelle
2

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:

  1. Vereinfachen Sie die Bilder (Schwellenwert vielleicht?)
  2. Wenden Sie Template Matching an und überprüfen Sie das max_val mit minMaxLoc

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:

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

Ich hoffe es hilft.

zanfranceschi
quelle
1

Die Entfernung der Erdbewegungsmaschinen könnte genau das sein, was Sie brauchen. Die Implementierung in Echtzeit kann jedoch sehr schwierig sein .

shoosh
quelle
Ich finde diese Antwort nicht wirklich gut: "Ich suche eher nach Einfachheit als nach Perfektion. Ich verwende Python."
PilouPili
Ich denke, da dieser Fragenthread viel Verkehr bekommt und der Titel, der die meisten Zuschauer anzieht, darüber handelt, wie man den Unterschied zwischen zwei Bildern quantifiziert, hat er hier Wert.
Danoram
1

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.

Tobias
quelle
1

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?

Römisches Zifferblatt
quelle
1

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).

vishalv2050
quelle
Könnten Sie den Koeffizienten für die Bilder selbst berechnen?
Endolith
Sie müssen die Histogramme für die Bilder berechnen (mit der Bin-Größe des Histogramms gemäß den Anforderungen).
vishalv2050
1

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:

isk-daemon ist ein Open-Source-Datenbankserver, der in der Lage ist, jeder bildbezogenen Website oder Software eine inhaltsbasierte (visuelle) Bildsuche hinzuzufügen.

Mit dieser Technologie können Benutzer jeder bildbezogenen Website oder Software in einem Widget skizzieren, welches Bild sie finden möchten, und die Website kann ihnen die ähnlichsten Bilder antworten oder einfach auf jeder Bilddetailseite weitere ähnliche Fotos anfordern.

Ricardo Cabral
quelle
1

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/

datenhahn
quelle
1

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.

Felix Goldberg
quelle
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()
  • 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
      815.jpg

    • 5.jpg
      5.jpg

Administrator
quelle
0

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.

Federico A. Ramponi
quelle
0

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.

Cyfex
quelle
0

Es gibt eine einfache und schnelle Lösung mit numpy durch Berechnung des mittleren quadratischen Fehlers:

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
quelle