c++ español - Procesamiento de imágenes:Mejora de algoritmos para el reconocimiento de 'Coca-Cola Can'




opencv tutorial (20)

Uno de los proyectos más interesantes en los que he trabajado en los últimos dos años fue un proyecto sobre procesamiento de imágenes . El objetivo era desarrollar un sistema para poder reconocer las 'latas' de Coca-Cola (tenga en cuenta que estoy enfatizando la palabra 'latas', verá por qué en un minuto). Puede ver una muestra a continuación, con la lata reconocida en el rectángulo verde con escala y rotación.

Algunas restricciones en el proyecto:

  • El fondo puede ser muy ruidoso.
  • La lata puede tener cualquier escala, rotación o incluso orientación (dentro de límites razonables).
  • La imagen puede tener cierto grado de borrosidad (los contornos pueden no ser completamente rectos).
  • Podría haber botellas de Coca-Cola en la imagen, y el algoritmo solo debería detectar la lata .
  • El brillo de la imagen puede variar mucho (por lo que no puede confiar "demasiado" en la detección de color).
  • La lata podría estar parcialmente oculta en los lados o en el medio y posiblemente en parte oculta detrás de una botella.
  • No podía haber ninguna lata en absoluto en la imagen, en cuyo caso no tenía que encontrar nada y escribir un mensaje que lo dijera.

Así que podrías terminar con cosas complicadas como esta (que en este caso había fallado totalmente mi algoritmo):

Hice este proyecto hace un tiempo y me divertí mucho haciéndolo, y tuve una implementación decente. Aquí hay algunos detalles sobre mi implementación:

Idioma : Hecho en C ++ usando la librería OpenCV .

Preprocesamiento : para el preprocesamiento de la imagen, es decir, transformar la imagen en una forma más simple para darle al algoritmo, usé 2 métodos:

  1. Cambio del dominio de color de RGB a HSV y filtrado basado en el tono "rojo", saturación por encima de un cierto umbral para evitar colores de color naranja y filtrado de valor bajo para evitar tonos oscuros. El resultado final fue una imagen binaria en blanco y negro, donde todos los píxeles blancos representarían los píxeles que coinciden con este umbral. Obviamente, todavía hay mucha basura en la imagen, pero esto reduce la cantidad de dimensiones con las que tienes que trabajar.
  2. Filtrado de ruido mediante el filtrado de mediana (tomando el valor de píxel medio de todos los vecinos y reemplazando el píxel por este valor) para reducir el ruido.
  3. Utilizando el filtro de detección de borde Canny para obtener los contornos de todos los elementos después de 2 pasos precedentes.

Algoritmo : el algoritmo que elegí para esta tarea se tomó de this impresionante libro sobre extracción de características y se llamó Transformada de Hough Generalizada (bastante diferente de la Transformada de Hough normal). Básicamente dice algunas cosas:

  • Puede describir un objeto en el espacio sin conocer su ecuación analítica (como es el caso aquí).
  • Es resistente a las deformaciones de la imagen, como la escala y la rotación, ya que básicamente probará su imagen para cada combinación de factor de escala y factor de rotación.
  • Utiliza un modelo base (una plantilla) que el algoritmo "aprenderá".
  • Cada píxel restante en la imagen de contorno votará por otro píxel que supuestamente será el centro (en términos de gravedad) de su objeto, en función de lo que aprendió del modelo.

Al final, terminará con un mapa de calor de los votos, por ejemplo, aquí todos los píxeles del contorno de la lata votarán por su centro gravitacional, por lo que tendrá muchos votos en el mismo píxel correspondiente al Centro, y verá un pico en el mapa de calor como a continuación:

Una vez que tenga eso, una simple heurística basada en umbrales puede darle la ubicación del píxel central, desde donde puede derivar la escala y la rotación y luego trazar su pequeño rectángulo a su alrededor (la escala final y el factor de rotación obviamente serán relativos a su plantilla original). En teoría al menos ...

Resultados : Ahora, mientras este enfoque funcionó en los casos básicos, faltaba severamente en algunas áreas:

  • ¡Es extremadamente lento ! No estoy enfatizando esto lo suficiente. Se necesitaba casi un día completo para procesar las 30 imágenes de prueba, obviamente porque tenía un factor de escala muy alto para la rotación y la traducción, ya que algunas de las latas eran muy pequeñas.
  • Se perdió completamente cuando las botellas estaban en la imagen, y por alguna razón casi siempre se encontró la botella en lugar de la lata (quizás porque las botellas eran más grandes, por lo tanto tenían más píxeles, por lo tanto más votos)
  • Las imágenes borrosas tampoco fueron buenas, ya que los votos terminaron en píxeles en ubicaciones aleatorias alrededor del centro, lo que terminó con un mapa de calor muy ruidoso.
  • Se logró una variación en la traducción y la rotación, pero no en la orientación, lo que significa que no se reconoció una lata que no estaba directamente orientada hacia el objetivo de la cámara.

¿Puede ayudarme a mejorar mi algoritmo específico , utilizando exclusivamente las funciones de OpenCV , para resolver los cuatro problemas específicos mencionados?

Espero que algunas personas también aprendan algo al respecto, después de todo, creo que no solo las personas que hacen preguntas deben aprender. :)


Answers

¿No es difícil incluso para los humanos distinguir entre una botella y una lata en la segunda imagen (siempre que la región transparente de la botella esté oculta)?

Son casi iguales, excepto en una región muy pequeña (es decir, el ancho en la parte superior de la lata es un poco pequeño, mientras que el envoltorio de la botella tiene el mismo ancho, pero ¿un cambio menor, verdad?)

Lo primero que me vino a la mente fue buscar la tapa roja de la botella. Pero sigue siendo un problema, si no hay una tapa para la botella, o si está parcialmente oculta (como se mencionó anteriormente).

Lo segundo que pensé fue sobre la transparencia de la botella. OpenCV tiene algunos trabajos para encontrar objetos transparentes en una imagen. Compruebe los siguientes enlaces.

En particular, mire esto para ver con qué precisión detectan el vidrio:

Ver el resultado de su implementación:

Dicen que es la implementación del documento "Un marco de contorno activo geodésico para encontrar vidrio" por K. McHenry y J. Ponce, CVPR 2006 .

Puede ser útil en su caso un poco, pero el problema vuelve a surgir si se llena la botella.

Así que creo que aquí puede buscar el cuerpo transparente de las botellas primero o una región roja conectada a dos objetos transparentes lateralmente, que obviamente es la botella. (Cuando se trabaja idealmente, una imagen de la siguiente manera.)

Ahora puede eliminar la región amarilla, es decir, la etiqueta de la botella y ejecutar su algoritmo para encontrar la lata.

De todos modos, esta solución también tiene diferentes problemas como en las otras soluciones.

  1. Sólo funciona si su botella está vacía. En ese caso, tendrá que buscar la región roja entre los dos colores negros (si el líquido de Coca Cola es negro).
  2. Otro problema si se cubre la parte transparente.

Pero de todos modos, si no hay ninguno de los problemas anteriores en las imágenes, esto parece ser una mejor manera.


Necesita un programa que aprenda y mejore la precisión de clasificación de forma orgánica a partir de la experiencia.

Sugeriré un aprendizaje profundo, con un aprendizaje profundo esto se convierte en un problema trivial.

Puede volver a entrenar el modelo v3 inicial en Tensorflow:

Cómo volver a entrenar la capa final de inicio para nuevas categorías .

En este caso, estará entrenando una red neuronal convolucional para clasificar un objeto como si una coca-cola puede o no.


Mirando a la forma

Eche un vistazo a la forma de la parte roja de la lata / botella. Observe cómo la lata disminuye ligeramente en la parte superior mientras que la etiqueta de la botella es recta. Puede distinguir entre estos dos comparando el ancho de la parte roja a lo largo de la misma.

Mirando los aspectos más destacados

Una forma de distinguir entre botellas y latas es el material. Una botella está hecha de plástico, mientras que una lata está hecha de aluminio metal. En situaciones suficientemente bien iluminadas, observar la especularidad sería una forma de distinguir una etiqueta de botella de una etiqueta de lata.

Por lo que puedo decir, así es como un humano diría la diferencia entre los dos tipos de etiquetas. Si las condiciones de iluminación son deficientes, es probable que haya cierta incertidumbre al distinguir las dos de todos modos. En ese caso, tendría que poder detectar la presencia de la botella transparente / translúcida.


Me gusta el desafío y quería dar una respuesta, lo cual resuelve el problema, creo.

  1. Extraiga características (puntos clave, descriptores como SIFT, SURF) del logotipo
  2. Haga coincidir los puntos con una imagen modelo del logotipo (utilizando Matcher como Brute Force)
  3. Estimar las coordenadas del cuerpo rígido (problema PnP - SolvePnP)
  4. Estimar la posición de la tapa según el cuerpo rígido.
  5. Realice una retroproyección y calcule la posición del píxel de la imagen (ROI) de la tapa de la botella (supongo que tiene los parámetros intrínsecos de la cámara)
  6. Verifique con un método si la tapa está ahí o no. Si hay, entonces esta es la botella

La detección de la tapa es otro problema. Puede ser complicado o simple. Si yo fuera usted, simplemente revisaría el histograma de color en el ROI para una decisión simple.

Por favor, dé su opinión si estoy equivocado. Gracias.


Hay un paquete de visión artificial llamado HALCON de MVTec cuyas demostraciones podrían darle buenas ideas de algoritmos. Hay muchos ejemplos similares a su problema que podría ejecutar en modo de demostración y luego observar los operadores en el código y ver cómo implementarlos desde los operadores existentes de OpenCV.

He usado este paquete para crear prototipos de algoritmos complejos rápidamente para problemas como este y luego encontrar la forma de implementarlos utilizando las características existentes de OpenCV. En particular, para su caso, podría intentar implementar en OpenCV la funcionalidad incorporada en el operador find_scaled_shape_model . Algunos operadores señalan el artículo científico sobre la implementación del algoritmo, que puede ayudar a descubrir cómo hacer algo similar en OpenCV. Espero que esto ayude...


Lo primero que buscaría es el color, como el ROJO, al detectar el efecto de ojos rojos en una imagen, hay un cierto rango de color para detectar, algunas características al respecto, considerando el área circundante y la distancia del otro ojo si Es de hecho visible en la imagen.

1: La primera característica es el color y el rojo es muy dominante. Después de detectar la Coca Cola Red, hay varios elementos de interés 1A: ¿Qué tan grande es esta área roja (es la cantidad suficiente para hacer una determinación de una lata verdadera o no? 10 píxeles probablemente no sea suficiente), 1B: ¿Contiene? El color de la etiqueta - "Coca-Cola" u onda. 1B1: ¿Es suficiente considerar una alta probabilidad de que sea una etiqueta?

El elemento 1 es una especie de atajo: antes del proceso, si esa imagen no existe en la imagen, continúe.

Entonces, si ese es el caso, entonces puedo utilizar ese segmento de mi imagen y comenzar a buscar un poco más de zoom en el área en cuestión un poco, básicamente mirar la región / bordes circundantes ...

2: Dada la ID de área de imagen anterior en 1: verifique los puntos circundantes [bordes] del elemento en cuestión. A: ¿Hay lo que parece ser una lata arriba o abajo - plata? B: Una botella puede parecer transparente, pero también lo puede ser una mesa de vidrio. Entonces, ¿hay una mesa / estante de vidrio o un área transparente? Si es así, hay varias salidas posibles. Una botella PUEDE tener una tapa roja, puede que no, pero debe tener la forma de la parte superior de la botella / tornillos de rosca, o una tapa. C: Incluso si esto falla A y B, aún puede ser una lata parcial. Esto es más complejo cuando es parcial porque una botella parcial / lata parcial puede parecer lo mismo, por lo que es posible que haya más procesamiento de la medición del borde de la región Roja. al borde ... botella pequeña podría ser similar en tamaño ...

3: Después del análisis anterior, es cuando miraría las letras y el logotipo de wave, porque puedo orientar mi búsqueda de algunas de las letras en las palabras, ya que es posible que no tenga todo el texto porque no tengo todas las letras. puede, la onda se alinearía en ciertos puntos con el texto (a lo largo de la distancia) para que pudiera buscar esa probabilidad y saber qué letras deberían existir en ese punto de la onda en la distancia x.


No tengo conocimiento de OpenCV, pero viendo el problema de forma lógica, creo que podría diferenciar entre botella y lata cambiando la imagen que está buscando, es decir, Coca Cola. Debe incorporar hasta la parte superior de la lata, ya que en el caso de la lata hay un forro de plata en la parte superior de la coca cola y en el caso de la botella no habrá tal adorno.

Pero, obviamente, este algoritmo fallará en los casos donde la parte superior de la lata esté oculta, pero en tal caso, incluso el ser humano no podrá diferenciar entre las dos (si solo es visible la porción de coca cola de la botella / lata)


Como alternativa a todas estas buenas soluciones, puede entrenar su propio clasificador y hacer que su aplicación sea robusta a los errores. Como ejemplo, puede usar Haar Training , que proporciona un buen número de imágenes positivas y negativas de su objetivo.

Puede ser útil extraer solo latas y puede combinarse con la detección de objetos transparentes.


Un enfoque alternativo sería extraer características (puntos clave) utilizando la transformación de característica invariante de escala (SIFT) o las características robustas aceleradas (SURF).

Se implementa en OpenCV 2.3.1.

Puede encontrar un buen ejemplo de código usando características en Features2D + Homography para encontrar un objeto conocido

Ambos algoritmos son invariantes para el escalado y la rotación. Ya que trabajan con características, también puede manejar la occlusion (siempre que haya suficientes puntos clave visibles).

Fuente de la imagen: ejemplo de tutorial

El procesamiento toma unos cientos de ms para SIFT, SURF es un poco más rápido, pero no es adecuado para aplicaciones en tiempo real. ORB usa FAST, que es más débil con respecto a la invariancia de rotación.

Los papeles originales


Hmm, realmente creo que tengo algo (esta es la pregunta más interesante de la historia, por lo que sería una pena no seguir buscando la respuesta "perfecta", aunque se haya encontrado una respuesta aceptable). .

Una vez que encuentre el logotipo, sus problemas están a medio hacer. Entonces solo tienes que descubrir las diferencias entre lo que está alrededor del logotipo. Además, queremos hacer lo menos posible. Creo que esta es realmente esta parte fácil ...

¿Qué hay alrededor del logo? Para una lata, podemos ver el metal, que a pesar de los efectos de la iluminación, no cambia nada en su color básico. Mientras sepamos el ángulo de la etiqueta, podemos saber qué hay directamente sobre ella, así que estamos viendo la diferencia entre estos:

Aquí, lo que está arriba y debajo del logotipo es completamente oscuro, de color consistente. Relativamente fácil en ese sentido.

Aquí, lo que está arriba y abajo es claro, pero sigue siendo de color consistente. Es completamente plateado, y el metal plateado parece bastante raro, al igual que los colores plateados en general. Además, está en un deslizamiento delgado y lo suficientemente cerca del rojo que ya se ha identificado para que pueda trazar su forma en toda su longitud para calcular un porcentaje de lo que puede considerarse el anillo metálico de la lata. En realidad, solo necesitas una pequeña fracción de eso en cualquier lugar a lo largo de la lata para saber que es parte de ella, pero aún necesitas encontrar un equilibrio que asegure que no sea solo una botella vacía con algo de metal detrás.

Y por último, el complicado. Pero no es tan complicado, una vez que solo vamos por lo que podemos ver directamente arriba (y abajo) la envoltura roja. Es transparente, lo que significa que mostrará lo que está detrás de él. Eso es bueno, porque las cosas que están detrás no son tan consistentes en color como el metal circular plateado de la lata. Podría haber muchas cosas diferentes detrás de esto, que nos dirían que es una botella vacía (o llena de líquido claro), o un color uniforme, lo que podría significar que está llena de líquido o que la botella está simplemente frente a un color solido. Estamos trabajando con lo que está más cerca de la parte superior e inferior, y las posibilidades de que los colores correctos estén en el lugar correcto son relativamente escasas. Sabemos que es una botella, porque no tiene ese elemento visual clave de la lata, que es relativamente simplista en comparación con lo que podría haber detrás de una botella.

(este último fue el mejor que pude encontrar de una botella grande de coca cola vacía; curiosamente, la tapa y el anillo son amarillos, lo que indica que probablemente no se debe confiar en el enrojecimiento de la tapa)

En la rara circunstancia de que haya un tono de plata similar detrás de la botella, incluso después de la extracción del plástico, o si la botella está de alguna manera llena con el mismo tono de líquido plateado, podemos recurrir a lo que podemos estimar aproximadamente como el Forma de la plata, que, como he mencionado, es circular y sigue la forma de la lata. Pero aunque carezco de cierto conocimiento en el procesamiento de imágenes, suena lento. Mejor aún, ¿por qué no deducir esto por una vez verificando los lados del logotipo para asegurarse de que no haya nada del mismo color plateado allí? Ah, pero ¿y si hay el mismo tono de plata detrás de una lata? Entonces, sí tenemos que prestar más atención a las formas, mirando de nuevo la parte superior e inferior de la lata.

Dependiendo de lo impecable que sea todo esto, podría ser muy lento, pero creo que mi concepto básico es verificar primero las cosas más fáciles y cercanas. Ir por las diferencias de color en torno a la forma ya emparejada (que parece la parte más trivial de esto de todos modos) antes de ir al esfuerzo de averiguar la forma de los otros elementos. Para enumerarlo, va:

  • Encuentre la atracción principal (fondo del logotipo rojo, y posiblemente el mismo logotipo para la orientación, aunque en caso de que la lata sea rechazada, debe concentrarse solo en el rojo)
  • Verifique la forma y la orientación, una vez más a través del enrojecimiento muy distintivo
  • Compruebe los colores alrededor de la forma (ya que es rápido y sin dolor)
  • Finalmente, si es necesario, verifique la forma de esos colores alrededor de la atracción principal para la redondez correcta.

En el caso de que no pueda hacer esto, probablemente significa que la parte superior e inferior de la lata están cubiertas, y las únicas cosas posibles que un humano podría haber usado para hacer una distinción confiable entre la lata y la botella es la oclusión y la reflexión. de la lata, que sería una batalla mucho más difícil de procesar. Sin embargo, para ir aún más lejos, puede seguir el ángulo de la lata / botella para verificar si hay más rasgos de botella, utilizando las técnicas de escaneo semitransparentes que se mencionan en las otras respuestas.

Las pesadillas adicionales interesantes podrían incluir una lata situada cómodamente detrás de la botella a una distancia tal que el metal de la misma aparezca por encima y por debajo de la etiqueta, que aún fallaría mientras se esté escaneando a lo largo de todo el rojo. etiqueta - que en realidad es más un problema porque no está detectando una lata donde podría tener, en lugar de considerar que en realidad está detectando una botella, incluida la lata por accidente. ¡El vaso está medio vacío, en ese caso!

Como un descargo de responsabilidad, no tengo experiencia ni he pensado en el procesamiento de imágenes fuera de esta pregunta, pero es tan interesante que me hizo pensar mucho en ello, y después de leer todas las demás respuestas, considero que esto posiblemente sea La forma más fácil y eficiente de hacerlo. Personalmente, me alegro de no tener que pensar en programar esto.

EDITAR

Además, mira este dibujo que hice en MS Paint ... Es absolutamente horrible y bastante incompleto, pero solo por la forma y los colores, puedes adivinar lo que probablemente será. En esencia, estas son las únicas cosas que uno necesita para molestarse en escanear. Cuando miras esa forma muy distintiva y la combinación de colores tan cerca, ¿qué otra cosa podría ser? Lo que no pinté, el fondo blanco, debe considerarse "algo inconsistente". Si tuviera un fondo transparente, podría repasar casi cualquier otra imagen y aún podría verse.


Me gusta tu pregunta, independientemente de si está fuera de tema o no: P

Un interesante aparte; Acabo de completar una asignatura en mi carrera en la que cubrimos robótica y visión computacional. Nuestro proyecto para el semestre fue increíblemente similar al que usted describe.

Tuvimos que desarrollar un robot que utilizara un Xbox Kinect para detectar botellas de coque y latas en cualquier orientación en una variedad de condiciones ambientales y de iluminación. Nuestra solución consistió en utilizar un filtro de paso de banda en el canal de Tono en combinación con la transformada de círculo de Hough. Pudimos restringir un poco el entorno (pudimos elegir dónde y cómo ubicar el robot y el sensor Kinect), de lo contrario íbamos a utilizar las transformaciones SIFT o SURF.

Puedes leer sobre nuestro enfoque en mi blog sobre el tema :)


Detectaré rectángulos rojos: RGB -> HSV, filtro rojo -> imagen binaria, close (dilatar y luego erosionar, conocido como imclose en matlab)

Luego mira a través de rectángulos de mayor a menor. Los rectángulos que tienen rectángulos más pequeños en una posición / escala conocida pueden eliminarse (asumiendo que las proporciones de la botella sean constantes, el rectángulo más pequeño sería una tapa de botella).

Esto te dejaría con rectángulos rojos, entonces necesitarás detectar de alguna manera los logotipos para saber si son un rectángulo rojo o una lata de coca. ¿Te gusta OCR, pero con un logo conocido?


Si no está limitado a solo una cámara que no estaba en una de sus restricciones, quizás pueda usar un sensor de rango como el Xbox Kinect . Con esto puede realizar la segmentación coincidente de la imagen basada en la profundidad y el color. Esto permite una separación más rápida de los objetos en la imagen. Luego puede usar técnicas de combinación ICP o técnicas similares para igualar la forma de la lata en lugar de solo su contorno o color, y dado que es cilíndrico, esta puede ser una opción válida para cualquier orientación si tiene un escaneo 3D del objetivo en 3D. Estas técnicas son a menudo bastante rápidas, especialmente cuando se usan para un propósito específico que debe resolver su problema de velocidad.

También podría sugerir, no necesariamente por precisión o velocidad, sino por diversión que podría usar una red neuronal entrenada en su imagen segmentada de tono para identificar la forma de la lata. Estos son muy rápidos y con frecuencia pueden tener una precisión de hasta el 80/90%. La capacitación sería un proceso un poco largo, ya que tendría que identificar manualmente la lata en cada imagen.


Por favor, eche un vistazo al rastreador Predator de Zdenek Kalal. Requiere algo de entrenamiento, pero puede aprender activamente cómo el objeto rastreado mira diferentes orientaciones y escalas y lo hace en tiempo real.

El código fuente está disponible en su sitio. Está en MATLAB , pero quizás haya una implementación de Java ya realizada por un miembro de la comunidad. He vuelto a implementar con éxito la parte del rastreador de TLD en C #. Si recuerdo correctamente, TLD está utilizando Ferns como detector de puntos clave. En su lugar, utilizo SURF o SIFT (ya sugerido por @stacker) para volver a adquirir el objeto si el rastreador lo perdió. Los comentarios del rastreador facilitan la creación con el tiempo de una lista dinámica de plantillas de tamizado / navegación que con el tiempo permiten volver a adquirir el objeto con una precisión muy alta.

Si está interesado en mi implementación de C # del rastreador, no dude en preguntar.


Esto puede ser una idea muy ingenua (o puede que no funcione en absoluto), pero las dimensiones de todas las latas de coque son fijas. Por lo tanto, si la misma imagen contiene una lata y una botella, puede diferenciarlas por consideraciones de tamaño (las botellas serán más grandes). Ahora, debido a la falta de profundidad (es decir, mapeo 3D a mapeo 2D) es posible que una botella aparezca encogida y no haya una diferencia de tamaño. Puede recuperar cierta información de profundidad usando stereo-imaging y luego recuperar el tamaño original.


Si está interesado en que sea en tiempo real, entonces lo que necesita es agregar un filtro de preprocesamiento para determinar qué se escanea con el material de trabajo pesado. Un buen filtro de preprocesamiento rápido y en tiempo real que le permitirá escanear cosas que tienen más probabilidades de ser una coca-cola puede antes que pasar a más cosas dudosas es algo como esto: busque en la imagen los parches más grandes de color que están a cierta tolerancia de distancia del sqrt(pow(red,2) + pow(blue,2) + pow(green,2)) de su lata de coca-cola. Comience con una tolerancia de color muy estricta y avance hacia tolerancias de color más indulgentes. Luego, cuando su robot se queda sin un tiempo asignado para procesar el marco actual, utiliza las botellas encontradas actualmente para sus propósitos. Tenga en cuenta que tendrá que modificar los colores RGB en sqrt(pow(red,2) + pow(blue,2) + pow(green,2)) para que queden bien.

Además, esto parece muy tonto, pero ¿se aseguró de activar las optimizaciones del compilador -oFast cuando compiló su código C?


Hay un montón de descriptores de colores que se utilizan para reconocer objetos, el documento a continuación compara muchos de ellos. Son especialmente potentes cuando se combinan con SIFT o SURF. El SURF o SIFT por sí solos no son muy útiles en una imagen de lata de coca cola porque no reconocen muchos puntos de interés, necesita la información de color para ayudar. Uso BIC (Clasificación de píxeles de borde / interior) con SURF en un proyecto y funcionó muy bien para reconocer objetos.

Descriptores de color para la recuperación de imágenes web: un estudio comparativo


Realmente me gustan las respuestas de Darren Cook y stacker a este problema. Estaba en medio de poner mis pensamientos en un comentario sobre ellos, pero creo que mi enfoque es demasiado en forma de respuesta para no salir de aquí.

En breve resumen, ha identificado un algoritmo para determinar que un logotipo de Coca-Cola está presente en una ubicación particular en el espacio. Ahora está tratando de determinar, para orientaciones arbitrarias y factores de escalamiento arbitrarios, una heurística adecuada para distinguir las latas de Coca-Cola de otros objetos, incluidos: botellas , carteles publicitarios , anuncios y parafernalia de Coca-Cola, todos asociados con este logotipo icónico. No mencionó muchos de estos casos adicionales en la declaración de su problema, pero creo que son vitales para el éxito de su algoritmo.

El secreto aquí es determinar qué características visuales contiene una lata o, a través del espacio negativo, qué características están presentes para otros productos de Coca-Cola que no están presentes para las latas. Para ese fin, la respuesta principal actual esboza un enfoque básico para seleccionar "lata" si y solo si no se identifica la "botella", ya sea por la presencia de una tapa de botella, líquido u otras heurísticas visuales similares.

El problema es que esto se rompe. Una botella podría, por ejemplo, estar vacía y carecer de la presencia de una tapa, dando lugar a un falso positivo. O bien, podría ser una botella parcial con características adicionales modificadas, lo que lleva nuevamente a la detección falsa. No hace falta decir que esto no es elegante ni efectivo para nuestros propósitos.

Para este fin, los criterios de selección más correctos para las latas parecen ser los siguientes:

  • ¿Es correcta la forma de la silueta del objeto, como dibujó en su pregunta ? Si es así, +1.
  • Si asumimos la presencia de luz natural o artificial, ¿detectamos un contorno cromado en la botella que indica si está hecho de aluminio? Si es así, +1.
  • ¿Determinamos que las propiedades especulares del objeto son correctas, en relación con nuestras fuentes de luz ( enlace de video ilustrativo sobre la detección de fuentes de luz )? Si es así, +1.
  • ¿Podemos determinar otras propiedades sobre el objeto que lo identifiquen como una lata, incluyendo, entre otros, el sesgo de imagen topológica del logotipo, la orientación del objeto, la yuxtaposición del objeto (por ejemplo, en una superficie plana)? como una mesa o en el contexto de otras latas), y la presencia de una lengüeta de tiro? Si es así, para cada uno, +1.

Su clasificación podría parecerse a la siguiente:

  • Para cada partido candidato, si se detectó la presencia de un logotipo de Coca Cola, dibuje un borde gris.
  • Para cada partida sobre +2, dibuja un borde rojo.

Esto resalta visualmente al usuario lo que se detectó, enfatizando los positivos débiles que pueden, correctamente, detectarse como latas destrozadas.

La detección de cada propiedad conlleva una complejidad de tiempo y espacio muy diferente, y para cada enfoque, un paso rápido a través de http://dsp.stackexchange.com es más que razonable para determinar el algoritmo más correcto y más eficiente para sus propósitos. Mi intención aquí es, pura y simplemente, enfatizar que la detección de algo es una lata mediante la invalidación de una pequeña porción del espacio de detección candidato no es la solución más robusta o efectiva para este problema, e idealmente, debe tomar las medidas adecuadas. en consecuencia.

Y hey, felicidades por la publicación de Hacker News! En general, esta es una pregunta tremendamente digna de la publicidad que recibió. :)


Aprendizaje profundo

Reúna al menos unos cientos de imágenes que contengan latas de cola, haga anotaciones en el cuadro delimitador alrededor de ellas como clases positivas, incluya botellas de cola y otros productos de cola etiquetados clases negativas así como objetos aleatorios.

A menos que recopile un conjunto de datos muy grande, realice el truco de usar funciones de aprendizaje profundo para conjuntos de datos pequeños. Lo ideal es utilizar una combinación de máquinas de vectores de soporte (SVM) con redes neuronales profundas.

Una vez que alimenta las imágenes a un modelo de aprendizaje profundo previamente entrenado (por ejemplo, GoogleNet), en lugar de usar la capa de decisión (final) de la red neuronal para hacer clasificaciones, use los datos de las capas anteriores como funciones para capacitar a su clasificador.

OpenCV y Google Net: http://docs.opencv.org/trunk/d5/de7/tutorial_dnn_googlenet.html

OpenCV y SVM: http://docs.opencv.org/2.4/doc/tutorials/ml/introduction_to_svm/introduction_to_svm.html


Esto es lo que se me ocurrió después de un poco de experimentación:

import cv, cv2, numpy as np
import sys

def get_new(old):
    new = np.ones(old.shape, np.uint8)
    cv2.bitwise_not(new,new)
    return new

if __name__ == '__main__':
    orig = cv2.imread(sys.argv[1])

    # these constants are carefully picked
    MORPH = 9
    CANNY = 84
    HOUGH = 25

    img = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY)
    cv2.GaussianBlur(img, (3,3), 0, img)


    # this is to recognize white on white
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(MORPH,MORPH))
    dilated = cv2.dilate(img, kernel)

    edges = cv2.Canny(dilated, 0, CANNY, apertureSize=3)

    lines = cv2.HoughLinesP(edges, 1,  3.14/180, HOUGH)
    for line in lines[0]:
         cv2.line(edges, (line[0], line[1]), (line[2], line[3]),
                         (255,0,0), 2, 8)

    # finding contours
    contours, _ = cv2.findContours(edges.copy(), cv.CV_RETR_EXTERNAL,
                                   cv.CV_CHAIN_APPROX_TC89_KCOS)
    contours = filter(lambda cont: cv2.arcLength(cont, False) > 100, contours)
    contours = filter(lambda cont: cv2.contourArea(cont) > 10000, contours)

    # simplify contours down to polygons
    rects = []
    for cont in contours:
        rect = cv2.approxPolyDP(cont, 40, True).copy().reshape(-1, 2)
        rects.append(rect)

    # that's basically it
    cv2.drawContours(orig, rects,-1,(0,255,0),1)

    # show only contours
    new = get_new(img)
    cv2.drawContours(new, rects,-1,(0,255,0),1)
    cv2.GaussianBlur(new, (9,9), 0, new)
    new = cv2.Canny(new, 0, CANNY, apertureSize=3)

    cv2.namedWindow('result', cv2.WINDOW_NORMAL)
    cv2.imshow('result', orig)
    cv2.waitKey(0)
    cv2.imshow('result', dilated)
    cv2.waitKey(0)
    cv2.imshow('result', edges)
    cv2.waitKey(0)
    cv2.imshow('result', new)
    cv2.waitKey(0)

    cv2.destroyAllWindows()

No es perfecto, pero al menos funciona para todas las muestras:







c++ algorithm image-processing opencv