He estado estudiando en el centro de CS en Novosibirsk por segundo año. Antes de ingresar, ya tenía un trabajo en TI: trabajé como analista en Yandex, pero quería desarrollarme más, descubrir algo más allá de las tareas actuales y, por consejo de un colega, ingresé al centro de CS. En este artículo quiero hablar sobre la práctica que pasé mientras estudiaba.
Al comienzo del primer semestre, nos ofrecieron varios proyectos. Mi atención se enganchó inmediatamente a un proyecto llamado "Método para evaluar el color del grano de una fotografía". Este tema fue sugerido por especialistas del Instituto de Citología y Genética de SB RAS, pero el proyecto en sí estaba más relacionado con el análisis y procesamiento de imágenes que con la biología. Lo elegí porque estaba interesado en el aprendizaje automático y el reconocimiento de patrones y quería practicar en estas áreas.
La esencia del proyecto.
Hay una aplicación
SeedCounter diseñada para contar y medir el tamaño de los granos de trigo de una fotografía para liberar a los agrónomos del trabajo aburrido y rutinario de contar y analizar granos. Necesitaba estudiar la posibilidad de determinar el color de los granos de una fotografía e implementar esto en la aplicación para que los granos pudieran dividirse en clases significativas. Las clases obtenidas pueden corresponder, por ejemplo, al contenido de sustancias útiles para los humanos.
Foto de ejemplo antes y después de la calibración:

Parecería que tomar y comprender el color de los granos de una fotografía es una tarea simple, especialmente si ya existe un algoritmo para encontrar los granos. Sin embargo, el color obtenido depende mucho de la iluminación y la cámara introduce su propia distorsión. Como resultado, el color obtenido tiene poca relación con las propiedades del grano mismo. Por lo tanto, el objetivo principal era obtener colores de grano calibrados, es decir como si estuvieran en condiciones ideales de disparo.
Para ajustar los colores, utilizamos una paleta de referencia llamada ColorChecker. ColorChecker se encuentra en el mismo marco que los granos, sus colores se conocen de antemano. La aplicación debe elegir una conversión de imagen de manera que los colores en ColorChecker estén lo más cerca posible de los colores de referencia conocidos.
Es decir, la tarea se dividió en tres subtareas:
- encontrando ColorChecker en la imagen,
- cálculo de conversión de color y aplicación a la imagen,
- separación de granos según los colores obtenidos.
Progreso del trabajo
En primer lugar, buscamos el algoritmo de búsqueda ColorChecker ya implementado, que se encontró en el paquete gratuito macduff. Lo probé en imágenes de prueba, resultó mal: incluso con un pequeño giro de ColorChecker se reconocieron muy pocos cuadrados de la paleta. Después de eso comencé a buscar otros métodos de búsqueda donde la orientación no es importante. Resultó que hay un método utilizado para una tarea más general de encontrar un objeto arbitrario: se basa en la selección de puntos característicos en la imagen y en compararlos con la plantilla. Todos los componentes necesarios ya están en OpenCV, por lo que no fue difícil implementarlo.
Para resaltar los puntos característicos en OpenCV, utilizamos varios algoritmos: ambos patentados (SIFT / SURF) y gratuitos (ORB / FAST). Inicialmente, el método funcionó bastante bien con las opciones patentadas, pero fue muy lento, lo cual es crítico cuando se usa en un dispositivo móvil. También estaban ausentes en la versión estándar de la biblioteca, lo que podría causar dificultades al portar a Android. Al usar opciones más rápidas, la calidad del reconocimiento disminuyó.
Para aumentar la calidad del reconocimiento, miré ejemplos en los que el algoritmo estaba equivocado. En la mayoría de los casos, el algoritmo encontró la ubicación aproximada de ColorChecker, pero no determinó con precisión su área. Debido a la determinación inexacta del área del punto desde el cual se tomaron los colores para la calibración, no cayeron en los cuadrados correctos de la paleta, respectivamente, los colores se restauraron incorrectamente. Para solucionar esto, intenté volver a ejecutar el algoritmo, obteniendo una aproximación inicial inexacta, y también cambiar empíricamente los puntos utilizados para la calibración, en la dirección de los cuadrados deseados. Después de eso, la calidad del método aumentó y se volvió aceptable, incluso para algoritmos inicialmente débiles pero rápidos:
Algoritmo | Precisión | Tiempo de trabajo |
Surfear | 75% | 2.8s |
83% (+ 8%) | 14s |
SIFT | 88% | 3.4s |
96% (+ 8%) | 15s |
Enérgico | 65% | 0.5s |
93% (+ 28%) | 1.5s |
ORB | 56% | 0.4s |
79% (+ 23%) | 1s |
Para la calibración, utilizo la regresión de mínimos cuadrados simples: tanto de color lineal como en órdenes superiores. En consecuencia, surgió la pregunta: cómo elegir el mejor de varios modelos. Las métricas basadas en la proximidad del color al estándar dieron resultados mixtos: una imagen bien calibrada de acuerdo con criterios formales podría parecer poco natural desde el punto de vista humano. La imagen a continuación muestra un ejemplo de tal efecto. Para ilustrar, en lugar de granos, tomé una rodaja de tubérculo de papa, ya que es más grande y podemos ver mejor las distorsiones de color. Intentamos cambiar las métricas, pero al final decidimos que era mejor evaluar el modelo para la calibración por su influencia en el resultado de la tarea final: la separación del grano.
Rodaja de tubérculo de patata, de izquierda a derecha: antes de la calibración, después de la calibración por regresión del primer, segundo y tercer orden.

Luego, fue necesario ensamblar un conjunto de datos para verificar la calidad de la búsqueda y calibración de ColorChecker, y también resolver el problema de separar los granos por color. Para hacer esto, tomamos muestras de granos de diferentes variedades y las fotografiamos en varios dispositivos, con diferentes fuentes de iluminación: tanto artificiales como a la luz del día. Después de eso, ejecuté todas las imágenes a través del algoritmo de calibración y recolecté los colores de los granos, el algoritmo para reconocer los granos me fue entregado listo. Tuve que hacer más de una iteración de este proceso: el reconocimiento en imágenes de baja calidad no siempre funcionó bien, tuve que seleccionar heurísticas adicionales para tamizar la basura.
Al final, resultó recopilar un conjunto de datos, cuya calidad me complació. Formalicé el problema de la separación de granos de la siguiente manera: nueve grados de granos se dividieron en tres clases (blanco, rojo y morado), cada grano individual debía clasificarse por color en una de tres clases. Intenté métodos de clasificación simples como KNN y clasificadores lineales, pero no pude obtener una buena precisión. Sin embargo, incluso cuando se ve a simple vista, estaba claro que las clases se cruzan fuertemente entre sí y no existe una superficie divisoria aparente entre ellas.
Resumen
El resultado principal del trabajo es el algoritmo de búsqueda ColorChecker, que funciona rápidamente y con buena calidad, y la calibración del color por él. Puede ser útil no solo para granos. Por ejemplo, fue posible aplicarlo en la tarea de analizar espigas.
También verifiqué la posibilidad de clasificar los granos por color: no pude obtener una alta precisión aquí, incluso con la ayuda de la calibración.
Pero el resultado más importante es que adquirí experiencia en la solución de un problema para el cual no hay un algoritmo ya establecido en los estantes, y descubrí por mí mismo un área emocionante de visión por computadora, que espero encontrar en el futuro.