Capítulo 7: Suavizado de imágenes

El suavizado de la imagen consiste en filtrar el ruido dentro de la imagen manteniendo la información original de la imagen tanto como sea posible. Debido a que el suavizado de imágenes suele ir acompañado de desenfoque de imagen, a veces el suavizado de imágenes también se denomina desenfoque de imagen. A veces también se le llama filtrado de imágenes en las computadoras. Esto es solo un nombre, y diferentes lugares pueden tener diferentes dichos, así que no te enredes demasiado.

  • El propósito del suavizado de imágenes es filtrar el ruido interno de la imagen.

La esencia del procesamiento de suavizado de imágenes es procesar los valores de píxel en la imagen que son bastante diferentes de los de los píxeles circundantes y ajustar su valor a un valor aproximado de los valores de píxel de los píxeles circundantes.

como muestra la imagen:

imagen-20211014150205518

Los píxeles ubicados en la tercera fila y la tercera columna tienen diferencias obvias en el valor de los valores de píxeles circundantes. Reflejados en la imagen, los píxeles alrededor de este punto son todos puntos en escala de grises, y el color de este punto es más oscuro, un punto negro puede ser ruido y el valor de este punto debe ajustarse a un valor aproximado de los valores de píxeles circundantes .

imagen-20211014150330480

Hay muchas formas de procesamiento de suavizado de imágenes, la introducción principal es la siguiente:

  • filtrado medio
  • filtrado de caja
  • filtro gaussiano
  • filtro mediano
  • filtrado bilateral
  • Convolución 2D (filtrado personalizado)

1. Filtrado medio:

El filtrado medio se refiere al uso del valor promedio de los valores de píxeles N*N alrededor del punto de píxel actual para reemplazar el valor de píxel actual con el punto de píxel actual como centro. El uso de este método para recorrer y procesar cada píxel de la imagen puede completar el filtrado medio de toda la imagen.

Para los píxeles del borde de la imagen, solo puede tomar el valor promedio de los valores de píxel de los puntos de vecindad circundantes en la imagen. También es posible expandir el borde de la imagen y llenar diferentes valores de píxeles en las filas y columnas recién agregadas. Sobre esta base, calcule el valor medio de N · N píxeles de vecindad para la imagen original. OpenCV proporciona una variedad de métodos de procesamiento de límites, y podemos elegir diferentes modos de procesamiento de límites según las necesidades reales.

imagen-20211014152606976

1. Sintaxis de la función:

  • En OpenCV, la función que realiza el valor medio es cv2.blur(), y su formato de sintaxis es:

    • dst = cv2.blur(src, ksize, ancla, borderType)

      • dst: valor devuelto, el resultado del procesamiento obtenido después del filtrado medio.

      • src: La imagen a procesar, es decir, la imagen original. Puede haber cualquier número de canales y cada canal se puede procesar de forma independiente. La profundidad de la imagen debe ser uno de CV_8U, CV_16U, CV_16S, CV_32F, CV_64F.

      • ksize: es el tamaño del núcleo del filtro. El tamaño del núcleo del filtro se refiere a la altura y el ancho de su imagen vecina durante el procesamiento medio. Por ejemplo, su valor puede ser (5, 5), lo que indica que se utiliza el valor medio de la vecindad de tamaño 5x5 como resultado del proceso de filtrado del valor medio de la imagen.

        imagen-20211014152435585

        M y N corresponden a alto y ancho, respectivamente. En general, M y N son iguales, como los más utilizados 3×3, 5×5, 7×7, etc. Si los valores de M y N son mayores, la cantidad de píxeles involucrados en la operación será mayor y la distorsión de la imagen será más grave.

      • Anchor: punto de anclaje, su valor por defecto es (-1, -1), lo que significa que el punto actual para el cálculo de la media se encuentra en el punto central del kernel, y el valor por defecto es suficiente, en casos especiales, un diferente El punto se puede especificar como el punto de anclaje.

      • borderType: estilo de borde, este valor determina cómo procesar el borde, generalmente no necesita considerar el valor de este valor, solo use el valor predeterminado.

Ejemplo:

import cv2

img = cv2.imread('../lena512color_noise.tiff')
dst1 = cv2.blur(img, (7, 7))
dst2 = cv2.blur(img, (15, 15))
cv2.imshow('img', img)
cv2.imshow('dst1', dst1)
cv2.imshow('dst2', dst2)
cv2.waitKey()
cv2.destroyAllWindows()

inserte la descripción de la imagen aquí

2. Caja de filtrado:

El filtrado de cuadro es diferente del filtrado medio en que el filtrado de cuadro no calcula los valores medios de píxeles. En el filtrado medio, el resultado del filtrado es el promedio de la vecindad de cualquier punto. El filtrado de caja puede elegir libremente si normalizar el resultado del filtrado medio y puede elegir libremente si la estructura de filtrado es la suma de los vecindarios o el promedio de la suma de los vecindarios.

1. Sintaxis del filtro de cuadro:

En OpenCV, la función que implementa el filtrado de cajas es cv2.boxFilter(), y su formato de sintaxis es:

dst = cv2.boxFilter(src, d depth, ksize, ancla, normalizar, borderType)

  • dst: valor devuelto, el resultado del procesamiento obtenido después del filtrado medio.

  • src: La imagen a procesar, es decir, la imagen original. Puede haber cualquier número de canales y cada canal se puede procesar de forma independiente. La profundidad de la imagen debe ser uno de CV_8U, CV_16U, CV_16S, CV_32F, CV_64F.

  • d depth: La profundidad de la imagen de la imagen resultante, generalmente use -1 para indicar la misma profundidad de imagen que la imagen original.

  • ksize: es el tamaño del núcleo del filtro. El tamaño del núcleo del filtro se refiere a la altura y el ancho de su imagen vecina durante el procesamiento medio. Por ejemplo, su valor puede ser (5, 5), lo que indica que se utiliza el valor medio de la vecindad de tamaño 5x5 como resultado del proceso de filtrado del valor medio de la imagen.

inserte la descripción de la imagen aquí

  • Anchor: punto de anclaje, el valor predeterminado es (-1, -1), lo que significa que el punto de cálculo actual se encuentra en el punto central del kernel, el valor predeterminado se puede usar para la modificación y se puede especificar un punto diferente como punto de anclaje en casos especiales.

  • normalizar: indica si se debe realizar el procesamiento de normalización (normalización: aquí se refiere a normalizar el resultado del cálculo a un rango razonable, es decir, normalizar el resultado del cálculo a un valor dentro del rango de valor de píxel actual) durante el filtrado. Este parámetro es un valor lógico.

    • Cuando el parámetro normalizar = 1, significa realizar el procesamiento de normalización, y se debe usar el valor de los píxeles vecinos y el área de procesamiento.
    • Cuando el parámetro normalizar = 0, significa que no se requiere el procesamiento de normalización, y la suma de los valores de píxeles vecinos se usa directamente. (255 cuando la suma excede 255)

    Por lo general, para el filtrado de cajas, el kernel de convolución se puede expresar como:
    inserte la descripción de la imagen aquí

La relación anterior correspondiente es:
f ( n ) = { 1 / ancho ⋅ alto , normalizar=1 1 , normalizar=0 f(n)= \begin{cases} 1/ancho·alto, & \text{normalizar=1} \ \ 1, & \text{normalizar=0} \end{casos}f ( n )={ 1 / ancho yo re t h altura , _ _ _ _ _1 ,normalizar=1normalizar= 0

  • borderType: estilo de borde, este valor determina cómo manejar el borde.

Normalmente, al usar la función de filtro de cuadro, para los parámetros ancla, normalizar y tipo de borde, puede usar directamente los valores predeterminados.

Ejemplo:

import cv2

img = cv2.imread('../lena512color_noise.tiff')
rst = cv2.boxFilter(img, -1, (7, 7))
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

inserte la descripción de la imagen aquí

3. Filtro gaussiano:

En el filtrado medio y el filtrado de caja, el peso de cada píxel en su vecindad es igual. En el filtrado gaussiano, el peso más cercano al punto central aumenta y el peso más alejado del punto central disminuye. Sobre esta base, se calcula la suma de los diferentes pesos de cada valor de píxel en la vecindad.

1. Principios básicos

  • En el filtrado gaussiano, el valor del kernel de convolución no es todo 1. como se muestra en la imagen

    imagen-20211016234515733

  • En el filtrado gaussiano, el ancho y el alto del kernel de convolución pueden ser diferentes, pero deben ser números impares.

    imagen-20211016234617059

  • Cada tamaño de kernel de convolución puede tener varias proporciones de peso en diferentes formas. Como se muestra en la figura, también es un núcleo de convolución de 5x5.

    imagen-20211016234752725

    En diferentes materiales, el núcleo de convolución tiene muchas representaciones diferentes. Pueden escribirse en una tabla o mostrarse en una matriz. En el cálculo real, el núcleo de convolución está normalizado, lo que se puede expresar como un núcleo de convolución en forma decimal o fraccionaria. El núcleo de convolución sin normalización se utiliza para ilustrar el problema. Estrictamente hablando, al utilizar un núcleo de convolución que no ha sido normalizado para el filtrado, los resultados suelen ser erróneos.

2. Sintaxis de la función :

En OpenCV, la función cv2.GaussianBlur() que implementa el filtrado gaussiano, el formato de sintaxis de esta función es:

dst = cv2.GauusianBlur(src, ksize, sigmaX, sigmaY, borderType)

  • dst: valor devuelto, el resultado del procesamiento obtenido después del filtrado medio.

  • src: La imagen a procesar, es decir, la imagen original. Puede haber cualquier número de canales y cada canal se puede procesar de forma independiente. La profundidad de la imagen debe ser uno de CV_8U, CV_16U, CV_16S, CV_32F, CV_64F.

  • ksize: es el tamaño del núcleo del filtro. El tamaño del núcleo del filtro se refiere a la altura y el ancho de su imagen vecina durante el procesamiento medio. Sin embargo, debe tenerse en cuenta que el valor del núcleo del filtro debe ser un número impar.

  • sigmaX: La desviación estándar del kernel de convolución en la dirección horizontal (dirección del eje X), que controla la relación de peso.

  • sigmaY: la desviación estándar del kernel de convolución en la dirección vertical (dirección del eje Y). Si este valor se establece en 0, solo se utilizará el valor de sigmaX; si tanto sigmaX como sigmaY son 0, pase ksize.width y ksize.height Calculado para obtener:

    • sigmaX = 0,3 × [(ktamaño.ancho-1) × 0,5-1] + 0,8
    • sigmaY = 0,3 × [(ktamaño.altura-1) × 0,5-1] + 0,8
  • borderType: estilo de borde, este valor determina cómo manejar el borde. En circunstancias normales, no es necesario tener en cuenta este valor y el valor predeterminado se usa directamente.

Nota: sigmaY y borderType son parámetros opcionales en esta función. sigmaX es un parámetro obligatorio, pero se puede establecer en 0 para permitir que la función calcule el valor específico de sigmaX por sí misma.

​ El documento oficial recomienda especificar los valores de los tres parámetros ksize, sigmaX y sigmaY para evitar errores de sintaxis que puedan ser causados ​​por futuras modificaciones de parámetros. Por supuesto, en el procesamiento real, los valores sigmaX y sigmaY especificados que se pueden mostrar son los valores predeterminados de 0. Por lo tanto, la forma común de la función cv2.GaussianBlur() es:

  • dst = cv2.GaussianBlur(src, ksize, 0, 0)

import cv2
o=cv2.imread("image\\lenaNoise.png")
r=cv2.GaussianBlur(o,5,5,0,0)
cv2.imshow("original",o)
cv2.imshow("result",r)
cv2.waitKey()
cv2.destroyAllWindows()

inserte la descripción de la imagen aquí

4. Filtrado mediano

El filtrado de la mediana es diferente del método de filtrado anterior y el valor del filtro ya no se utiliza para calcular el resultado del filtrado. Utiliza el valor medio de todos los valores de píxel en el vecindario para reemplazar el valor de píxel del píxel actual.

1. Principios básicos:

El filtrado mediano tomará los valores de píxel del píxel actual y los píxeles adyacentes que lo rodean (un total de píxeles impares), los ordenará y luego usará el valor de píxel en la posición media como el valor de píxel del píxel actual.

2. Sintaxis de la función:

En OpenCV, la función que implementa el filtrado mediano es cv2.medianBlur(), y su formato de sintaxis es:

dst = cv2.medianBlur(src, ksize)

  • dst: valor devuelto, el resultado del procesamiento obtenido después del filtrado medio.

  • src: La imagen a procesar, es decir, la imagen original. Puede haber cualquier número de canales y cada canal se puede procesar de forma independiente. La profundidad de la imagen debe ser uno de CV_8U, CV_16U, CV_16S, CV_32F, CV_64F.

  • ksize: es el tamaño del núcleo del filtro. El tamaño del núcleo del filtro se refiere a la altura y el ancho de su imagen vecina durante el procesamiento medio. Pero cabe señalar que el valor del kernel de filtro debe ser un número impar mayor que 1, como 3, 5, 7, etc.

Ejemplo:

import cv2

img = cv2.imread('../lena512color_noise.tiff')
rst = cv2.medianBlur(img, 5)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

inserte la descripción de la imagen aquí

A partir de los resultados se puede ver que, dado que no se realiza ningún procesamiento de valor medio, el filtro de mediana no tiene el problema de detalles borrosos causados ​​por métodos de filtrado como el filtrado medio. En el procesamiento de filtros medianos, es difícil seleccionar los componentes del ruido, por lo que es posible extraer todo el ruido sin afectar la imagen original. Pero la desventaja es que, debido a la necesidad de operaciones como la clasificación, el filtro de la mediana requiere una gran cantidad de cálculos.

Cinco, filtrado bilateral:

El filtrado bilateral es un método de filtrado que considera exhaustivamente la información espacial y la información de color, y puede proteger eficazmente la información de los bordes de la imagen durante el proceso de filtrado.

1. Principios básicos:

Los métodos de filtrado anteriores solo consideran la información de peso espacial, que es más conveniente de calcular, pero habrá un gran problema al procesar la información de borde. Por ejemplo, el lado izquierdo de la imagen es negro, el lado derecho es blanco y hay un borde afilado en el medio.

imagen-20211017103641068

En el filtrado medio, el filtrado de caja y el filtrado gaussiano, se calcula el promedio ponderado de cada píxel en el borde, desdibujando así la información del borde. La siguiente figura es la imagen procesada por filtrado Gaussiano:

imagen-20211017104218213

Al calcular el nuevo valor de un píxel, el filtrado bilateral no solo considera la información de la distancia (cuanto más lejos, menor el peso), sino también la información del color (cuanto mayor es la diferencia de color, menor es el peso). El filtrado bilateral considera la estructura de peso de la distancia y el color de manera integral, lo que no solo puede eliminar el ruido de manera efectiva, sino también proteger mejor la información de borde.

​ En el filtrado bilateral, cuando está en el borde, los píxeles que son similares en color al punto actual (la distancia de color es muy cercana) tendrán un mayor valor de peso; mientras que los píxeles que son más diferentes al color actual (la la distancia de color está lejos) se le dará un valor de peso más pequeño (el peso puede ser 0 en casos extremos, simplemente ignore este punto), protegiendo así la información del borde.

2. Sintaxis de la función:

En OpenCV, la función que implementa el filtrado bilateral es cv2.bilateralFilter(). La sintaxis de esta función es:

dst = cv2.bilateralFilter(src, d, sigmaColor, sigmaSpace, borderType)

  • dst: valor devuelto, el resultado del procesamiento obtenido después del filtrado medio.
  • src: La imagen a procesar, es decir, la imagen original. Puede haber cualquier número de canales y cada canal se puede procesar de forma independiente. La profundidad de la imagen debe ser uno de CV_8U, CV_16U, CV_16S, CV_32F, CV_64F.
  • d: El parámetro de distancia espacial seleccionado durante el filtrado, aquí representa el diámetro del punto central actual. Si el valor no es positivo, se calculará automáticamente a partir del parámetro sigmaSpace, si el espacio de filtrado es grande (d>5), la velocidad es menor. Por lo tanto, se recomienda d=5 en aplicaciones prácticas. Para filtrado fuera de línea con mayor ruido, se puede seleccionar d=9.
  • sigmaColor: el rango de diferencia de color seleccionado durante el filtrado, que determina qué píxeles circundantes pueden participar en el filtrado. Los píxeles cuya diferencia de valor de píxel con el píxel actual es menor que sigmaColor pueden participar en el filtrado actual. Cuanto mayor sea el valor, más píxeles circundantes podrán participar en el cálculo. Cuando el valor es 0, el filtrado no tiene sentido; cuando el valor es 255, todos los puntos dentro del diámetro especificado pueden participar en el cálculo.
  • sigmaSpagce: es el valor sigma en el espacio de coordenadas. Cuanto mayor sea su valor, más puntos pueden participar en el cálculo de filtrado. Cuando d > 0, d especifica el tamaño de la vecindad independientemente del valor de sigmaSpace; de ​​lo contrario, d es proporcional al valor de sigmaSpace.
  • borderType: estilo de borde, este valor determina cómo manejar el borde. En circunstancias normales, no es necesario tener en cuenta este valor y el valor predeterminado se usa directamente.

Para simplificar, puede configurar los valores de sigmaColor y sigmaSpagce para que sean iguales. Si sus valores son relativamente pequeños (menos de 10), el efecto de filtrado no es obvio; si sus valores son relativamente grandes (por ejemplo: mayores de 150), el efecto de filtrado será más obvio y un efecto de dibujos animados. se producira.

En la función cv2.lateralFilter(), excepto que borderType es un parámetro opcional, todos los demás parámetros son obligatorios.

import cv2

img = cv2.imread('../lena512color_noise.tiff')
rst = cv2.bilateralFilter(img, 25, 100, 100)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

inserte la descripción de la imagen aquí

Puede verse a partir de los resultados anteriores que el filtrado bilateral no es eficaz para eliminar el ruido. La ventaja del filtrado bilateral se refleja en el procesamiento de la información de borde.

import cv2
import numpy as np

img = np.zeros((500, 500), dtype=np.uint8)
img[:, :250] = 255
rst = cv2.bilateralFilter(img, 25, 100, 100)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

imagen-20211017104837702

Seis, convolución 2D

​ OpenCV proporciona una variedad de métodos de filtrado para lograr el efecto de suavizar imágenes, como filtrado medio, filtrado de caja, filtrado gaussiano, filtrado mediano, etc. Los núcleos de convolución utilizados en la mayoría de los métodos de filtrado tienen cierta flexibilidad, y el tamaño y el número de núcleos de convolución se pueden configurar fácilmente. Sin embargo, a veces queremos usar un kernel de convolución específico para implementar operaciones de convolución, por ejemplo, use los siguientes kernels de convolución para realizar operaciones de convolución.

imagen-20211017105649221

Ninguna de las funciones de filtro presentadas anteriormente puede determinar el kernel de convolución como el formulario anterior, por lo que se debe usar la función de convolución personalizada de OpenCV.

En OpenCV, los usuarios pueden personalizar el kernel de convolución para realizar la operación de convolución. La función de usar el kernel de convolución personalizado para realizar la operación de convolución es cv2.filer2D(), y su formato de sintaxis es:

dst = cv2.filter2D(src, d depth, kernel, ancla, delta, borderType)

  • dst: valor devuelto, el resultado del procesamiento obtenido después del filtrado medio.

  • src: La imagen a procesar, es decir, la imagen original. Puede haber cualquier número de canales y cada canal se puede procesar de forma independiente. La profundidad de la imagen debe ser uno de CV_8U, CV_16U, CV_16S, CV_32F, CV_64F.

  • d depth: La profundidad de la imagen de la imagen resultante, generalmente use -1 para indicar la misma profundidad de imagen que la imagen original.

  • kenel: El kernel de convolución es una matriz de un solo canal. Si desea utilizar diferentes núcleos para cada canal al procesar una imagen en color, debe descomponer la imagen en color y utilizar diferentes núcleos para operar.

  • Anchor: punto de anclaje, el valor predeterminado es (-1, -1), lo que significa que el punto de cálculo actual se encuentra en el punto central del kernel, el valor predeterminado se puede usar para la modificación y se puede especificar un punto diferente como punto de anclaje en casos especiales.

  • delta: valor de corrección. Opcional, si este valor existe, se agregará al resultado de filtrado básico como el resultado de filtrado final.

  • borderType: estilo de borde, este valor determina cómo manejar el borde. En circunstancias normales, no es necesario tener en cuenta este valor y el valor predeterminado se usa directamente.

Normalmente, cuando usa la función de filtro cv2.filter2D(), puede usar directamente los valores predeterminados para los parámetros ancla, delta y borderType.

Ejemplo: personalice un kernel de convolución, aplique el kernel de convolución para filtrar la imagen a través de la función cv2.filter2D() y muestre el resultado del filtrado.

imagen-20211017110708632

import cv2
import numpy as np

img = cv2.imread('../lena512color_noise.tiff')
kernal = np.ones((9, 9), dtype=np.float32) / 81
rst = cv2.filter2D(img, -1, kernal)
cv2.imshow('img', img)
cv2.imshow('rst', rst)
cv2.waitKey()
cv2.destroyAllWindows()

[Transferencia de imagen de enlace externo...(img-m8umG3dN-1642887693106)]

Supongo que te gusta

Origin blog.csdn.net/weixin_57440207/article/details/122646994
Recomendado
Clasificación