5.14. Suavização gaussiana e bordas

Dois trabalhos dominam o uso das janelas de vizinhança na visão de máquina clássica: suavizar de forma limpa a variação de pixel a pixel e encontrar as bordas onde a imagem muda bruscamente. O filtro gaussiano é a ferramenta padrão para o primeiro, e os detectores baseados no Laplaciano são a ferramenta padrão para o segundo – e os dois se combinam, porque todo detector de bordas funciona melhor sobre uma entrada levemente suavizada.

5.14.1. O filtro gaussiano

gaussian() é o primo ponderado pelo centro de mean(). Ambos calculam uma média sobre a vizinhança de cada pixel, mas os pesos do gaussiano não são uniformes: pixels mais próximos do centro da vizinhança contam mais, pixels na borda da vizinhança contam menos, com os pesos seguindo a familiar curva em sino que dá nome ao filtro.

A ponderação em forma de sino é o que torna um filtro gaussiano mais suave do que uma média de caixa. A filtragem por média pode produzir artefatos visíveis nas bordas dos objetos – um corte abrupto na ponderação introduz pequenos padrões de oscilação em transições nítidas. Os pesos suavemente decrescentes do gaussiano evitam essa oscilação e produzem um resultado que se parece mais com o que um “desfocado” deveria parecer. O custo é mais computação por pixel do que o filtro de média, mas não de forma drástica – o custo por pixel ainda é muito menor do que o do filtro bilateral.

img.gaussian(1)    # 3x3 Gaussian -- a clean light blur
img.gaussian(2)    # 5x5 Gaussian -- stronger smoothing

A suavização gaussiana é a primeira etapa padrão de quase todo pipeline de detecção de bordas. Os detectores de borda abaixo amplificam todos o conteúdo de alta frequência, incluindo o ruído do sensor que o algoritmo na verdade não quer detectar. Executar um gaussiano leve primeiro suprime esse ruído sem suavizar muito as bordas reais, deixando o detector de bordas encontrar bordas reais em vez de ruído pontual.

5.14.2. Máscara de nitidez (unsharp masking)

Uma cópia da imagem desfocada por gaussiano é a matéria-prima que a técnica de unsharp mask usa para a nitidez clássica. Definir unsharp=True no filtro o alterna de “produzir a imagem desfocada” para “subtrair a imagem desfocada do original e somar a diferença de volta ao original” – o efeito é que as bordas de alta frequência são amplificadas em relação aos interiores suaves.

img.gaussian(1, unsharp=True)

Os parâmetros opcionais mul e add escalonam a intensidade do resultado unsharp; os padrões (mul=1.0, add=0.0) produzem uma nitidez moderada que não exagera o ruído do sensor.

5.14.3. O filtro Laplaciano

laplacian() executa uma aproximação discreta da segunda derivada espacial da imagem. A saída é grande onde os valores dos pixels mudam rapidamente, próxima de zero onde são constantes ou mudam linearmente. A leitura natural do resultado é uma resposta de borda: pixels onde a imagem muda rapidamente se acendem, pixels em interiores suaves permanecem escuros.

img.laplacian(1)   # 3x3 Laplacian -- edge response

Os mesmos parâmetros de gaussian estão disponíveis. sharpen=True produz uma imagem com mais nitidez (o Laplaciano somado de volta ao original em vez de retornado isoladamente). mul e add escalonam a resposta.

Um uso prático além da detecção de bordas é a medição de foco. A resposta do Laplaciano calculada como média sobre uma região fornece uma medida aproximada de quanto conteúdo de alta frequência a região carrega; em um quadro bem focado essa média é alta, em um quadro desfocado ela cai. Comparar a resposta do Laplaciano entre quadros é a forma barata de perguntar “a lente está focada?” sem precisar de uma métrica de contraste mais cara.

5.14.4. O método find_edges

find_edges() executa um pipeline completo de detecção de bordas, e não apenas um filtro de resposta de borda. Ele funciona em imagens em escala de cinza, e o resultado é uma imagem binária cujos pixels não nulos marcam as posições onde a entrada possui o tipo de mudança de brilho que deve contar como uma borda.

O método recebe um parâmetro edge_type que escolhe entre dois algoritmos:

EDGE_SIMPLE executa um filtro passa-alta, aplica um limiar e retorna o resultado. Rápido, mas a saída inclui toda mudança de brilho acima do limiar, incluindo ruído e textura com os quais a aplicação provavelmente não se importa. Razoável para imagens limpas e para casos em que o ruído será limpo por uma passagem morfológica posterior.

EDGE_CANNY executa o detector de bordas Canny – o clássico algoritmo de múltiplos estágios. Ele calcula o gradiente de brilho, suprime toda resposta não máxima ao longo da direção do gradiente (de modo que cada borda tenha um pixel de largura) e aplica um limiar de histerese (de modo que uma borda forte em um ponto seja rastreada mesmo onde ela enfraquece no meio). O resultado é um conjunto limpo, fino e conectado de pixels de borda do tipo que todo algoritmo clássico baseado em bordas deseja.

O parâmetro threshold é uma tupla de dois elementos (low, high). Para EDGE_CANNY, o valor high é o corte acima do qual um pixel é definitivamente uma borda, e o valor low é o corte acima do qual um pixel só é uma borda se estiver conectado a uma borda definitiva. Para EDGE_SIMPLE, apenas o valor high importa; ele é o corte único acima do qual um pixel conta como uma borda. O padrão de (100, 200) é um ponto de partida que vale a pena ajustar para a cena específica.

img.gaussian(1)                                   # pre-smooth
img.find_edges(image.EDGE_CANNY, threshold=(50, 100))

O detector Canny é a melhor escolha para quase toda aplicação em que as bordas importam. O mais rápido EDGE_SIMPLE vale a pena lembrar para os casos em que o custo do Canny é um problema e a rejeição de ruído de sua histerese não é, na prática, necessária.

5.14.5. Limiar adaptativo no gaussiano

Assim como os filtros estatísticos, gaussian() aceita o par de palavras-chave threshold=True / offset=N para limiar adaptativo. O comportamento é o mesmo de mean(): a estatística gaussiana em cada posição torna-se o corte local, e o pixel de origem é comparado com a estatística mais o offset para produzir um resultado binário.

A variante gaussiana é geralmente a escolha mais limpa para limiar adaptativo quando a entrada é razoavelmente livre de ruído. A média ponderada fornece um corte mais suave do que o produzido pelo filtro de média, com menos artefatos em transições nítidas de iluminação.