2010-03-31 59 views
8

Tarea: Tengo una cámara montada en el extremo de nuestra línea de montaje, que captura imágenes de artículos producidos. Digamos, por ejemplo, que nosotros producimos boletos (con texto e imágenes). Entonces, cada boleto producido es fotografiado y guardado en el disco como imagen. Ahora I desea comprobar estas imágenes guardadas en busca de anomalías (es decir, comparar a una imagen (una plantilla), que está bien). Entonces, si hay un problema con un ticket en nuestra línea de ensamblaje (falta una imagen, una mancha, ...), mi aplicación debería encontrarla (porque su imagen difiere demasiado de mi plantilla ).Comparar imágenes para encontrar las diferencias

Pregunta: ¿Cuál es la forma más fácil de comparar imágenes y encontrar diferencias entre ellas? ¿Debo escribir mis propios métodos, o puedo usar los existentes? Sería muy bueno si me acaba de establecer un valor de tolerancia (es decir, las imágenes pueden diferir de un 1%), poner las dos imágenes en una función y obtener un valor de retorno de verdadero o falso :)

Herramientas: C# o VB. NET, Emgu.CV (contenedor .NET para OpenCV) o algo similar

Respuesta

2

I' Recomiendo mirar AForge Imaging library ya que tiene muchas funciones realmente útiles para este tipo de trabajo.

Existen varios métodos que puede usar:

  1. simple resta (imagen de la plantilla - actual) y ver cuántos píxeles son diferentes. Probablemente desee establecer el umbral de los resultados, es decir, solo incluir píxeles que sean diferentes por 10 o más (por ejemplo).
  2. Si las entradas se pueden mover en el campo de visión, entonces el punto 1) no va a funcionar a menos que pueda localizar el billete de primera. Si, por ejemplo, el boleto es blanco sobre un fondo negro, podría hacer un umbral en la imagen y eso le daría una buena idea de dónde estaba el boleto.
  3. Otra técnica que he usado antes es "Finding Modelo" o "coincidencia de patrones", pero sólo sabe de una biblioteca comercial Matrox Imaging Library (o MIL) que contiene estas funciones, ya que no son triviales.

También debe asegurarse de saber qué partes del ticket son más importantes. Por ejemplo, supongo que un logotipo o marca de agua faltante es un gran problema. Pero algunas áreas pueden tener texto variable, como un número de serie, por lo que es de esperar que sean diferentes. Básicamente, es posible que deba tratar algunas áreas de la imagen de manera diferente a los demás.

1

No conozco los detalles, pero sí sé que en situaciones industriales donde es esencial un alto rendimiento, a veces esto se hace usando redes neuronales. Convierten millones de bits (píxeles de cámara) en 1 (bueno o malo). Quizás esto lo ayude en su búsqueda.

3

No sé mucho sobre OpenCV, pero un poco sobre el procesamiento de imágenes.

El camino a seguir depende de la frecuencia con la que se toman las imágenes nuevas. Un enfoque simplista sería calcular una imagen diferente de su plantilla 'buena' y la imagen de su producto real.

Si las imágenes son 100% idénticas, la imagen resultante debe estar vacía. Si hay píxeles residuales, puede contarlos y tomarlos como una medida de desviación de la norma.

Sin embargo, tendrá que coincidir con la orientación (y probablemente la escala) de una de las imágenes para alinear los bordes, de lo contrario, este enfoque no funcionará.

Si tiene restricciones de timón, puede reducir la información en sus imágenes antes de procesarlas (utilizando por ejemplo una detección de bordes y/o convertirlas a escala de grises o incluso mapa de bits monocromático si las características de su producto son lo suficientemente significativas)

1

Seguramente hay aplicaciones y bibliotecas por ahí que ya hacen lo que está intentando hacer, pero no sé de ninguna manera. Obviamente, uno podría mezclar las dos imágenes y compararlas, pero eso espera que las cosas sean idénticas y no deja margen para diferencias de luz o cosas por el estilo.

Suponiendo que había controlado para los objetos en las imágenes que se están orientados de forma idéntica y colocados de forma idéntica, una cosa que podía hacer es marchar a través de los píxeles de cada imagen, y obtener los valores HSV de cada modo:

Color color1 = Image1.GetPixel(i,j); 
Color color2 = Image2.GetPIxel(i,j); 
float hue1 = color1.GetHue(); 
float sat1 = color1.GetSaturation(); 
float bright1 = color1.GetBrightness(); 
float hue2 = color2.GetHue(); 
float sat2 = color2.GetSaturation(); 
float bright2 = color2.GetBrightness(); 

y hacer algunas comparaciones con esos valores. Eso me permitiría compararlos, creo, con más fiabilidad que con los valores RGB, sobre todo porque quiere incluir algunas tolerancias en su comparación.


Editar:

Sólo por diversión, me escribió una pequeña aplicación de ejemplo que utiliza mi idea anterior. Esencialmente ascendió hasta el número de píxeles cuyo H, S y V valores difieren por una cierta cantidad (I recogió 0,1 como el valor de mi) y después se retiró de la comparación bucles si las H, S, o contadores V superan 38.400 o 2% de los píxeles (0.02 * 1600 * 1200). En el peor de los casos, tomó aproximadamente 2 segundos comparar dos imágenes idénticas. Cuando comparé las imágenes donde una de ellas había sido alterada lo suficiente como para exceder ese valor del 2%, generalmente tomaba una fracción de segundo.

Obviamente, esto probablemente sea demasiado lento si había un montón de imágenes que se producen por segundo, pero pensé que era interesante de todos modos.

+0

Hashing es una buena idea, pero el análisis píxel por píxel en la imagen completa no producirá un rendimiento óptimo debido a la gran cantidad de píxeles por imagen (piensa en 1600 * 1200 bytes o 1.875 MB en escala de grises) – sum1stolemyname

+0

Parece al igual que depende de la velocidad del algoritmo utilizado, ya que cualquier algoritmo que se espera que reconozca las diferencias más de 1-2% tendría que iterar sobre el archivo completo de todos modos. Tal vez hacer una resta rápida de las imágenes, y luego sumar los residuos. Eso sería lo más rápido que podría hacerlo mientras sigue examinando toda la imagen. – tloflin

1

This guy here escribió un código Java simple para simplemente el mismo problema. No será difícil convertirlo en C#, supongo. Está funcionando bien, también se puede encontrar una versión más nueva y más fuerte.

Cuestiones relacionadas