8. Operaciones avanzadas de procesamiento de imágenes de Opencv-python (5): detección de bordes

  • La detección de bordes a menudo se considera un tema de maestría o una pregunta de entrevista de empresa, por lo que es muy importante. En este capítulo, se presentarán varios operadores comunes de detección de bordes.

objetivo de aprendizaje

Comprender el operador de Sobel, el operador de Scharr y el operador laplaciano

Domine los principios y aplicaciones de la detección de bordes astuta

1. Principio de detección de bordes

La detección de bordes es un problema fundamental en el procesamiento de imágenes y la visión por computadora, y su propósito es representar puntos en imágenes digitales con cambios obvios de brillo. Los cambios significativos en los atributos de una imagen a menudo reflejan eventos y cambios importantes en los atributos. La expresión de la detección de bordes se muestra en la siguiente figura:
Insertar descripción de la imagen aquí
La detección de bordes de la imagen reduce en gran medida la cantidad de datos, elimina información que puede considerarse irrelevante y conserva atributos estructurales importantes de la imagen. Existen muchos métodos para la detección de bordes, la mayoría de los cuales se pueden dividir en dos categorías: basados ​​en búsqueda y basados ​​en cruce por cero.

1. Basado en la búsqueda

El límite se detecta encontrando el valor máximo en la primera derivada de la imagen y luego usando los resultados del cálculo para estimar la dirección local del borde. Por lo general, se usa la dirección del gradiente y esta dirección se usa para encontrar el máximo. Valor del módulo de gradiente local. Los algoritmos representativos incluyen el operador de Sobel y el operador de Scharr.

(1) El valor máximo de la primera derivada de la imagen -->
(
2) La dirección local del borde (dirección general del gradiente) -->
(
3) El valor máximo del módulo de gradiente local

Insertar descripción de la imagen aquí

2. Basado en el cruce por cero

El límite se encuentra buscando el cruce por cero de la segunda derivada de la imagen, y el operador representativo es el operador laplaciano.
El punto cero es el punto donde la función intersecta al eje y.
Insertar descripción de la imagen aquí

2. Operador de detección de Sobel

El algoritmo de detección de bordes de Sobel es relativamente simple y más eficiente que la detección de bordes astuta en aplicaciones prácticas . Sin embargo, el borde no es tan preciso como la detección astuta, pero en muchas aplicaciones prácticas, el operador Sobel es la primera opción.
El operador Sobel es una combinación de suavizado gaussiano y operaciones diferenciales, por lo que tiene una fuerte resistencia al ruido y muchos usos . Especialmente cuando los requisitos de eficiencia son altos y no te importan mucho las texturas detalladas.

1. Discusión de principios y métodos.

Para funciones discontinuas, la primera derivada se puede escribir como:
Insertar descripción de la imagen aquí
o
Insertar descripción de la imagen aquí
Entonces:
Insertar descripción de la imagen aquí
Supongamos que la imagen a procesar es I y la derivada se toma en dos direcciones.

  • Cambio horizontal: convoluciona la imagen I con una plantilla de tamaño de período y el resultado es Gx. Por ejemplo, cuando el tamaño de la plantilla es 3, Gx es:
    Insertar descripción de la imagen aquí
  • Variación vertical: Convoluciona la imagen I con una plantilla de tamaño técnico, el resultado es Gy. Por ejemplo, cuando el tamaño de la plantilla es 3, Gy es:
    Insertar descripción de la imagen aquí
    en cada punto de la imagen, combinado con los dos resultados anteriores,
    Insertar descripción de la imagen aquí
    la posición del valor máximo estadístico es el borde de la imagen.
    **Nota:** Cuando el tamaño del kernel es 3, el kernel de Sobel anterior puede producir errores obvios. Para resolver este problema, usamos la función Scharr, pero esta función solo funciona en kernels con un tamaño de 3. Esta función funciona tan rápido como la función de Sobel, pero los resultados son más precisos. Se calcula como:
    Insertar descripción de la imagen aquí

2. Solicitud

La API para la detección de bordes de Sobel usando OpenCV es:

Sobel_x_or_y = 
cv2.Sobel(src, ddepth, dx, dy, dst, ksize, scale, delta, borderType)

parámetro:

  • src: la imagen entrante
  • dprofundidad: la profundidad de la imagen
  • dx y dy: se refieren al orden de derivación, 0 significa que no hay derivación en esta dirección y los valores son 0 y 1.
  • ksize: es el tamaño del operador Sobel, es decir, el tamaño del núcleo de convolución, debe ser un número impar de 1, 3, 5 o 7, el valor predeterminado es 3.
  • Nota: Si ksize=-1, evoluciona a un operador Scharr 3x3.
  • escala: la constante proporcional de la derivada de escala, el valor predeterminado es sin coeficiente de escala.
  • borderType: el modo del borde de la imagen, el valor predeterminado es cv2.BORDER_DEFAULT.

Después de que la función de Sobel calcula la derivada, habrá valores negativos y habrá valores mayores que 255. La imagen original es uint8, es decir, 8 es un número sin signo, por lo que la imagen creada por Sobel no tiene suficientes dígitos y será truncada. Por lo tanto, utilice el tipo de datos con signo de 16 bits, cv2.CV_16s. Después de procesar la imagen, use la función cv2.convertScaleAbs() para convertirla nuevamente al tipo uint8 original; de lo contrario, la imagen no se podrá mostrar.

El operador Sobel se calcula en dos direcciones y finalmente debe combinarse usando la función cv2.addWeighted ()

Scale_abs = cv2.convertScaleAbs(x)  # 格式转换函数
result = cv2.addWeighted(src1, alpha, src2, beta) # 图像混合

Ejemplo de código:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 1 读取图像
img = cv.imread('./image/horse.jpg',0)
# 2 计算Sobel卷积结果
x = cv.Sobel(img, cv.CV_16S, 1, 0)
y = cv.Sobel(img, cv.CV_16S, 0, 1)
# 3 将数据进行转换
Scale_absX = cv.convertScaleAbs(x)  # convert 转换  scale 缩放
Scale_absY = cv.convertScaleAbs(y)
# 4 结果合成
result = cv.addWeighted(Scale_absX, 0.5, Scale_absY, 0.5, 0)
# 5 图像显示
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('原图')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(result,cmap = plt.cm.gray),plt.title('Sobel滤波后结果')
plt.xticks([]), plt.yticks([])
plt.show()

Insertar descripción de la imagen aquí
Establezca el ksize de la parte de cálculo del operador Sobel en el código anterior en -1, que consiste en utilizar scharr para la detección de bordes.

x = cv2.Sobel(img, cv2.CV_16S, 1, 0, ksize=-1)
y = cv2.Sobel(img, cv2.CV_16S, 0, 1, ksize=-1)

Insertar descripción de la imagen aquí

Se puede ver que utilizando el operador Scharr, el efecto de detección es ligeramente mejor que el operador Sobel.

3. Operador laplaciano

El método de detección laplaciano utiliza derivadas de segundo orden para detectar bordes. Debido a que la imagen es "bidimensional", necesitamos derivar la derivada en dos direcciones, como se muestra en la siguiente fórmula:
Insertar descripción de la imagen aquí
Entonces la derivada discontinua de segundo orden es:
Insertar descripción de la imagen aquí
Entonces el núcleo de convolución utilizado es:
Insertar descripción de la imagen aquí
API:

laplacian = cv2.Laplacian(src, ddepth[, dst[, ksize[, scale[, delta[, borderType]]]]])

parámetro:

  • Fuente: imagen
  • Dprofundidad: profundidad de la imagen, -1 significa que se utiliza la misma profundidad de la imagen original y la profundidad de la imagen de destino debe ser mayor o igual que la profundidad de la imagen original;
  • ksize: el tamaño del operador, es decir, el tamaño del núcleo de convolución, debe ser 1, 3, 5, 7

Ejemplo de código:

import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 1 读取图像
img = cv.imread('./image/horse.jpg',0)
# 2 laplacian转换
result = cv.Laplacian(img,cv.CV_16S)
Scale_abs = cv.convertScaleAbs(result)
# 3 图像展示
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('原图')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(Scale_abs,cmap = plt.cm.gray),plt.title('Laplacian检测后结果')
plt.xticks([]), plt.yticks([])
plt.show()

Insertar descripción de la imagen aquí

4. detección de bordes astuta

El algoritmo de detección de bordes astuto es un algoritmo de detección de bordes muy popular, propuesto por John F. Canny en 1986 y considerado el mejor algoritmo de detección de bordes.

1. Principio del algoritmo Canny

El algoritmo de detección de bordes de Canny consta de 4 pasos, que se presentan a continuación:

  • eliminación de ruido

Dado que la detección de bordes se ve fácilmente interferida por el ruido, primero se utiliza un filtro gaussiano para eliminar el ruido. (El filtrado gaussiano se menciona en Suavizado de imágenes, puede leer más adelante)

  • Calcular gradiente de imagen

Utilice el operador de Sobel para calcular las primeras derivadas (Gx y Gy) en las direcciones horizontal y vertical de la imagen suavizada . Encuentre el gradiente y la dirección del límite según los dos mapas de gradiente obtenidos (Gx y Gy). La fórmula es la siguiente:
Insertar descripción de la imagen aquí
si un píxel es un borde, su dirección de gradiente siempre es perpendicular a la dirección del borde. Las direcciones de gradiente se clasifican en cuatro categorías: vertical, horizontal y dos direcciones diagonales.

  • supresión no máxima

Después de obtener la dirección y la magnitud del gradiente, escanee toda la imagen para eliminar los puntos que no están en el límite. Verifique cada píxel para ver si el gradiente de este punto es el mayor entre los puntos circundantes con la misma dirección de gradiente. Como se muestra en la siguiente figura:
Insertar descripción de la imagen aquí
El punto A está ubicado en el borde de la imagen. En la dirección de su cambio de gradiente, seleccione los puntos de píxeles B y C para verificar si el gradiente del punto A es un valor máximo. Si es un máximo valor, manténgalo; de lo contrario, los puntos A se suprimen y el resultado final es una imagen binaria con "bordes finos".

  • umbral de histéresis

Ahora viene la determinación de los verdaderos límites. Establecemos dos umbrales: minVal y maxVal. Cuando el gradiente de gris de la imagen es mayor que maxVal, se considera un límite verdadero y el límite por debajo de minVal se descartará. Si está entre los dos, depende de si el punto está conectado a un determinado punto límite determinado como un punto límite real, si es así, se considera un punto límite, y si no, se descarta. Como se muestra en la siguiente figura:
Insertar descripción de la imagen aquí
Como se muestra en la figura anterior, A es mayor que el umbral maxVal, por lo que es un punto límite real. Aunque C es menor que maxVal, es mayor que minVal y está conectado a A, por lo que También se considera un punto límite real. Y B se descartará porque es inferior a maxVal y no está conectado al punto límite real. Por lo tanto, elegir maxVal y minVal adecuados es muy importante para obtener buenos resultados.

2. Solicitud

API utilizada para implementar detección astuta en medicina china opencv:

canny = cv2.Canny(image, threshold1, threshold2)

parámetro:

  • imagen: imagen en escala de grises,
  • umbral1: minval, un umbral más pequeño conecta bordes discontinuos
  • umbral2: maxval, un umbral mayor para detectar bordes obvios en la imagen
    . Ejemplo de código:
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
# 1 图像读取
img = cv.imread('./image/horse.jpg',0)
# 2 Canny边缘检测
lowThreshold = 0
max_lowThreshold = 100
canny = cv.Canny(img, lowThreshold, max_lowThreshold) 
# 3 图像展示
plt.figure(figsize=(10,8),dpi=100)
plt.subplot(121),plt.imshow(img,cmap=plt.cm.gray),plt.title('原图')
plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(canny,cmap = plt.cm.gray),plt.title('Canny检测后结果')
plt.xticks([]), plt.yticks([])
plt.show()

Insertar descripción de la imagen aquí

Resumir:

1. Principio de detección de bordes

(1) Basado en búsqueda

(2) Basado en cruce por cero

2. Operador Sobel [Aplicación práctica]

(1) Obtener el límite según el método de búsqueda

(2)cv2.Sobel()

(3)cv2.convertScaleAbs()

(4)cv2.addWeighted()

3. Operador laplaciano

(1) Obtener el límite basado en el cruce por cero

(2)cv2.Laplaciano()

4. Algoritmo astuto

(1) Eliminación de ruido (filtrado gaussiano)

(2) Calcular el gradiente de la imagen (operador Sobel)

(3) Supresión no máxima: determine si el píxel es un punto límite

(4) Umbral de histéresis: establezca dos umbrales para determinar el límite final

5. Comparación entre varios operadores tradicionales

Insertar descripción de la imagen aquí

  • El camino para volverse más fuerte es largo y arduo, ¡así que vamos! ! !

Supongo que te gusta

Origin blog.csdn.net/weixin_44463519/article/details/126095174
Recomendado
Clasificación