Filtros de desenfoque en OpenCV

Salman Mehmood 21 junio 2022
Filtros de desenfoque en OpenCV

Esta demostración presentará cómo suavizar o desenfocar imágenes en OpenCV. Discutiremos los diferentes tipos de filtros de desenfoque y cómo usarlos al final de este artículo.

Use diferentes tipos de filtros de desenfoque en OpenCV

El suavizado, también conocido como desenfoque, es una de las operaciones más utilizadas en el procesamiento de imágenes. Se utiliza comúnmente para eliminar el ruido de las imágenes.

Podemos usar diversos filtros lineales porque los filtros lineales son fáciles de lograr y relativamente rápidos. Hay varios tipos de filtros disponibles en OpenCV, por ejemplo, filtros homogéneos, gaussianos, medianos o bilaterales, que veremos individualmente.

En primer lugar, veremos el filtro homogéneo. El filtro homogéneo es simple y cada píxel de salida es la media de sus vecinos del núcleo en un filtro homogéneo.

Todos los píxeles contribuyen con el mismo peso, por lo que se denominan filtros homogéneos. En otras palabras, el núcleo es una forma que podemos aplicar o convolucionar sobre una imagen.

El numpy crea este tipo de núcleo cuadrado. Entonces, en un filtro homogéneo, el núcleo se parece a esta imagen.

Opencv Desenfoque Ejemplo 1

En el filtro homogéneo, el kernel K es igual a 1 dividido por el ancho del kernel multiplicado por la altura del kernel. Si queremos usar un kernel de 5 por 5 usando esta fórmula, entonces tendremos K igual a 1 dividido por 25, y tendremos una matriz kernel de 5 por 5 de 1s.

Opencv Desenfoque Ejemplo 2

Ahora, necesitamos crear este kernel para el filtrado de imágenes usando filter2D() o el filtro homogéneo. Primero, leeremos una imagen usando el método imread().

IMG = cv2.imread("opencv-logo.jpg")

Necesitamos convertir la imagen de BGR a RGB porque matplotlib lee las imágenes en formato RGB y OpenCV lee las imágenes en formato BGR.

IMG = cv2.cvtColor(IMG, cv2.COLOR_BGR2RGB)

Necesitamos definir un kernel 5x5 usando el método ones() con el tipo de datos float32, y lo dividiremos por 25.

K = np.ones((5, 5), np.float32) / 25

Ahora, podemos definir nuestra imagen de destino asistiendo al kernel definido. Se utiliza un método llamado filter2D() para el filtro homogéneo.

El primer parámetro será la imagen de origen, el segundo es la profundidad deseada de la imagen de destino y el tercero es el kernel.

HMG = cv2.filter2D(IMG, -1, K)

En la siguiente línea, estamos iterando un bucle for, y mostraremos imágenes en matplotlib en formato 1 por 2 a través de este bucle.

for j in range(2):
    plot.subplot(1, 2, j + 1), plot.imshow(IMGS[j], "gray")

Código fuente de ejemplo completo:

import numpy as np
import matplotlib.pyplot as plot

IMG = cv2.imread("opencv-logo.jpg")
IMG = cv2.cvtColor(IMG, cv2.COLOR_BGR2RGB)

K = np.ones((5, 5), np.float32) / 25
HMG = cv2.filter2D(IMG, -1, K)


T = ["Original IMG", "2D Convolution"]
IMGS = [IMG, HMG]

for j in range(2):
    plot.subplot(1, 2, j + 1), plot.imshow(IMGS[j], "gray")
    plot.title(T[j])
    plot.xticks([]), plot.yticks([])

plot.show()

Podemos ver un poco de ruido en las esquinas y, después de aplicar la convolución 2D sobre esta imagen, las esquinas se suavizan o desenfocan ligeramente. Los ruidos son eliminados o suprimidos por este desenfoque, por lo que esta es una forma de desenfocar una imagen utilizando el método filter2D().

Salida de desenfoque Opencv 1

Filtro de desenfoque

Las imágenes unidimensionales se pueden filtrar con filtros de paso bajo o filtros de paso alto. El filtro de paso bajo ayuda a eliminar el ruido o la borrosidad de la imagen, etc., y el filtro de paso alto ayuda a encontrar bordes en las imágenes.

Para lograr una imagen borrosa, debe convertir la imagen con el filtro de paso bajo. Varios tipos de algoritmos están disponibles en OpenCV; el primer algoritmo es el método blur().

El método blur() también se denomina método de promedio, que usaremos para aplicar el algoritmo de promedio para hacer la imagen borrosa. Este método toma dos parámetros: el primero es la imagen y el segundo es el núcleo, que será (5,5).

import cv2
import numpy as np
import matplotlib.pyplot as plot

IMG = cv2.imread("opencv-logo.jpg")
IMG = cv2.cvtColor(IMG, cv2.COLOR_BGR2RGB)

K = np.ones((5, 5), np.float32) / 25
HMG = cv2.filter2D(IMG, -1, K)
BL = cv2.blur(IMG, (5, 5))

T = ["Original IMG", "2D Convolution", "Blur"]
IMGS = [IMG, HMG, BL]

for j in range(3):
    plot.subplot(1, 3, j + 1), plot.imshow(IMGS[j], "gray")
    plot.title(T[j])
    plot.xticks([]), plot.yticks([])

plot.show()

El resultado, más o menos, se ve igual entre la convolución 2D y el desenfoque porque hemos aplicado el mismo tipo de kernel a ambas funciones.

Salida de desenfoque Opencv 2

Filtro gaussiano

Veamos el siguiente algoritmo, que es el algoritmo de filtro Gaussiano. El filtro gaussiano no es más que usar un kernel de diferente peso en ambas direcciones x e y.

En la salida, los píxeles se ubican en el medio del kernel con un peso mayor o mayor. Los pesos disminuyen con la distancia desde el centro de la vecindad.

Los píxeles de menor peso se ubican en el costado y los píxeles de mayor peso se ubican en el centro.

Cuando tomamos un kernel 5x5, su resultado se verá como el que se muestra en la imagen.

Opencv Desenfoque Ejemplo 3

Veamos cómo podemos usar el método GaussianBlur() en OpenCV. Los parámetros son los mismos que los del método blur(), por lo que el primer parámetro es la imagen de entrada, el segundo es nuestro kernel y el tercero es el valor Sigma X.

import cv2
import numpy as np
import matplotlib.pyplot as plot

IMG = cv2.imread("eye.jpg")
IMG = cv2.cvtColor(IMG, cv2.COLOR_BGR2RGB)

K = np.ones((5, 5), np.float32) / 25
HMG = cv2.filter2D(IMG, -1, K)
BL = cv2.blur(IMG, (5, 5))
GB = cv2.GaussianBlur(IMG, (5, 5), 0)

T = ["Original IMG", "2D Convolution", "Blur", "GaussianBlur"]
IMGS = [IMG, HMG, BL, GB]

for j in range(4):
    plot.subplot(2, 2, j + 1), plot.imshow(IMGS[j], "gray")
    plot.title(T[j])
    plot.xticks([]), plot.yticks([])

plot.show()

Podemos observar que el resultado del método GaussianBlur() es mejor que los otros métodos de desenfoque.

Mire la imagen original, que tiene demasiado ruido. Todo el ruido se elimina después de aplicar el método GaussianBlur().

Por lo tanto, el método GaussianBlur() está diseñado específicamente para eliminar el ruido de alta frecuencia de una imagen.

Salida de desenfoque Opencv 3

Filtro mediano

El filtro de mediana es algo que reemplaza cada valor de píxel con la mediana de su píxel vecino. El método medianBlur() es excelente cuando se trata de una imagen con ruido de sal y pimienta.

Si quieres saber más sobre el ruido de la sal y la pimienta, sigue este enlace.

Tenemos aquí una imagen; algunos píxeles están distorsionados, algunos son los puntos blancos o el ruido blanco, y algunos son donde se ve el ruido negro. Debido a que los píxeles están distorsionados como la sal y los píxeles negros parecen pimienta, se denomina ruido de sal y pimienta.

Imagen de muestra de agua

Usemos esta imagen como fuente en el método medianBlur(). La imagen de origen será el primer parámetro y el segundo será el tamaño del kernel.

Debemos tener en cuenta que el tamaño del núcleo debe ser impar, como 3, 5, 7, etc., excepto 1. Si usa 1, le mostrará la imagen original.

import cv2
import numpy as np
import matplotlib.pyplot as plot

IMG = cv2.imread("water.jpg")
IMG = cv2.cvtColor(IMG, cv2.COLOR_BGR2RGB)

K = np.ones((5, 5), np.float32) / 25
HMG = cv2.filter2D(IMG, -1, K)
BL = cv2.blur(IMG, (5, 5))
GB = cv2.GaussianBlur(IMG, (5, 5), 0)
MB = cv2.medianBlur(IMG, 5)

T = ["Original IMG", "2D Convolution", "Blur", "GaussianBlur", "medianBlur"]
IMGS = [IMG, HMG, BL, GB, MB]

for j in range(5):
    plot.subplot(2, 3, j + 1), plot.imshow(IMGS[j], "gray")
    plot.title(T[j])
    plot.xticks([]), plot.yticks([])

plot.show()

Vemos a continuación el mejor resultado que obtenemos usando el método medianBlur().

Salida de desenfoque Opencv 4

Filtro Bilateral

Veamos el último filtro, que se llama filtro bilateral. Entonces, al usar otros filtros, no solo disolvimos el ruido sino que también suavizamos los bordes.

A veces necesitamos conservar los bordes, lo que significa que todos los bordes permanecen nítidos incluso si la imagen está borrosa.

El método bilateralFilter() toma la imagen como primer parámetro. El segundo parámetro es el diámetro de cada píxel utilizado durante el filtro, el tercer parámetro es el color Sigma y el cuarto es el espacio Sigma.

El color Sigma es el filtro Sigma en el espacio de color, y el espacio Sigma es el filtro Sigma en el espacio de coordenadas.

import cv2
import numpy as np
import matplotlib.pyplot as plot

IMG = cv2.imread("lena-1.jpg")
IMG = cv2.cvtColor(IMG, cv2.COLOR_BGR2RGB)

K = np.ones((5, 5), np.float32) / 25
HMG = cv2.filter2D(IMG, -1, K)
BL = cv2.blur(IMG, (5, 5))
GB = cv2.GaussianBlur(IMG, (5, 5), 0)
MB = cv2.medianBlur(IMG, 5)
BF = cv2.bilateralFilter(IMG, 9, 75, 75)

T = [
    "Original IMG",
    "2D Convolution",
    "Blur",
    "GaussianBlur",
    "medianBlur",
    "bilateralFilter",
]
IMGS = [IMG, HMG, BL, GB, MB, BF]
plot.figure(figsize=(8, 6))
for j in range(6):
    plot.subplot(2, 3, j + 1), plot.imshow(IMGS[j], "gray")
    plot.title(T[j])
    plot.xticks([]), plot.yticks([])

plot.show()

Mira como se conservan mucho mejor los bordes donde se aplica el método bilateralFilter(). El filtro bilateral es muy eficaz para eliminar el ruido manteniendo los bordes nítidos.

Salida de desenfoque Opencv 5

Salman Mehmood avatar Salman Mehmood avatar

Hello! I am Salman Bin Mehmood(Baum), a software developer and I help organizations, address complex problems. My expertise lies within back-end, data science and machine learning. I am a lifelong learner, currently working on metaverse, and enrolled in a course building an AI application with python. I love solving problems and developing bug-free software for people. I write content related to python and hot Technologies.

LinkedIn

Artículo relacionado - Python OpenCV