A medição automatizada de dimensões em componentes metálicos é um pilar fundamental da inspeção de qualidade industrial moderna (CQ). Diferente de tarefas de classificação ou detecção de objetos baseadas em Deep Learning, a metrologia por visão computacional exige precisão geométrica rigorosa, muitas vezes na escala de micrômetros. Este processo não busca apenas identificar a peça, mas sim extrair coordenadas espaciais precisas para calcular distâncias, diâmetros e ângulos.
Fundamentos da Medição Dimensional: Além da Classificação
Na inspeção de componentes eletrônicos ou mecânicos, a variabilidade aceitável é mínima. Utilizar redes neurais convolucionais para "enquadrar" uma peça não fornece a precisão necessária para validar se um furo possui exatamente 5,02 mm ou 5,08 mm. A medição visual baseia-se em três pilares: calibração do equivalente de pixel, extração de bordas com precisão de subpixel e algoritmos de ajuste geométrico.
Calibração e Correção de Distorção
O primeiro passo em qualquer sistema de metrologia visual é converter a unidade de medida da imagem (pixels) para a unidade física (milímetros). Este fator, conhecido como equivalente de pixel, depende da distância focal, do tamanho do sensor e da distância de trabalho.
Determinação do Equivalente de Pixel
Uma técnica comum envolve o uso de um objeto com dimensões conhecidas ou um padrão de calibração (como um tabuleiro de xadrez). O código abaixo exemplifica como obter essa escala a partir de uma região de interesse (ROI) onde se conhece a dimensão real de uma borda:
import cv2
import numpy as np
def obter_escala_pixel(caminho_img, regiao_roi, dim_real_mm=10.0):
img = cv2.imread(caminho_img, cv2.IMREAD_GRAYSCALE)
# Detecção básica para estimativa inicial
bordas = cv2.Canny(img, 60, 120)
x, y, w, h = regiao_roi
recorte = bordas[y:y+h, x:x+w]
pontos_y, pontos_x = np.where(recorte > 0)
if len(pontos_x) < 10:
return None
largura_pixels = np.ptp(pontos_x) # Pico a pico (max - min)
escala = largura_pixels / dim_real_mm
return escala
Importância da Lente Telecêntrica
Em metrologia, o uso de lentes convencionais pode introduzir erros de perspectiva e distorção radial. Se os componentes a serem medidos estiverem nas extremidades da imagem, a distorção pode alterar o equivalente de pixel. Para alta precisão, recomenda-se o uso de lentes telecêntricas, que eliminam o erro de paralaxe, garantindo que o tamanho do objeto na imagem não mude com sua distância em relação à câmera.
Processamento de Imagem para Superfícies Metálicas
Metais apresentam desafios devido ao brilho especular. O reflexo pode saturar o sensor, mascarando a borda real do componente.
Pré-processamento e Supressão de Reflexos
A ordem das operações é crítica. Primeiro, aplicamos uma suavização para reduzir o ruído de textura e, em seguida, limitamos a intensidade máxima para evitar que o brilho interfira no gradiente da borda.
def preparar_frame(frame, k_size=7, clip_limit=190):
# Conversão e desfoque para suavizar texturas do metal
cinza = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
suave = cv2.GaussianBlur(cinza, (k_size, k_size), 0)
# Clip de intensidade para mitigar reflexos
processada = np.clip(suave, 0, clip_limit).astype(np.uint8)
return processada
Extração de Bordas com Subpixel
A resolução de uma imagem é limitada pelo grid de pixels. Para superar essa barreira, utilizamos a interpolação de subpixel, que estima a posição da borda entre dois pixels vizinhos analisando a curva do gradiente.
A técnica consiste em encontrar o ponto de magnitude máxima do gradiente e ajustar uma parábola usando seus vizinhos imediatos. O deslocamento $d$ em relação ao pixel central é dado por:
def ajuste_subpixel(m1, m0, p1):
# m1: vizinho anterior, m0: centro, p1: próximo vizinho
divisor = m1 - 2.0 * m0 + p1
if abs(divisor) < 1e-9:
return 0.0
return 0.5 * (m1 - p1) / divisor
Algoritmo de Medição via Ferramenta de Caliper
A "ferramenta de caliper" simula um paquímetro virtual. Ela projeta linhas de busca perpendiculares à borda teórica e detecta transições de intensidade.
def localizar_borda_na_linha(vetor_intensidade, limiar_grad=15):
gradiente = np.abs(np.diff(vetor_intensidade.astype(np.float32)))
idx_max = np.argmax(gradiente)
if gradiente[idx_max] < limiar_grad:
return None
if 0 < idx_max < len(gradiente) - 1:
offset = ajuste_subpixel(gradiente[idx_max-1], gradiente[idx_max], gradiente[idx_max+1])
else:
offset = 0.0
return idx_max + offset
def medir_distancia_entre_bordas(img, ponto_central, angulo, busca=20):
cos_a, sin_a = np.cos(angulo), np.sin(angulo)
cx, cy = ponto_central
amostras_a, amostras_b = [], []
# Amostragem ao longo da normal da borda
for i in range(-busca, busca + 1):
# Coordenadas com interpolação bilinear simplificada (truncada)
px = int(cx + i * cos_a)
py = int(cy + i * sin_a)
# Lógica para coletar pontos e detectar transições
# ...
Validação de Resultados e Tolerâncias
Após a extração das coordenadas em milímetros, o sistema deve comparar os valores com os dados de projeto (CAD). Na indústria, os resultados são geralmente exportados em formatos estruturados como CSV ou integrados via protocolos como MQTT ou OPC-UA.
| Parâmetro | Unidade | Descrição |
|---|---|---|
| Distância Nominal | mm | Valor esperado segundo o projeto. |
| Tolerância | mm | Desvio máximo permitido (ex: ±0.05mm). |
| Repetibilidade | mm | Desvio padrão em 10 medições consecutivas. |
Para garantir a confiabilidade, é essencial realizar testes de repetibilidade. Se o desvio padrão das medições de uma peça estática exceder 10% da zona de tolerância, o sistema de iluminação ou a estabilidade mecânica da câmera devem ser revisados. A integração final envolve encapsular a lógica em classes que processam buffers de imagem de câmeras industriais (GigE ou USB3), aplicando os filtros e retornando o status de "Aprovado" ou "Reprovado" em tempo real.