Um dos projetos mais interessantes em que trabalhei nos últimos dois anos foi um projeto sobre processamento de imagens . O objetivo era desenvolver um sistema para reconhecer 'latas' da Coca-Cola (observe que estou enfatizando a palavra 'latas', você verá o porquê em um minuto). Você pode ver uma amostra abaixo, com a lata reconhecida no retângulo verde com escala e rotação.
Algumas restrições no projeto:
- O fundo pode ser muito barulhento.
- A lata pode ter qualquer escala ou rotação ou mesmo orientação (dentro de limites razoáveis).
- A imagem pode ter algum grau de imprecisão (os contornos podem não ser totalmente retos).
- Pode haver garrafas de Coca-Cola na imagem e o algoritmo deve detectar apenas a lata !
- O brilho da imagem pode variar muito (então você não pode confiar "demais" na detecção de cores).
- A lata pode estar parcialmente escondida nas laterais ou no meio e possivelmente parcialmente escondida atrás de uma garrafa.
- Não havia nenhuma lata na imagem; nesse caso, você não precisava encontrar nada e escrever uma mensagem dizendo isso.
Então você pode acabar com coisas complicadas como esta (que neste caso tiveram meu algoritmo totalmente falho):
Eu fiz esse projeto há um tempo atrás, e me diverti muito fazendo isso, e eu tive uma implementação decente. Aqui estão alguns detalhes sobre minha implementação:
Idioma : feito em C ++ usando a biblioteca OpenCV .
Pré-processamento : Para o pré-processamento de imagem, ou seja, transformar a imagem em uma forma mais bruta para fornecer ao algoritmo, usei 2 métodos:
- Alterando o domínio de cores de RGB para HSV e a filtragem com base em matiz "vermelho", saturação acima de um determinado limite para evitar cores alaranjadas e filtragem de baixo valor para evitar tons escuros. O resultado final foi uma imagem em preto e branco binária, na qual todos os pixels brancos representariam os pixels que correspondem a esse limite. Obviamente, ainda há muita porcaria na imagem, mas isso reduz o número de dimensões com as quais você precisa trabalhar.
- Filtragem de ruído usando filtragem mediana (pegando o valor mediano do pixel de todos os vizinhos e substituindo o pixel por esse valor) para reduzir o ruído.
- Usando o Canny Edge Detection Filter para obter os contornos de todos os itens após 2 etapas anteriores.
Algoritmo : O próprio algoritmo que eu escolhi para esta tarefa foi retirado deste livro incrível sobre extração de recursos e chamado Generalized Hough Transform (bem diferente da Hough Transform normal). Basicamente, diz algumas coisas:
- Você pode descrever um objeto no espaço sem conhecer sua equação analítica (que é o caso aqui).
- É resistente a deformações da imagem, como redimensionamento e rotação, pois basicamente testará sua imagem para todas as combinações de fator de escala e fator de rotação.
- Ele usa um modelo base (um modelo) que o algoritmo "aprenderá".
- Cada pixel restante na imagem de contorno votará em outro pixel que supostamente será o centro (em termos de gravidade) do seu objeto, com base no que aprendeu com o modelo.
No final, você acaba com um mapa de calor dos votos, por exemplo, aqui todos os pixels do contorno da lata votarão em seu centro gravitacional, para que você tenha muitos votos no mesmo pixel correspondente ao centro e verá um pico no mapa de calor como abaixo:
Depois disso, uma heurística simples baseada em limite pode fornecer a localização do pixel central, a partir do qual você pode derivar a escala e a rotação e, em seguida, plotar seu pequeno retângulo em torno dele (a escala final e o fator de rotação obviamente serão relativos ao seu tamanho). modelo original). Em teoria, pelo menos ...
Resultados : Agora, embora essa abordagem funcionasse nos casos básicos, faltava muito em algumas áreas:
- É extremamente lento ! Não estou estressando isso o suficiente. Foi necessário quase um dia inteiro para processar as 30 imagens de teste, obviamente porque eu tinha um fator de escala muito alto para rotação e translação, já que algumas latas eram muito pequenas.
- Perdeu-se completamente quando havia garrafas na imagem e, por algum motivo, quase sempre encontrou a garrafa em vez da lata (talvez porque as garrafas fossem maiores, tinham mais pixels, mais votos)
- Imagens confusas também não eram boas, uma vez que os votos acabavam em pixels em locais aleatórios ao redor do centro, terminando com um mapa de calor muito barulhento.
- A variação na translação e rotação foi alcançada, mas não na orientação, o que significa que uma lata que não estava diretamente voltada para a objetiva da câmera não foi reconhecida.
Você pode me ajudar a melhorar meu algoritmo específico , usando exclusivamente recursos OpenCV , para resolver os quatro problemas específicos mencionados?
Espero que algumas pessoas também aprendam algo com isso, afinal, acho que não apenas as pessoas que fazem perguntas devem aprender. :)