Saltar al contenido

Algoritmo para comparar dos imágenes en C #

Solución:

Aquí hay un enfoque simple con un hash de imagen de 256 bits (MD5 tiene 128 bits)

  1. cambiar el tamaño de la imagen a 16×16 pixel

16 x 16 redimensionado

  1. reducir los colores a negro/blanco (que es igual a cierto/falso en esta salida de consola)

ingrese la descripción de la imagen aquí

  1. leer los valores booleanos en List<bool> – este es el hash

Código:

public static List<bool> GetHash(Bitmap bmpSource)
{
    List<bool> lResult = new List<bool>();         
    //create new image with 16x16 pixel
    Bitmap bmpMin = new Bitmap(bmpSource, new Size(16, 16));
    for (int j = 0; j < bmpMin.Height; j++)
    {
        for (int i = 0; i < bmpMin.Width; i++)
        {
            //reduce colors to true / false                
            lResult.Add(bmpMin.GetPixel(i, j).GetBrightness() < 0.5f);
        }             
    }
    return lResult;
}

Sé, GetPixel no es tan rápido, pero en una imagen de 16×16 píxeles no debería ser el cuello de botella.

  1. compare este hash con los valores de hash de otras imágenes y agregue una tolerancia (número de píxeles que pueden diferir del otro hash)

Código:

List<bool> iHash1 = GetHash(new Bitmap(@"C:mykoala1.jpg"));
List<bool> iHash2 = GetHash(new Bitmap(@"C:mykoala2.jpg"));

//determine the number of equal pixel (x of 256)
int equalElements = iHash1.Zip(iHash2, (i, j) => i == j).Count(eq => eq);

Entonces este código puede encontrar imágenes iguales con:

  • diferentes formatos de archivo (por ejemplo, jpg, png, bmp)
  • rotación (90, 180, 270), volteo horizontal / vertical, cambiando el orden de iteración de i y j
  • diferentes dimensiones (se requiere el mismo aspecto)
  • compresión diferente (se requiere tolerancia en caso de pérdida de calidad como los artefactos jpeg): puede aceptar una igualdad del 99% para que sea la misma imagen y del 50% para ser diferente.
  • color cambiado a geyscaled y al revés (porque el brillo es independiente del color)

Actualización / Mejoras:

después de usar este método por un tiempo, noté algunas mejoras que se pueden hacer

  • reemplazando GetPixel para un mayor rendimiento
  • usar la miniatura exeif en lugar de leer la imagen completa para mejorar el rendimiento
  • en lugar de establecer 0.5f para diferenciar entre claro y oscuro: utilice el brillo medio distintivo de los 256 píxeles. De lo contrario, se supone que las imágenes oscuras / claras son iguales y permite detectar imágenes que tienen un brillo cambiado.
  • si necesita cálculos rápidos, utilice bool[] o List<bool> Si necesita almacenar muchos hashes con la necesidad de ahorrar memoria, use un Bitarray porque un booleano no se almacena en un bit, ¡toma un byte!

Puede comprobar el algoritmo para comparar dos imágenes con el fin de ver los métodos disponibles para la comparación de imágenes.

A menos que desee recrear los algoritmos completos por su cuenta, debe intentar usar bibliotecas ya existentes o al menos parte de su código (siempre que su licencia sea adecuada para usted).

Para una implementación C # de código abierto de detección de bordes y algoritmos de visión por computadora relacionados, puede probar EmguCV, que es un contenedor de OpenCV.

Después de volver a muestrear las imágenes a una resolución común, puede usar una descomposición de Wavelet y comparar los coeficientes de esta descomposición en lugar de las imágenes en sí. Comparar solo los primeros N coeficientes hará que este método sea más robusto al ruido y otros artefactos.

Hay varias implementaciones de C # para wavelets disponibles. Un ejemplo es https://waveletstudio.codeplex.com/

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *