Come posso quantificare la differenza tra due immagini?


179

Ecco cosa vorrei fare:

Sto scattando foto con una webcam a intervalli regolari. Un po 'come una cosa al rallentatore. Tuttavia, se nulla è realmente cambiato, che è, il quadro più o meno sembra lo stesso, non voglio per memorizzare l'ultimo snapshot.

Immagino che ci sia un modo per quantificare la differenza e dovrei determinare empiricamente una soglia.

Sto cercando la semplicità piuttosto che la perfezione. Sto usando Python.


Risposte:


269

Idea generale

Opzione 1: carica entrambe le immagini come array ( scipy.misc.imread) e calcola una differenza di elemento (pixel per pixel). Calcola la norma della differenza.

Opzione 2: carica entrambe le immagini. Calcola un vettore caratteristica per ciascuno di essi (come un istogramma). Calcola la distanza tra i vettori delle caratteristiche anziché le immagini.

Tuttavia, ci sono alcune decisioni da prendere per prime.

Domande

Dovresti rispondere prima a queste domande:

  • Le immagini hanno la stessa forma e dimensione?

    In caso contrario, potrebbe essere necessario ridimensionarli o ritagliarli. La libreria PIL aiuterà a farlo in Python.

    Se sono presi con le stesse impostazioni e lo stesso dispositivo, probabilmente sono gli stessi.

  • Le immagini sono ben allineate?

    In caso contrario, potresti voler eseguire prima la correlazione incrociata per trovare prima il miglior allineamento. SciPy ha funzioni per farlo.

    Se la fotocamera e la scena sono ferme, è probabile che le immagini siano ben allineate.

  • L'esposizione delle immagini è sempre la stessa? (La luminosità / il contrasto sono uguali?)

    In caso contrario, potresti voler normalizzare le immagini.

    Ma attenzione, in alcune situazioni questo può fare più male che bene. Ad esempio, un singolo pixel luminoso su uno sfondo scuro renderà l'immagine normalizzata molto diversa.

  • Le informazioni sul colore sono importanti?

    Se vuoi notare cambiamenti di colore, avrai un vettore di valori di colore per punto, piuttosto che un valore scalare come nell'immagine in scala di grigi. Hai bisogno di più attenzione quando scrivi questo codice.

  • Ci sono bordi distinti nell'immagine? È probabile che si muovano?

    In caso affermativo, è possibile applicare prima l'algoritmo di rilevamento dei bordi (ad es. Calcolare il gradiente con trasformazione Sobel o Prewitt, applicare una soglia), quindi confrontare i bordi della prima immagine con i bordi della seconda.

  • C'è del rumore nell'immagine?

    Tutti i sensori inquinano l'immagine con una certa quantità di rumore. I sensori a basso costo hanno più rumore. Potresti voler applicare una riduzione del rumore prima di confrontare le immagini. Blur è l'approccio più semplice (ma non il migliore) qui.

  • Che tipo di modifiche vuoi notare?

    Ciò può influire sulla scelta della norma da utilizzare per la differenza tra le immagini.

    Prendi in considerazione l'utilizzo della norma Manhattan (la somma dei valori assoluti) o della norma zero (il numero di elementi non uguale a zero) per misurare quanto l'immagine è cambiata. Il primo ti dirà quanto l'immagine è spenta, il secondo dirà solo quanti pixel differiscono.

Esempio

Presumo che le tue immagini siano ben allineate, stesse dimensioni e forma, possibilmente con diversa esposizione. Per semplicità, li converto in scala di grigi anche se sono immagini a colori (RGB).

Avrai bisogno di queste importazioni:

import sys

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

Funzione principale, leggere due immagini, convertire in scala di grigi, confrontare e stampare i risultati:

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

Come confrontare. img1e img2sono array 2D SciPy qui:

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)

Se il file è un'immagine a colori, imreadrestituisce un array 3D, canali RGB medi (l'ultimo asse dell'array) per ottenere intensità. Non è necessario farlo per le immagini in scala di grigi (ad es. .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 normalizzazione è banale, puoi scegliere di normalizzare a [0,1] invece di [0,255]. arrè un array SciPy qui, quindi tutte le operazioni sono elementari:

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

Esegui la mainfunzione:

if __name__ == "__main__":
    main()

Ora puoi mettere tutto in uno script ed eseguire due immagini. Se confrontiamo l'immagine con se stessa, non c'è differenza:

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

Se sfociamo l'immagine e confrontiamo l'originale, ci sono alcune differenze:

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

PS Intero script compare.py .

Aggiornamento: tecniche pertinenti

Poiché la domanda riguarda una sequenza video, in cui i frame sono probabilmente gli stessi, e cerchi qualcosa di insolito, vorrei menzionare alcuni approcci alternativi che potrebbero essere rilevanti:

  • sottrazione e segmentazione dello sfondo (per rilevare oggetti in primo piano)
  • flusso ottico scarso (per rilevare il movimento)
  • confrontando istogrammi o alcune altre statistiche invece di immagini

Consiglio vivamente di dare un'occhiata al libro "Learning OpenCV", Capitoli 9 (Parti di immagini e segmentazione) e 10 (Tracciamento e movimento). Il primo insegna a utilizzare il metodo di sottrazione di sfondo, il secondo fornisce alcune informazioni sui metodi di flusso ottico. Tutti i metodi sono implementati nella libreria OpenCV. Se usi Python, ti suggerisco di usare OpenCV ≥ 2.3 e il suo cv2modulo Python.

La versione più semplice della sottrazione di sfondo:

  • impara il valore medio μ e la deviazione standard σ per ogni pixel dello sfondo
  • confrontare i valori correnti di pixel con l'intervallo di (μ-2σ, μ + 2σ) o (μ-σ, μ + σ)

Le versioni più avanzate tengono conto delle serie temporali per ogni pixel e gestiscono scene non statiche (come spostare alberi o erba).

L'idea del flusso ottico è di prendere due o più fotogrammi e assegnare il vettore di velocità a ogni pixel (flusso ottico denso) o ad alcuni di essi (flusso ottico rado). Per stimare il flusso ottico sparso, è possibile utilizzare il metodo Lucas-Kanade (implementato anche in OpenCV). Ovviamente, se c'è molto flusso (alta media su valori massimi del campo di velocità), allora qualcosa si sta muovendo nel frame e le immagini successive sono più diverse.

Il confronto degli istogrammi può aiutare a rilevare cambiamenti improvvisi tra fotogrammi consecutivi. Questo approccio è stato utilizzato in Courbon et al, 2010 :

Somiglianza di frame consecutivi. Viene misurata la distanza tra due fotogrammi consecutivi. Se è troppo alto, significa che il secondo fotogramma è danneggiato e quindi l'immagine viene eliminata. La distanza di Kullback-Leibler , o entropia reciproca, sugli istogrammi dei due fotogrammi:

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

dove p e q sono utilizzati gli istogrammi dei frame. La soglia è fissata su 0,2.


Ottengo un RuntimeWarning: invalid value encountered in double_scalarson line 44 ( return (arr-amin)*255/rng) e un ValueError: array must not contain infs or NaNson line 30 ( z_norm = norm(diff.ravel(), 0))
BioGeek il

@BioGeek cioè se è rnguguale a zero. Basta aggiungere un assegno e impostarerng = 1
haisi

76

Una soluzione semplice:

Codifica l'immagine come jpeg e cerca un cambiamento sostanziale nella dimensione del file .

Ho implementato qualcosa di simile con le miniature dei video e ho avuto molto successo e scalabilità.


3
Questa è una soluzione molto semplice ed è molto meglio di qualsiasi confronto pixel-saggio. Se c'è un po 'di rumore nell'immagine della tua webcam o se l'immagine viene spostata anche di un solo pixel, un confronto diretto rileverà tutte queste modifiche insignificanti. Un approccio più solido sarebbe quello di calcolare la trasformazione del coseno discreto e quindi confrontare le immagini nel dominio della frequenza. L'uso della compressione JPEG in questo modo ti offre la maggior parte dei vantaggi senza tuffarti nella teoria di Fourier.
AndrewF

Mi piace. Anche se funzionano anche altre soluzioni, questo ha un grande vantaggio per una situazione comune: cosa succede se non si desidera salvare l'immagine "base"? salva la dimensione del file come hash e poi confronta solo i numeri con la sottrazione. Nel mio caso ho 4 immagini, una delle quali è molto simile e le altre 3 sono assolutamente diverse. Basta ridimensionare alle stesse dimensioni, jpg e sottrarre. Veramente bello.
Diego Andrés Díaz Espinoza,

60

Puoi confrontare due immagini usando le funzioni di PIL .

import Image
import ImageChops

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

diff = ImageChops.difference(im2, im1)

L'oggetto diff è un'immagine in cui ogni pixel è il risultato della sottrazione dei valori di colore di quel pixel nella seconda immagine dalla prima immagine. Usando l'immagine diff puoi fare diverse cose. La più semplice è la diff.getbbox()funzione. Ti dirà il rettangolo minimo che contiene tutte le modifiche tra le tue due immagini.

Probabilmente puoi implementare approssimazioni delle altre cose menzionate qui usando anche le funzioni di PIL.


2
Voglio salvare l'immagine della differenza. indica l'oggetto diff che contiene la differenza delle immagini. come posso salvarlo?
Sagar,

2
@Anthony è possibile chiamare save () sull'oggetto diff specificando il nome dell'immagine. in questo modo: diff.save ("diff.png") salverà l'immagine della differenza per te.
Sagar,

20

Due metodi popolari e relativamente semplici sono: (a) la distanza euclidea già suggerita, o (b) correlazione incrociata normalizzata. La correlazione incrociata normalizzata tende ad essere notevolmente più robusta rispetto ai cambiamenti di illuminazione rispetto alla semplice correlazione incrociata. Wikipedia fornisce una formula per la correlazione incrociata normalizzata . Esistono anche metodi più sofisticati, ma richiedono un po 'più di lavoro.

Utilizzando una sintassi simile al numpy,

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

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

dist_ncc = sum ((i1 - mean (i1)) * (i2 - mean (i2))) / (
  (i1.size - 1) * stdev (i1) * stdev (i2))

supponendo che i1e i2siano matrici di immagini in scala di grigi 2D.


3
Le funzioni di correlazione incrociata delle immagini sono integrate in SciPy ( docs.scipy.org/doc/scipy/reference/generated/… ), e una versione veloce usando FFT è disponibile in stsci python ( stsci.edu/resources/software_hardware/pyraf/ stsci_python )
endolith

14

Una cosa banale da provare:

Ricampiona entrambe le immagini in miniature piccole (ad esempio 64 x 64) e confronta le miniature pixel per pixel con una determinata soglia. Se le immagini originali sono quasi le stesse, le miniature ricampionate saranno molto simili o addirittura esattamente le stesse. Questo metodo si occupa del rumore che può verificarsi soprattutto nelle scene in condizioni di scarsa illuminazione. Potrebbe anche essere meglio se vai in scala di grigi.


ma come confronteresti i pixel?
vettore

Una volta che hai le anteprime, puoi semplicemente confrontare i pixel uno per uno. Dovresti calcolare la "distanza" dei valori RGB, se lavori a colori o solo la differenza tra i toni di grigio se sei in scala di grigi.
Ates Goral,

1
msgstr "confronta i pixel uno per uno". Cosa significa? Il test dovrebbe fallire se UNO dei 64 pixel test per pixel 2 fallisce?
Federico A. Ramponi,

Quello che intendevo per "confrontare le miniature pixel per pixel con una certa soglia" è inventare un algoritmo fuzzy per confrontare i pixel. Se la differenza calcolata (dipende dall'algoritmo fuzzy) supera una determinata soglia, le immagini non sono "le stesse".
Ates Goral,

1
Esempio molto semplice, senza "algoritmo fuzzy": ciclo parallelo attraverso ogni pixel (confronta pixel # n dell'immagine n. 1 con pixel n . N dell'immagine n. 2) e aggiungi la differenza di valore a una variabile
mk12

7

Sto affrontando specificamente la domanda su come calcolare se sono "abbastanza diversi". Suppongo che tu possa capire come sottrarre i pixel uno per uno.

In primo luogo, prenderei un mucchio di immagini senza cambiare nulla e scoprire la quantità massima che cambia qualsiasi pixel solo a causa delle variazioni nella cattura, del rumore nel sistema di imaging, degli artefatti di compressione JPEG e dei cambiamenti momento per momento dell'illuminazione . Forse scoprirai che ci si possono aspettare differenze di 1 o 2 bit anche quando non si muove nulla.

Quindi per il test "reale", vuoi un criterio come questo:

  • lo stesso se fino a P pixel differiscono di non più di E.

Quindi, forse, se E = 0,02, P = 1000, ciò significherebbe (approssimativamente) che sarebbe "diverso" se ogni singolo pixel cambi di più di ~ 5 unità (assumendo immagini a 8 bit), o se più di 1000 i pixel non hanno riscontrato alcun errore.

Ciò è inteso principalmente come una buona tecnica di "triage" per identificare rapidamente immagini abbastanza vicine da non necessitare di ulteriori esami. Le immagini che "falliscono" potrebbero quindi essere più una tecnica più elaborata / costosa che non avrebbe falsi positivi se la fotocamera si scuotesse, ad esempio, o fosse più robusta ai cambiamenti di illuminazione.

Corro un progetto open source, OpenImageIO , che contiene un'utilità chiamata "idiff" che confronta le differenze con soglie come questa (ancora più elaborata, in realtà). Anche se non vuoi usare questo software, potresti voler guardare la fonte per vedere come l'abbiamo fatto. È usato un po 'commercialmente e questa tecnica di soglia è stata sviluppata in modo da poter disporre di una suite di test per il software di rendering e di elaborazione delle immagini, con "immagini di riferimento" che potrebbero avere piccole differenze da piattaforma a piattaforma o quando abbiamo apportato piccole modifiche a che algoritmi, quindi volevamo un'operazione di "corrispondenza entro tolleranza".


6

Ho avuto un problema simile al lavoro, stavo riscrivendo il nostro endpoint di trasformazione delle immagini e volevo verificare che la nuova versione producesse lo stesso o quasi lo stesso output della versione precedente. Quindi ho scritto questo:

https://github.com/nicolashahn/diffimg

Che opera su immagini della stessa dimensione e a livello di pixel, misura la differenza di valori per ciascun canale: R, G, B (, A), prende la differenza media di quei canali e quindi media la differenza tutti i pixel e restituisce un rapporto.

Ad esempio, con un'immagine 10x10 di pixel bianchi e la stessa immagine ma un pixel è diventato rosso, la differenza in quel pixel è 1/3 o 0,33 ... (RGB 0,0,0 vs 255,0,0 ) e per tutti gli altri pixel è 0. Con un totale di 100 pixel, 0,33 ... / 100 = una differenza di ~ 0,33% nell'immagine.

Credo che questo funzionerebbe perfettamente per il progetto di OP (mi rendo conto che questo è un post molto vecchio ora, ma per i futuri StackOverflowers che vogliono anche confrontare le immagini in Python).


5

La maggior parte delle risposte fornite non tratterà dei livelli di illuminazione.

Innanzitutto normalizzare l'immagine a un livello di luce standard prima di fare il confronto.


Se stai scattando immagini periodiche e diffondi coppie adiacenti, probabilmente puoi permetterti di mantenere il primo dopo che qualcuno accende le luci.
walkytalky,

5

Un altro modo carino e semplice per misurare la somiglianza tra due immagini:

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)

Se altri sono interessati a un modo più efficace per confrontare la somiglianza delle immagini, metto insieme un tutorial e un'app Web per misurare e visualizzare immagini simili usando Tensorflow.


3
Sì, skimageè davvero bello da usare per questa applicazione. Ne uso from skimage.measure import compare_ssim, compare_msemolto. skimage.measure docs .
ximiki,

3

Hai visto l' algoritmo per trovare domande simili ? Dai un'occhiata per vedere i suggerimenti.

Suggerirei una trasformazione wavelet dei tuoi frame (ho scritto un'estensione C per quello usando la trasformazione Haar); quindi, confrontando gli indici dei maggiori fattori wavelet (proporzionali) tra le due immagini, si dovrebbe ottenere un'approssimazione numerica di somiglianza.


2

Mi scuso se è troppo tardi per rispondere, ma dato che ho fatto qualcosa di simile ho pensato di poter contribuire in qualche modo.

Forse con OpenCV potresti usare la corrispondenza dei template. Supponendo che stai usando una webcam come hai detto:

  1. Semplifica le immagini (soglia forse?)
  2. Applica la corrispondenza del modello e controlla max_val con minMaxLoc

Suggerimento: max_val (o min_val a seconda del metodo utilizzato) ti darà numeri, numeri grandi. Per ottenere la differenza in percentuale, utilizzare la corrispondenza del modello con la stessa immagine: il risultato sarà il 100%.

Pseudo codice per esemplificare:

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

Spero che sia d'aiuto.


1

La distanza dei movimenti della Terra potrebbe essere esattamente ciò di cui hai bisogno. Potrebbe essere un po ' pesante da implementare in tempo reale.


Non sento davvero che questa risposta si rivolga bene: "Sto cercando semplicità anziché perfezione. Sto usando Python."
PilouPili,

Penso che poiché questo thread di domande ottiene molto traffico e il titolo che attira la maggior parte degli spettatori riguarda come quantificare la differenza tra due immagini, ha un valore qui.
Danoram,

1

Che dire del calcolo della distanza di Manhattan delle due immagini. Questo ti dà n * n valori. Quindi potresti fare qualcosa come una media di riga per ridurre a n valori e una funzione su quello per ottenere un singolo valore.


1

Ho avuto molta fortuna con le immagini jpg scattate con la stessa fotocamera su un treppiede semplificando notevolmente (come passare da 3000 pixel di larghezza a 100 pixel di larghezza o anche meno) (2) appiattendo ogni array jpg in un singolo vettore (3) immagini sequenziali correlate in coppia con un semplice algoritmo correlato per ottenere coefficiente di correlazione (4) coefficiente di correlazione quadrata per ottenere r-quadrato (cioè frazione di variabilità in un'immagine spiegata dalla variazione nella successiva) (5) generalmente nella mia applicazione se r-square <0.9, dico che le due immagini sono diverse e qualcosa è accaduto nel mezzo.

Questo è solido e veloce nella mia implementazione (Mathematica 7)

Vale la pena giocare con la parte dell'immagine a cui sei interessato e concentrarti su di essa ritagliando tutte le immagini in quella piccola area, altrimenti ci mancherà un cambiamento distante dalla fotocamera ma importante.

Non so come usare Python, ma sono sicuro che fa anche correlazioni, no?


1

puoi calcolare l'istogramma di entrambe le immagini e quindi calcolare il coefficiente Bhattacharyya , questo è un algoritmo molto veloce e l'ho usato per rilevare i cambiamenti di tiro in un video di cricket (in C usando openCV)


Potresti calcolare il coefficiente sulle immagini stesse?
Endolith,

Dovrai calcolare gli istogrammi per le immagini (con la dimensione del cestino dell'istogramma secondo i requisiti).
vishalv2050,

1

Scopri come Haar Wavelets sono implementate da isk-daemon . Puoi usare il suo codice C ++ imgdb per calcolare la differenza tra le immagini al volo:

isk-daemon è un server di database open source in grado di aggiungere ricerche di immagini (visive) basate sul contenuto a qualsiasi sito Web o software relativo alle immagini.

Questa tecnologia consente agli utenti di qualsiasi sito Web o software relativo alle immagini di disegnare su un widget quale immagine desiderano trovare e di far sì che il sito Web risponda loro alle immagini più simili o richieda semplicemente foto più simili in ogni pagina dei dettagli dell'immagine.


1

Ho avuto lo stesso problema e ho scritto un semplice modulo Python che confronta due immagini della stessa dimensione usando ImageChops del cuscino per creare un'immagine diff bianco / nero e riassumere i valori dell'istogramma.

È possibile ottenere direttamente questo punteggio o un valore percentuale rispetto a una differenza tra nero e bianco.

Contiene anche una semplice funzione is_equal, con la possibilità di fornire una soglia fuzzy al di sotto (e compresa) l'immagine passa come uguale.

L'approccio non è molto elaborato, ma forse è utile per altri là fuori alle prese con lo stesso problema.

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


1

Un approccio un po 'più basato sui principi è quello di utilizzare un descrittore globale per confrontare le immagini, come GIST o CENTRIST. Una funzione hash, come descritto qui , fornisce anche una soluzione simile.


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()
  • produzione:

    Falso
    Vero
    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

  • le immagini di esempio:

    • 815.jpg
      815.jpg

    • 5.jpg
      5.jpg


0

Penso che potresti semplicemente calcolare la distanza euclidea (cioè sqrt (somma dei quadrati delle differenze, pixel per pixel)) tra la luminanza delle due immagini, e considerarle uguali se questa scende sotto una soglia empirica. E faresti meglio a farlo avvolgendo una funzione C.


0

Ci sono molte metriche là fuori per valutare se due immagini sembrano / quanto sembrano.

Non inserirò nessun codice qui, perché penso che dovrebbe essere un problema scientifico, diverso da un problema tecnico.

In generale, la domanda è correlata alla percezione umana sulle immagini, quindi ogni algoritmo ha il suo supporto sui tratti del sistema visivo umano.

Gli approcci classici sono:

Predittore di differenze visibili: un algoritmo per la valutazione della fedeltà dell'immagine ( https://www.spiedigitallibrary.org/conference-proceedings-of-spie/1666/0000/Visible-differences-predictor--an-algorithm-for-the- assessment-of / 10.1117 / 12.135952.short? SSO = 1 )

Valutazione della qualità dell'immagine: dalla visibilità dell'errore alla somiglianza strutturale ( http://www.cns.nyu.edu/pub/lcv/wang03-reprint.pdf )

FSIM: un indice di somiglianza di funzionalità per la valutazione della qualità dell'immagine ( https://www4.comp.polyu.edu.hk/~cslzhang/IQA/TIP_IQA_FSIM.pdf )

Tra questi, SSIM (valutazione della qualità dell'immagine: dalla visibilità dell'errore alla somiglianza strutturale) è il più semplice da calcolare e anche il suo sovraccarico è piccolo, come riportato in un altro documento "Valutazione della qualità dell'immagine basata sulla somiglianza del gradiente" ( https: //www.semanticscholar .org / paper / Valutazione della qualità delle immagini in base al gradiente-Liu-Lin / 2b819bef80c02d5d4cb56f27b202535e119df988 ).

Esistono molti altri approcci. Dai un'occhiata a Google Scholar e cerca qualcosa come "differenza visiva", "valutazione della qualità dell'immagine", ecc., Se sei interessato / ti interessa davvero l'arte.


0

Esiste una soluzione semplice e veloce che utilizza numpy calcolando l'errore quadratico medio:

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

    if  MSE > threshold:
        break

    before = now
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.