Eu estudei no centro de CS em Novosibirsk pelo segundo ano. Antes de entrar, eu já tinha um emprego na área de TI - trabalhei como analista na Yandex, mas queria me aprofundar mais, aprender algo além do escopo das tarefas atuais e, a conselho de um colega, entrei no centro de CS. Neste artigo, quero falar sobre a prática pela qual passei enquanto estudava.
No início do primeiro semestre, foram oferecidos vários projetos. Minha atenção foi imediatamente concentrada em um projeto chamado "Método para avaliar a cor do grão de uma fotografia". Este tópico foi sugerido por especialistas do Instituto de Citologia e Genética do SB RAS, mas o projeto em si estava mais relacionado à análise e processamento de imagens do que à biologia. Eu o escolhi porque estava interessado em aprendizado de máquina e reconhecimento de padrões e queria praticar nessas áreas.
A essência do projeto
Existe um aplicativo
SeedCounter projetado para contar e medir o tamanho dos grãos de trigo de uma fotografia, a fim de libertar agrônomos do trabalho chato e rotineiro de contar e analisar grãos. Eu precisava estudar a possibilidade de determinar a cor dos grãos de uma fotografia e implementá-la no aplicativo para que os grãos pudessem ser divididos em classes significativas. As classes obtidas podem corresponder, por exemplo, ao conteúdo de substâncias úteis ao ser humano.
Foto de exemplo antes e depois da calibração:

Parece que tirar e entender a cor dos grãos de uma fotografia é uma tarefa simples, especialmente se já existe um algoritmo para encontrar os grãos. No entanto, a cor obtida depende muito da iluminação e a câmera apresenta sua própria distorção. Como resultado, a cor obtida tem pouca relação com as propriedades do próprio grão. Portanto, o objetivo principal era obter cores de grão calibradas, ou seja, como se estivessem em condições ideais de fotografia.
Para ajustar as cores, usamos uma paleta de referência chamada ColorChecker. O ColorChecker está localizado no mesmo quadro dos grãos, suas cores são conhecidas antecipadamente. O aplicativo deve escolher uma conversão de imagem para que as cores no ColorChecker sejam o mais próximo possível das cores de referência conhecidas.
Ou seja, a tarefa foi dividida em três subtarefas:
- encontrando o ColorChecker na imagem,
- cálculo da conversão de cores e aplicação à imagem,
- separação de grãos de acordo com as cores obtidas.
Progresso do trabalho
Primeiro, procuramos o algoritmo de pesquisa ColorChecker já implementado - ele foi encontrado no pacote macduff gratuito. Eu tentei em imagens de teste, o resultado foi ruim: mesmo com um pequeno turno do ColorChecker, poucos quadrados da paleta foram reconhecidos.Depois disso, comecei a procurar outros métodos de pesquisa em que a orientação não é importante. Descobriu-se que existe um método usado para uma tarefa mais geral de encontrar um objeto arbitrário - ele se baseia na seleção de pontos característicos da imagem e na comparação com o modelo. Todos os componentes necessários já estão no OpenCV, portanto não foi difícil implementá-lo.
Para destacar os pontos característicos do OpenCV, usamos vários algoritmos: patenteados (SIFT / SURF) e gratuitos (ORB / FAST). Inicialmente, o método funcionou muito bem com as opções patenteadas, mas era muito lento, o que é crítico quando usado em um dispositivo móvel. Eles também estavam ausentes na versão padrão da biblioteca, o que poderia causar dificuldades ao portar para o Android. Ao usar opções mais rápidas, a qualidade do reconhecimento caiu.
Para aumentar a qualidade do reconhecimento, observei exemplos em que o algoritmo estava errado. Na maioria dos casos, o algoritmo encontrou a localização aproximada do ColorChecker, mas não determinou com precisão sua área. Devido à determinação imprecisa da área do ponto em que as cores foram obtidas para calibração, elas não caíram nos quadrados corretos da paleta, respectivamente, as cores foram restauradas incorretamente. Para consertar isso, tentei reexecutar o algoritmo, obtendo uma aproximação inicial imprecisa e também mudar empiricamente os pontos usados para a calibração, na direção dos quadrados desejados. Depois disso, a qualidade do método aumentou e se tornou aceitável, mesmo para algoritmos inicialmente fracos, mas rápidos:
Algoritmo | Precisão | Tempo de trabalho |
Surf | 75% | 2.8s |
83% (+ 8%) | 14s |
SIFT | 88% | 3.4s |
96% (+ 8%) | 15s |
Brisk | 65% | 0.5s |
93% (+ 28%) | 1.5s |
ORB | 56% | 0.4s |
79% (+ 23%) | 1s |
Para calibração, utilizo regressão simples de mínimos quadrados: linear em cores e em ordens superiores. Nesse sentido, surgiu a questão: como escolher o melhor de vários modelos. As métricas baseadas na proximidade da cor ao padrão deram resultados mistos: uma imagem bem calibrada de acordo com critérios formais pode parecer artificial do ponto de vista humano. A imagem abaixo mostra um exemplo desse efeito. Para ilustrar, em vez de grãos, peguei uma fatia de um tubérculo de batata, pois ele é maior e podemos ver melhor as distorções de cores. Tentamos alterar as métricas, mas no final decidimos que era melhor avaliar o modelo de calibração por sua influência no resultado da tarefa final - separação de grãos.
Fatia de tubérculo de batata, da esquerda para a direita: antes da calibração, após calibração por regressão da primeira, segunda e terceira ordens.

Em seguida, foi necessário montar um conjunto de dados para verificar a qualidade da pesquisa e calibração do ColorChecker e também resolver o problema de separar os grãos por cor. Para isso, coletamos amostras de grãos de diferentes variedades e fotografamos em vários dispositivos, com diferentes fontes de iluminação: artificiais e à luz do dia. Depois disso, corri todas as imagens através do algoritmo de calibração e coletei as cores dos grãos, o algoritmo de reconhecimento de grãos foi entregue a mim pronto. Eu tive que fazer mais de uma iteração desse processo: o reconhecimento de imagens de baixa qualidade nem sempre funcionou bem, eu tive que selecionar heurísticas adicionais para filtrar o lixo.
No final, acabou coletando um conjunto de dados, cuja qualidade me agradou. Eu formalizei o problema da separação de grãos da seguinte forma: nove graus de grãos foram divididos em três classes (branco, vermelho e roxo), cada grão individual teve que ser classificado por cor em uma das três classes. Tentei métodos simples de classificação, como KNN e classificadores lineares, mas não obtive boa precisão. No entanto, mesmo quando vistas com os olhos, ficou claro que as classes se cruzam fortemente umas com as outras e não há superfície divisória aparente entre elas.
Sumário
O principal resultado do trabalho é o algoritmo de pesquisa ColorChecker, que funciona rapidamente e com boa qualidade e a calibração de cores por ele. Pode ser útil não apenas para grãos. Por exemplo, foi possível aplicá-lo na tarefa de analisar espigas de trigo.
Também verifiquei a possibilidade de classificar os grãos por cor - não consegui obter alta precisão aqui, mesmo com a ajuda da calibração.
Mas o resultado mais importante é que adquiri experiência na solução de um problema para o qual não existe um algoritmo pronto nas prateleiras e descobri para mim uma área interessante de visão computacional que, espero, encontrarei no futuro.