OpenCV - Algoritmo de detecção de arestas astuto

Descrição do Problema

A segmentação de imagem é o processo de subdividir uma imagem digital em várias sub-regiões, que é amplamente utilizada no campo da visão computacional/visão de máquina. Sua finalidade é simplificar ou alterar a representação de uma imagem para que seja mais fácil de entender e analisar. Métodos comuns de segmentação de imagem incluem limiarização, agrupamento, detecção de borda e crescimento de região. Resolver problemas de segmentação de imagem geralmente requer combinar conhecimento de domínio para melhorar o efeito da solução.

A detecção de borda é um método de segmentação de imagem comumente usado, que é realizado extraindo as características de partes descontínuas na imagem. Atualmente, os operadores comuns de detecção de borda incluem o operador de diferença, o operador Roberts, o operador Sobel, o operador Prewitt, o operador Log e o operador Canny. O operador Canny é um operador de detecção de arestas proposto por John F. Canny em 1986, e é considerado um dos algoritmos de detecção de arestas mais completos da atualidade. Muitas ferramentas de processamento de imagem comumente usadas (como MATLAB, OpenCV) possuem a API do operador Canny integrada.

Detecção de borda astuta

A detecção de arestas Canny é um algoritmo clássico de detecção de arestas, proposto por John F. Canny em 1986. É amplamente utilizado nas áreas de visão computacional e processamento de imagem para detectar informações de borda em imagens.

Informações do papel:

Título: Uma Abordagem Computacional para Detecção de Bordas

Por John F. Canny

Ano de publicação: 1986

As etapas do algoritmo de detecção de arestas de Canny

O objetivo do algoritmo de detecção de bordas de Canny é encontrar bordas fortes na imagem e tentar eliminar o ruído e as bordas fracas. Os passos do algoritmo são os seguintes:

  1. Supressão de ruído: Primeiro, a imagem é suavizada usando um filtro gaussiano para reduzir o efeito do ruído.

  2. Calcular gradientes: em seguida, calcule a força e a direção do gradiente para cada pixel da imagem. Isso pode ser obtido aplicando um filtro como o Sobel.

  3. Supressão não máxima: Em seguida, a supressão não máxima é executada na imagem de intensidade de gradiente para refinar as bordas e remover as respostas das bordas.

  4. Limiarização dupla: Em seguida, use a limiarização dupla para determinar a força das arestas. De acordo com o limite definido, os pixels de borda são divididos em borda forte, borda fraca e pixels sem borda.

  5. Conexão de borda: Finalmente, o algoritmo de conexão de borda é usado para conectar pixels de borda forte e pixels de borda fraca adjacentes para formar uma borda completa.

O algoritmo Canny de detecção de bordas é amplamente elogiado no campo de processamento de imagens, pois pode detectar bordas sutis e tem boa robustez ao ruído.

1. Aplique a filtragem gaussiana para remover o ruído da imagem

O filtro gaussiano é um filtro de suavização que reduz a diferença entre os valores dos pixels realizando operações de convolução na imagem, reduzindo assim a influência do ruído.

O kernel (ou template) do filtro Gaussiano é uma matriz de pesos bidimensional, onde os valores dos pesos são calculados pela função Gaussiana. O tamanho e o desvio padrão (σ) dessa matriz de peso são dois parâmetros-chave do filtro gaussiano, que determinam a suavidade do filtro.

Uma função gaussiana bidimensional pode ser expressa como:

G(x, y) = \frac{1}{2\pi \sigma ^{2}} exp(-\tfrac{x^{2}+y^{2}}{2\sigma ^{2}} )

Entre eles, G(x, y) representa o valor da função gaussiana bidimensional no ponto (x, y) e σ representa o desvio padrão. 

Para cada pixel da imagem, a aplicação de um filtro gaussiano pode ser obtida com a seguinte operação de convolução:

I' = G * I

Dentre eles, I' representa a imagem filtrada, G representa o kernel do filtro gaussiano e I representa a imagem original.

Especificamente, para cada pixel, o kernel do filtro Gaussiano é convoluído com a vizinhança centrada no pixel, e a média ponderada dos valores de pixel na vizinhança é calculada como o valor do pixel na imagem filtrada. Desta forma, o filtro gaussiano desfoca a imagem e reduz o efeito do ruído.

Deve-se observar que o tamanho e o desvio padrão do filtro gaussiano precisam ser selecionados de acordo com o cenário de aplicação específico. Tamanhos de filtro maiores e desvios padrão menores podem fornecer efeitos de suavização mais fortes, mas podem levar ao desfoque das informações de borda. Por outro lado, tamanhos de filtro menores e desvios padrão maiores preservam mais detalhes, mas podem não suprimir o ruído de forma eficaz.

O desvio padrão σ do filtro gaussiano 2D é igual nas direções horizontal e vertical para manter o filtro isotrópico. A escolha de um desvio padrão apropriado depende do nível de ruído e das características da imagem. Um desvio padrão maior pode fornecer um efeito de suavização mais forte, mas pode desfocar bordas e detalhes.

 2.  Use o operador Sobel para calcular o gradiente de pixels

O operador Sobel é um operador diferencial discreto comumente usado, que pode calcular a força do gradiente e a direção de cada pixel na imagem. Na detecção de arestas de Canny, o operador Sobel é geralmente usado para calcular o gradiente da imagem nas direções horizontal e vertical.

Para imagens em tons de cinza, podemos calcular o gradiente de pixels por meio do seguinte operador Sobel:

Gradiente na direção horizontal (Gx):

      -1  0  1
Gx =  -2  0  2
      -1  0  1

Gradiente na direção vertical (Gy):

      -1 -2 -1
Gy =   0  0  0
       1  2  1

A seguir estão as etapas específicas para calcular o gradiente de pixel usando o operador Sobel:

  1. Converta a imagem em tons de cinza (se não em tons de cinza).

  2. Aplique o operador Sobel na direção horizontal (Gx) e o operador Sobel na direção vertical (Gy) à imagem.

  3. Calcule a intensidade e a direção do gradiente para cada pixel:

    G = sqrt(Gx^2 + Gy^2)       (梯度强度)
    θ = arctan(Gy / Gx)         (梯度方向)
    

    Entre eles, G representa a intensidade do gradiente e θ representa a direção do gradiente.

Dessa forma, podemos obter a intensidade e a direção do gradiente de cada pixel da imagem. Esta informação de gradiente será usada nas etapas subseqüentes do algoritmo de detecção de arestas de Canny para detectar e conectar arestas.

 3.  Supressão de gradiente de pixel não máxima

Nesta etapa, precisamos verificar os pixels adjacentes na direção do gradiente de cada pixel e manter o pixel com a maior intensidade de gradiente e suprimir os outros pixels para zero.

Para melhor descrever o processo de supressão não máxima, discretizamos a direção do gradiente da imagem assumida em quatro direções principais: 0° (direção horizontal), 45° (direção diagonal), 90° (direção vertical) e 135° (direção diagonal). Para cada pixel, comparamos sua força de gradiente com a de dois pixels vizinhos ao longo da direção do gradiente.

Se a direção do gradiente de um pixel for 0° (direção horizontal), comparamos a intensidade do gradiente com a intensidade do gradiente de seus dois vizinhos à esquerda e à direita.

Suponha que o ponto de pixel atual seja (x, y), sua direção de gradiente seja 0° e sua intensidade de gradiente seja G(x, y). Comparamos G(x, y) com a intensidade do gradiente de dois pixels vizinhos: G(x-1, y) e G(x+1, y).

  • Se G(x, y) for o maior dos três valores, mantemos esse valor de pixel, caso contrário, o reduzimos a zero.

Especificamente, usamos a interpolação linear para determinar se devemos preservar os valores de pixel. Se G(x, y) estiver entre G(x-1, y) e G(x+1, y), então calculamos o peso w correspondente por interpolação linear:

w = \frac{ |G(x, y) - G(x-1, y)|}{ |G(x+1, y) - G(x-1, y)|}

Por fim, as condições sob as quais preservamos os valores dos pixels são: 

G(x, y) >= w * G(x+1, y) + (1 - w) * G(x-1, y) 

 

Dependendo dos dados específicos da imagem e da orientação do gradiente, o processo acima será aplicado a outras orientações (45°, 90° e 135°), respectivamente.

4. Processamento de histerese de limiar

Depois de concluir as etapas acima, a borda forte na imagem já está na imagem de borda adquirida atualmente. No entanto, algumas bordas fantasmas também podem estar dentro da imagem da borda. Essas arestas virtuais podem ser produzidas por imagens reais ou por ruído. Para este último, tem que ser nocauteado.

Nesta etapa, usamos limiarização dupla para determinar a força das arestas.

  • Primeiro, de acordo com os limites alto e baixo definidos, os pixels da imagem de intensidade de gradiente são classificados em três categorias: bordas fortes, bordas fracas e não bordas.
  • Os pixels de borda fortes têm intensidades de gradiente acima do limite alto,
  • As intensidades de gradiente de pixels sem borda estão abaixo de um limite baixo,
  • As intensidades de gradiente de pixels de borda fracos estão entre dois limites.

5. Conectividade de borda

Na última etapa, os pixels de borda fortes e os pixels de borda fracos adjacentes são conectados pelo algoritmo de conexão de borda para formar uma borda completa. Em geral, um pixel de borda fraca é considerado parte de uma borda se for adjacente a pelo menos um pixel de borda forte. Este processo pode ser implementado de forma recursiva ou iterativa.

Fluxograma do programa

Link da imagem:  https://pic4.zhimg.com/80/v2-7400b8669ef4c750aeff27ed699ba7c7_720w.webp

Canny função e uso

O OpenCV  fornece a função cv2.Canny() para implementar a detecção de borda Canny, e sua sintaxe é a seguinte:

edges = cv.Canny( image, threshold1, threshold2[, apertureSize[, L2gradient]])

 em:

  •  edge é a imagem de borda calculada.
  • image é uma imagem de entrada de 8 bits.
  • threshold1 representa o primeiro limite no processamento.
  • threshold2 representa o segundo limite durante o processamento.
  • openingSize representa o tamanho da abertura do operador Sobel.
  • L2gradient é o logotipo para calcular a magnitude do gradiente da imagem. Seu valor padrão é False. Se True, a norma L2 mais precisa é usada para cálculos (ou seja, a raiz quadrada das derivadas em ambas as direções), caso contrário, a norma L1 é usada (adicione diretamente os valores absolutos das derivadas em ambas as direções).


Exemplo:
Use a função cv2.Canny() para obter as bordas da imagem e experimente diferentes tamanhos de threshold1 e threshold2.

import cv2
o=cv2.imread("lena.bmp",cv2.IMREAD_GRAYSCALE)
r1=cv2.Canny(o,128,200)
r2=cv2.Canny(o,32,128)
cv2.imshow("original",o)
cv2.imshow("result1",r1)
cv2.imshow("result2",r2)
cv2.waitKey()
cv2.destroyAllWindows()

 

resultado da operação: 

Pode ser visto nos resultados da execução do programa que quando os parâmetros threshold1 e threshold2 da função cv2.Canny() são menores, mais informações de borda podem ser capturadas. 

Acho que você gosta

Origin blog.csdn.net/weixin_45897172/article/details/131030659
Recomendado
Clasificación