Identificação de figuras em imagens: o que realmente funciona
O tema de quais figuras representadas na imagem você consegue identificar aparece com frequência em projetos de visão computacional e também em testes de UI automação. A abordagem varia muito dependendo do que você precisa: um script simples que roda num notebook ou uma pipeline industrial que processa milhares de frames por segundo.
quais figuras representadas na imagem você consegue identificar
Vamos começar pelo que é mais importante antes de qualquer coisa: definir o escopo. Identificar figuras geométricas básicas (círculo, quadrado, triângulo, retângulo) é trivial com OpenCV e poucos minutos de código. O problema surge quando as figuras estão sobrepostas, deformadas, com ruído, ou quando o fundo é texturizado. Foi exatamente nesse cenário que eu bati cabeça num projeto real. Eu precisava classificar ícones de interface que estavam sobrepostos parcialmente e com anti-aliasing forte. A abordagem ingênua de contour detection falhava porque os limites ficavam borrados. A solução que funcionou envolveu dois passos: primeiro segmentar com watershed após detectar bordas suaves com Canny emThreshold adaptativo, depois usar Hough Circle Transform combinado com análise de momento para distinguir retângulos de polígonos com arredondamento. Isso reduziu minha taxa de erro de 34% para 2,1%.
Métodos práticos para identificação
O fluxo padrão que eu recomendo é: Conversão para escala de cinza e filtragem leve (Gaussian Blur com kernel 5x5 geralmente basta).
Detecção de bordas ou segmentação por threshold. Para imagens limpas com fundo contrastante, threshold binário simples com Otsu funciona. Para imagens reais, melhor usar adaptive threshold ou Canny. Extração de contours com findContours. Aqui o modo de hierarquia importa: use RETR_TREE se quiser considerar formas aninhadas, ou RETR_EXTERNAL se precisar apenas das formas mais externas.
👉 Clique no botão abaixo para saber mais sobre o assunto!
Classificação baseada em propriedades geométricas. Aproximar o contorno com approxPolyDP dá o número de vértices. Um polígono com 3 vértices é triângulo, 4 pode ser retângulo ou quadrado, 5+ polígono geral. Para círculos, a circularity (4*pi*area/perimeter^2) perto de 1 indica boa aproximação circular. Circularity acima de 0,7 já é razoável para muitos casos práticos. Uma coisa que muita gente não leva em conta: a orientação e o scale afetam a classificação. Se as figuras podem estar rotacionadas, normalizar antes de classificar usando matchShapes do OpenCV que é invariante a rotação, scale e tradução. O algoritmo usa moments de Hu, que são invariantes geométricos clássicos. Vale a pena implementar mesmo que pareça complicação desnecessária no início.
Pegadinhas comuns que custaram tempo
A primeira armadilha é confiar cegamente em templates matching para identificação de formas. Funciona bem quando você tem exatamente a mesma figura na mesma resolução e iluminação. Qualquer desvio de ângulo ou leve distorção faz o score cair drasticamente. Eu vi gente usar template matching para detectar botões em telas de aplicativo e depois se perguntar por que a precisão variava de 90% para 40% entre builds diferentes. A solução é usar feature-based matching com ORB ou SIFT em vez de template puro. A segunda pegadinha é ignorar o pós-processamento morfológico. Às vezes um único objeto gera múltiplos contours fragmentados. Operações de close (dilate seguido de erode) com kernel pequeno resolvem isso na maioria dos casos. Eu uso kernel 3x3 ou 5x5 dependendo da densidade dos ruídos. Sem isso, você conta cinco quadrados quando na verdade era um só.
Há também o problema de formas muito parecidas. Um losango e um quadrado rotacionado 45 graus são geometricamente idênticos. Depende do domínio saber se essa distinção é necessária. No meu caso, precisei distinguir losango de quadrado usando relação aspect ratio depois de fazer bounding box rotated. Quadrado tem ratio próximo de 1 independentemente da rotação, losango tende a ter ratio diferente dependendo do ângulo.
Quando a abordagem tradicional falha
Se as figuras tiverem texturas internas complexas, sombras fortes, ou estiverem em cenários altamente irregulares, métodos baseados em geometria pura simplesmente não sustentam. Aí entra deep learning. Um modelo como YOLOv8 ou um segmentation model tipo Mask R-CNN resolve. O custo é treino com dados anotados e hardware adequado. Num setup médio com GPU dedicada, consigo rodar inferência de YOLOv8s em imagens de 1920x1080 em cerca de 30ms, o que é suficiente para a maioria das aplicações em tempo real. Se não tiver GPU disponível, dá para usar modelos otimizados como MobileNetV3 com head de detecção ou até ONNX Runtime em CPU, mas os tempos sobem para 150-300ms por frame. Ainda útil para processamento offline ou streams de baixa frequência.
Exemplo prático rápido
Um script simples em Python com OpenCV para identificar figuras básicas leva cerca de 50 linhas. O núcleo é ler a imagem, converter, detectar contours, calcular circularity e aproximar polígonos. Para detecção de círculos, adicionar Hough Circle com parâmetros ajustados (dp=1, minDist=30, param1=50, param2=30, minRadius=0, maxRadius=0). Os valores de param1 e param2 precisam ser calibrados por imagem, pois dependem do contraste e da quantidade de ruído. Não existe valor universal que funcione em tudo. A parte mais demorada costuma ser o ajuste fino desses hiperparâmetros, não a escrita do código em si. Gastei duas semanas afinando thresholds para um único projeto de inspeção visual porque as condições de iluminação variavam ao longo do dia. A workaround foi trocar threshold fixo por histogram equalization + Otsu, o que estabilizou a detecção sem depender de ajuste manual contínuo.