¿Cómo puedo cuantificar la diferencia entre dos imágenes?

179

Esto es lo que me gustaría hacer:

Estoy tomando fotos con una cámara web a intervalos regulares. Algo así como un lapso de tiempo. Sin embargo, si nada ha cambiado realmente, es decir, la imagen se ve más o menos igual, no quiero almacenar la última instantánea.

Me imagino que hay alguna forma de cuantificar la diferencia, y tendría que determinar empíricamente un umbral.

Estoy buscando simplicidad en lugar de perfección. Estoy usando python

portador
fuente

Respuestas:

269

Idea general

Opción 1: Cargue ambas imágenes como matrices ( scipy.misc.imread) y calcule una diferencia de elemento (píxel por píxel). Calcule la norma de la diferencia.

Opción 2: cargar ambas imágenes. Calcule algún vector de características para cada uno de ellos (como un histograma). Calcule la distancia entre vectores de características en lugar de imágenes.

Sin embargo, hay algunas decisiones que tomar primero.

Preguntas

Primero debe responder estas preguntas:

  • ¿Son las imágenes de la misma forma y dimensión?

    De lo contrario, es posible que deba cambiar su tamaño o recortarlos. La biblioteca PIL ayudará a hacerlo en Python.

    Si se toman con la misma configuración y el mismo dispositivo, probablemente sean lo mismo.

  • ¿Las imágenes están bien alineadas?

    Si no, es posible que desee ejecutar primero la correlación cruzada, para encontrar primero la mejor alineación. SciPy tiene funciones para hacerlo.

    Si la cámara y la escena están quietas, es probable que las imágenes estén bien alineadas.

  • ¿La exposición de las imágenes es siempre la misma? (¿La luminosidad / contraste es lo mismo?)

    Si no, es posible que desee normalizar las imágenes.

    Pero tenga cuidado, en algunas situaciones esto puede hacer más mal que bien. Por ejemplo, un solo píxel brillante sobre un fondo oscuro hará que la imagen normalizada sea muy diferente.

  • ¿Es importante la información de color?

    Si desea notar cambios de color, tendrá un vector de valores de color por punto, en lugar de un valor escalar como en la imagen en escala de grises. Necesita más atención al escribir dicho código.

  • ¿Hay bordes distintos en la imagen? ¿Es probable que se muevan?

    En caso afirmativo, puede aplicar primero el algoritmo de detección de bordes (por ejemplo, calcular el gradiente con la transformación Sobel o Prewitt, aplicar algún umbral), luego comparar los bordes en la primera imagen con los bordes en la segunda.

  • ¿Hay ruido en la imagen?

    Todos los sensores contaminan la imagen con cierta cantidad de ruido. Los sensores de bajo costo tienen más ruido. Es posible que desee aplicar algo de reducción de ruido antes de comparar imágenes. Desenfocar es el enfoque más simple (pero no el mejor) aquí.

  • ¿Qué tipo de cambios quieres notar?

    Esto puede afectar la elección de la norma a utilizar para la diferencia entre imágenes.

    Considere usar la norma de Manhattan (la suma de los valores absolutos) o la norma cero (el número de elementos que no son iguales a cero) para medir cuánto ha cambiado la imagen. El primero le dirá cuánto está apagada la imagen, el segundo le dirá cuántos píxeles difieren.

Ejemplo

Supongo que sus imágenes están bien alineadas, tienen el mismo tamaño y forma, posiblemente con diferente exposición. Para simplificar, los convierto a escala de grises incluso si son imágenes en color (RGB).

Necesitará estas importaciones:

import sys

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

Función principal, leer dos imágenes, convertir a escala de grises, comparar e imprimir resultados:

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

Cómo comparar img1y img2son matrices 2D SciPy aquí:

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

Si el archivo es una imagen en color, imreaddevuelve una matriz 3D, canales RGB promedio (el último eje de la matriz) para obtener intensidad. No es necesario hacerlo para imágenes en escala de grises (por ejemplo .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 normalización es trivial, puede elegir normalizar a [0,1] en lugar de [0,255]. arres una matriz SciPy aquí, por lo que todas las operaciones son por elementos:

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

Ejecuta la mainfunción:

if __name__ == "__main__":
    main()

Ahora puede poner todo esto en un script y ejecutar dos imágenes. Si comparamos la imagen consigo misma, no hay diferencia:

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

Si desenfocamos la imagen y la comparamos con la original, hay alguna diferencia:

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

PD : guión compare.py completo .

Actualización: técnicas relevantes

Como la pregunta es sobre una secuencia de video, donde es probable que los cuadros sean casi iguales, y se busca algo inusual, me gustaría mencionar algunos enfoques alternativos que pueden ser relevantes:

  • sustracción y segmentación de fondo (para detectar objetos en primer plano)
  • flujo óptico escaso (para detectar movimiento)
  • comparar histogramas u otras estadísticas en lugar de imágenes

Recomiendo echar un vistazo al libro "Learning OpenCV", Capítulos 9 (Partes de imagen y segmentación) y 10 (Seguimiento y movimiento). El primero enseña a usar el método de sustracción de fondo, el último da información sobre los métodos de flujo óptico. Todos los métodos se implementan en la biblioteca OpenCV. Si usa Python, sugiero usar OpenCV ≥ 2.3, y su cv2módulo Python.

La versión más simple de la resta de fondo:

  • Aprenda el valor promedio μ y la desviación estándar σ para cada píxel del fondo
  • compare los valores actuales de píxeles con el rango de (μ-2σ, μ + 2σ) o (μ-σ, μ + σ)

Las versiones más avanzadas tienen en cuenta las series temporales para cada píxel y manejan escenas no estáticas (como mover árboles o césped).

La idea del flujo óptico es tomar dos o más cuadros y asignar un vector de velocidad a cada píxel (flujo óptico denso) o a algunos de ellos (flujo óptico disperso). Para estimar el flujo óptico disperso, puede usar el método Lucas-Kanade (también se implementa en OpenCV). Obviamente, si hay mucho flujo (promedio alto sobre los valores máximos del campo de velocidad), entonces algo se mueve en el cuadro y las imágenes posteriores son más diferentes.

La comparación de histogramas puede ayudar a detectar cambios repentinos entre cuadros consecutivos. Este enfoque se utilizó en Courbon et al, 2010 :

Similitud de cuadros consecutivos. Se mide la distancia entre dos cuadros consecutivos. Si es demasiado alto, significa que el segundo cuadro está dañado y, por lo tanto, se elimina la imagen. La distancia Kullback-Leibler , o entropía mutua, en los histogramas de los dos cuadros:

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

donde p y q son los histogramas de los marcos se utiliza. El umbral se fija en 0.2.

sastanin
fuente
Me sale un RuntimeWarning: invalid value encountered in double_scalarsen línea 44 ( return (arr-amin)*255/rng) y un ValueError: array must not contain infs or NaNsen línea 30 ( z_norm = norm(diff.ravel(), 0))
BioGeek
@BioGeek es decir, si es rngigual a cero. Solo agregue un cheque y rng = 1
configúrelo
76

Una solución simple:

Codificar la imagen como un archivo JPEG y busque un cambio sustancial en el tamaño del archivo .

Implementé algo similar con las miniaturas de video y tuve mucho éxito y escalabilidad.

keparo
fuente
3
Esta es una solución muy fácil y simple y es mucho mejor que cualquier comparación de píxeles. Si hay un poco de ruido en la imagen de su cámara web o si la imagen se desplaza incluso un píxel, entonces una comparación directa recogerá todos estos cambios sin sentido. Un enfoque más robusto sería calcular la transformación discreta del coseno y luego comparar las imágenes en el dominio de la frecuencia. El uso de una compresión JPEG como esta le brinda la mayoría de los beneficios sin sumergirse en la teoría de Fourier.
AndrewF
Gusta. Aunque otras soluciones también funcionan, esto tiene una gran ventaja para una situación común: ¿qué pasa si no desea guardar la imagen "base"? simplemente guarde el tamaño del archivo como un hash y luego compare solo los números con la resta. En mi caso tengo 4 imágenes, una de ellas es muy similar y las otras 3 son absolutamente diferentes. Simplemente escale a las mismas dimensiones, a jpg y reste. Muy agradable.
Diego Andrés Díaz Espinoza
60

Puede comparar dos imágenes usando las funciones de PIL .

import Image
import ImageChops

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

diff = ImageChops.difference(im2, im1)

El objeto diff es una imagen en la que cada píxel es el resultado de la resta de los valores de color de ese píxel en la segunda imagen de la primera imagen. Usando la imagen diff puedes hacer varias cosas. El más simple es eldiff.getbbox() función. Le indicará el rectángulo mínimo que contiene todos los cambios entre sus dos imágenes.

Probablemente pueda implementar aproximaciones de las otras cosas mencionadas aquí usando funciones de PIL también.

elifiner
fuente
2
Quiero guardar la imagen de diferencia. significa el objeto diff que contiene la diferencia de imágenes. ¿Cómo lo guardo?
Sagar
2
@Anthony puede llamar a save () en el objeto diff especificando el nombre de la imagen. así: diff.save ("diff.png") guardará la imagen de diferencia para usted.
Sagar
20

Dos métodos populares y relativamente simples son: (a) la distancia euclidiana ya sugerida, o (b) la correlación cruzada normalizada. La correlación cruzada normalizada tiende a ser notablemente más robusta a los cambios de iluminación que la simple correlación cruzada. Wikipedia da una fórmula para la correlación cruzada normalizada . También existen métodos más sofisticados, pero requieren bastante más trabajo.

Usando sintaxis tipo 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))

suponiendo eso i1y i2son matrices de imágenes en escala de grises 2D.

Señor fooz
fuente
3
Las funciones de correlación cruzada de imágenes están integradas en SciPy ( docs.scipy.org/doc/scipy/reference/generated/… ), y una versión rápida que utiliza FFT está disponible en stsci python ( stsci.edu/resources/software_hardware/pyraf/ stsci_python )
endolith
14

Una cosa trivial para probar:

Vuelva a muestrear ambas imágenes en miniaturas pequeñas (por ejemplo, 64 x 64) y compare las miniaturas píxel por píxel con un cierto umbral. Si las imágenes originales son casi iguales, las miniaturas muestreadas serán muy similares o incluso exactamente las mismas. Este método se encarga del ruido que puede ocurrir especialmente en escenas con poca luz. Incluso puede ser mejor si vas en escala de grises.

Ates Goral
fuente
pero ¿cómo compararías los píxeles?
transportista
Una vez que tenga las miniaturas, simplemente puede comparar los píxeles uno por uno. Calcularía la "distancia" de los valores RGB, si trabaja en color o simplemente la diferencia entre los tonos grises si está en escala de grises.
Ates Goral
1
"compara los píxeles uno por uno". Qué significa eso? ¿Debería fallar la prueba si falla UNA de las 64 ^ 2 píxeles por píxel?
Federico A. Ramponi
Lo que quise decir con "comparar las miniaturas píxel por píxel con un cierto umbral" es crear un algoritmo difuso para comparar los píxeles. Si la diferencia calculada (depende de su algoritmo difuso) excede un cierto umbral, las imágenes "no son las mismas".
Ates Goral
1
Ejemplo muy simple, sin el "algoritmo difuso": bucle paralelo a través de cada píxel (compare el píxel n de la imagen n . ° 1 con el píxel n de la imagen n . ° 2) y agregue la diferencia de valor a una variable
mk12
7

Me dirijo específicamente a la cuestión de cómo calcular si son "lo suficientemente diferentes". Supongo que puedes descubrir cómo restar los píxeles uno por uno.

Primero, tomaría un montón de imágenes sin cambios, y averiguaría la cantidad máxima que cualquier píxel cambia solo por las variaciones en la captura, el ruido en el sistema de imágenes, los artefactos de compresión JPEG y los cambios de iluminación momento a momento . Tal vez encuentre que se esperan diferencias de 1 o 2 bits incluso cuando nada se mueve.

Luego, para la prueba "real", desea un criterio como este:

  • lo mismo si hasta P píxeles difieren en no más de E.

Entonces, tal vez, si E = 0.02, P = 1000, eso significaría (aproximadamente) que sería "diferente" si cualquier píxel cambia en más de ~ 5 unidades (suponiendo imágenes de 8 bits), o si más de 1000 píxeles tenían algún error en absoluto.

Esto está pensado principalmente como una buena técnica de "triaje" para identificar rápidamente imágenes que están lo suficientemente cerca como para no necesitar un examen más detallado. Las imágenes que "fallan" pueden entonces ser más una técnica más elaborada / costosa que no tendría falsos positivos si la cámara se sacudiera un poco, por ejemplo, o fuera más robusta a los cambios de iluminación.

Ejecuto un proyecto de código abierto, OpenImageIO , que contiene una utilidad llamada "idiff" que compara las diferencias con umbrales como este (aún más elaborado, en realidad). Incluso si no desea utilizar este software, puede consultar la fuente para ver cómo lo hicimos. Se utiliza bastante comercialmente y esta técnica de umbral se desarrolló para que pudiéramos tener un conjunto de pruebas para el software de procesamiento y procesamiento de imágenes, con "imágenes de referencia" que podrían tener pequeñas diferencias de plataforma a plataforma o cuando realizamos pequeños ajustes a tha algoritmos, por lo que queríamos una operación de "coincidencia dentro de la tolerancia".

Larry Gritz
fuente
6

Tuve un problema similar en el trabajo, estaba reescribiendo nuestro punto final de transformación de imagen y quería comprobar que la nueva versión producía el mismo o casi el mismo resultado que la versión anterior. Entonces escribí esto:

https://github.com/nicolashahn/diffimg

El cual opera en imágenes del mismo tamaño, y en un nivel por píxel, mide la diferencia de valores en cada canal: R, G, B (, A), toma la diferencia promedio de esos canales y luego promedia la diferencia sobre todos los píxeles, y devuelve una relación.

Por ejemplo, con una imagen de 10x10 píxeles blancos, y la misma imagen pero un píxel ha cambiado a rojo, la diferencia en ese píxel es 1/3 o 0.33 ... (RGB 0,0,0 vs 255,0,0 ) y en todos los demás píxeles es 0. Con un total de 100 píxeles, 0,33 ... / 100 = una diferencia de imagen de ~ 0,33%.

Creo que esto funcionaría perfectamente para el proyecto de OP (me doy cuenta de que esta es una publicación muy antigua ahora, pero está publicando para futuros StackOverflowers que también quieren comparar imágenes en python).

nicolashahn
fuente
5

La mayoría de las respuestas dadas no abordarán los niveles de iluminación.

Primero normalizaría la imagen a un nivel de luz estándar antes de hacer la comparación.

Loren Pechtel
fuente
Si toma imágenes periódicas y difiere pares adyacentes, probablemente pueda permitirse quedarse con la primera después de que alguien encienda las luces.
walkytalky
5

Otra forma agradable y simple de medir la similitud entre dos imágenes:

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

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

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

Si otros están interesados ​​en una forma más poderosa de comparar la similitud de la imagen, preparé un tutorial imágenes, preparé y una aplicación web para medir y visualizar imágenes similares usando Tensorflow.

duhaime
fuente
3
Sí, skimagees realmente agradable de usar para esta aplicación. Yo uso from skimage.measure import compare_ssim, compare_msemucho skimage.measure docs .
ximiki
3

¿Has visto el algoritmo para encontrar imágenes similares? pregunta ? Compruébalo para ver sugerencias.

Sugeriría una transformación wavelet de sus marcos (he escrito una extensión C para eso usando la transformación Haar); luego, al comparar los índices de los factores wavelet más grandes (proporcionalmente) entre las dos imágenes, debe obtener una aproximación de similitud numérica.

tzot
fuente
2

Pido disculpas si es demasiado tarde para responder, pero como he estado haciendo algo similar, pensé que podría contribuir de alguna manera.

Quizás con OpenCV podría usar la coincidencia de plantillas. Asumiendo que estás usando una cámara web como dijiste:

  1. Simplifique las imágenes (¿umbral quizás?)
  2. Aplique la coincidencia de plantillas y verifique max_val con minMaxLoc

Consejo: max_val (o min_val dependiendo del método utilizado) le dará números, números grandes. Para obtener la diferencia en porcentaje, use una plantilla que coincida con la misma imagen; el resultado será su 100%.

Pseudocódigo para ejemplificar:

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

Espero eso ayude.

zanfranceschi
fuente
1

La distancia de los motores de la Tierra podría ser exactamente lo que necesita. Sin embargo, podría ser bastante pesado implementarlo en tiempo real.

shoosh
fuente
Realmente no siento que esta respuesta se dirija bien: "Estoy buscando simplicidad en lugar de perfección. Estoy usando Python".
PilouPili
Creo que a medida que este hilo de preguntas recibe mucho tráfico y el título que atrae a la mayoría de los espectadores es sobre cómo cuantificar la diferencia entre dos imágenes, tiene valor aquí.
Danoram
1

¿Qué pasa con el cálculo de la distancia de Manhattan de las dos imágenes? Eso te da n * n valores. Entonces podría hacer algo como un promedio de fila para reducir a n valores y una función sobre eso para obtener un solo valor.

Tobias
fuente
1

He tenido mucha suerte con las imágenes jpg tomadas con la misma cámara en un trípode al (1) simplificar enormemente (como pasar de 3000 píxeles de ancho a 100 píxeles de ancho o incluso menos) (2) aplanar cada conjunto de jpg en un solo vector (3) imágenes secuenciales que se correlacionan por pares con un algoritmo de correlación simple para obtener el coeficiente de correlación (4) coeficiente de correlación de cuadratura para obtener r-cuadrado (es decir, fracción de variabilidad en una imagen explicada por la variación en la siguiente) (5) generalmente en mi aplicación si r-cuadrado <0.9, digo que las dos imágenes son diferentes y algo sucedió en el medio.

Esto es robusto y rápido en mi implementación (Mathematica 7)

Vale la pena jugar con la parte de la imagen que le interesa y enfocarse en eso recortando todas las imágenes en esa pequeña área, de lo contrario se perderá un cambio distante de la cámara pero importante.

No sé cómo usar Python, pero estoy seguro de que también tiene correlaciones, ¿no?

Dial romano
fuente
1

puedes calcular el histograma de ambas imágenes y luego calcular el Coeficiente de Bhattacharyya , este es un algoritmo muy rápido y lo he usado para detectar cambios de disparo en un video de cricket (en C usando openCV)

vishalv2050
fuente
¿Podría calcular el coeficiente de las imágenes mismas?
endolito
Tendrá que calcular los histogramas para las imágenes (con el tamaño del contenedor del histograma según los requisitos).
vishalv2050
1

Echa un vistazo a cómo isar-daemon implementa las Wavelets de Haar . Puede usar su código imgdb C ++ para calcular la diferencia entre imágenes sobre la marcha:

isk-daemon es un servidor de base de datos de código abierto capaz de agregar búsquedas de imágenes (visuales) basadas en contenido a cualquier sitio web o software relacionado con imágenes.

Esta tecnología permite a los usuarios de cualquier sitio web o software relacionado con imágenes dibujar en un widget qué imagen desean encontrar y hacer que el sitio web les responda las imágenes más similares o simplemente soliciten fotos más similares en cada página de detalles de imagen.

Ricardo Cabral
fuente
1

Tuve el mismo problema y escribí un módulo simple de Python que compara dos imágenes del mismo tamaño usando ImageChops de pillow para crear una imagen de diferencias en blanco y negro y resume los valores del histograma.

Puede obtener este puntaje directamente o un valor porcentual en comparación con una diferencia completa de blanco y negro.

También contiene una función simple is_equal, con la posibilidad de proporcionar un umbral difuso debajo (e incluido) de que la imagen pase como igual.

El enfoque no es muy elaborado, pero tal vez sea útil para otros que luchan con el mismo problema.

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

Datenhahn
fuente
1

Un enfoque algo más basado en principios es usar un descriptor global para comparar imágenes, como GIST o CENTRIST. Una función hash, como se describe aquí , también proporciona una solución similar.

Felix Goldberg
fuente
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()
  • salida:

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

  • las fotos de ejemplo:

    • 815.jpg
      815.jpg

    • 5.jpg
      5.jpg

administración
fuente
0

Creo que simplemente podría calcular la distancia euclidiana (es decir, sqrt (suma de cuadrados de diferencias, píxel por píxel)) entre la luminancia de las dos imágenes, y considerarlas iguales si esto cae por debajo de algún umbral empírico. Y será mejor que lo haga envolviendo una función C.

Federico A. Ramponi
fuente
0

Existen muchas métricas para evaluar si se ven dos imágenes / cuánto se ven.

No entraré en ningún código aquí, porque creo que debería ser un problema científico, además de un problema técnico.

En general, la pregunta está relacionada con la percepción humana en las imágenes, por lo que cada algoritmo tiene su apoyo en los rasgos del sistema visual humano.

Los enfoques clásicos son:

Predictor de diferencias visibles: un algoritmo para la evaluación de la fidelidad de la imagen ( https://www.spiedigitallibrary.org/conference-proceedings-of-spie/1666/0000/Visible-differences-predictor--an-algorithm-for-the- evaluación-de / 10.1117 / 12.135952.short? SSO = 1 )

Evaluación de la calidad de imagen: de la visibilidad del error a la similitud estructural ( http://www.cns.nyu.edu/pub/lcv/wang03-reprint.pdf )

FSIM: un índice de similitud de funciones para la evaluación de la calidad de imagen ( https://www4.comp.polyu.edu.hk/~cslzhang/IQA/TIP_IQA_FSIM.pdf )

Entre ellos, SSIM (Evaluación de calidad de imagen: de la visibilidad del error a la similitud estructural) es el más fácil de calcular y su sobrecarga también es pequeña, como se informó en otro documento "Evaluación de la calidad de la imagen basada en la similitud de gradiente" ( https: //www.semanticscholar .org / paper / Image-Quality-Assessment-Based-on-Gradient-Liu-Lin / 2b819bef80c02d5d4cb56f27b202535e119df988 ).

Hay muchos otros enfoques más. Eche un vistazo a Google Académico y busque algo como "diferencia visual", "evaluación de calidad de imagen", etc., si está interesado / realmente se preocupa por el arte.

cyfex
fuente
0

Hay una solución simple y rápida usando numpy calculando el error cuadrático 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
Arian Soltani
fuente