Directorio de artículos
prefacio
Este artículo se refiere principalmente al Procesamiento de imágenes digitales de González (4.ª edición), presenta algunas formas comunes de ruido en imágenes y métodos de eliminación de ruido de uso común, y brinda el código de implementación de los métodos de filtrado correspondientes.
如果要使用本文代码,建议在Jupyter Notebook环境下运行。
1. Clasificación de ruido
1. Ruido gaussiano
Se refiere a un tipo de ruido que obedece a una distribución gaussiana (distribución normal). La razón principal de su generación es que el campo de visión de la cámara es oscuro y el brillo es desigual al disparar. Al mismo tiempo, la cámara funciona para mucho tiempo y la temperatura es demasiado alta para causar ruido gaussiano .
La función de densidad de probabilidad (PDF) es la siguiente:
Imagen inicial:
tenga en cuenta que al agregar ruido, no puede agregar directamente ruido+img, de lo contrario, el resultado final será un espacio en blanco y algunos puntos de ruido esporádicos. La razón es que el requisito de entrada de cv2.imshow es 0-1 float o 0 -255 int .
(1) Visualización de errores:
(2) Visualización correcta:
import cv2
import random
import numpy as np
img = cv2.imread('A.png')
# 产生高斯随机数
noise = np.random.normal(0,50,size=img.size).reshape(img.shape[0],img.shape[1],img.shape[2])
# 加上噪声
img = img + noise
img = np.clip(img,0,255)
img = img/255
cv2.imshow('Gauss noise',img)
cv2.waitKey(0)
(3) Filtro gaussiano
El filtro gaussiano es un filtro de suavizado lineal , generalmente utilizado para eliminar el ruido gaussiano. El valor de cada píxel se obtiene por el promedio ponderado de sí mismo y otros valores de píxel en el vecindario .
Función gaussiana bidimensional:
Proceso específico:
Código: Usar cv2.GaussianBlur()
la función
Tenga en cuenta que el radio de desenfoque gaussiano no puede ser un número par
Resultado del filtro:
2. Ruido venenoso
En definitiva, es un modelo de ruido que se ajusta a la distribución de Poisson, también conocida como ruido de disparo.
Utilice la función **np.random.poisson()**
import cv2
import random
import numpy as np
img = cv2.imread('A.png')
# 产生泊松噪声
noise = np.random.poisson(lam=20,size=img.shape).astype('uint8')
# 加上噪声
img = img + noise
np.clip(img,0,255)
img = img/255
cv2.imshow('Poisson noise',img)
cv2.waitKey(0)
Cuanto mayor sea el valor de λ, más profundo será el nivel de ruido.
3. Ruido de sal y pimienta
El ruido de sal y pimienta, también conocido como ruido de impulso, son píxeles en blanco y negro que aparecen aleatoriamente en la imagen. Como su nombre lo indica, ruido de sal y pimienta = ruido de pimienta (valor 0, negro) + ruido de sal (valor 255, blanco)
directamente en el código:
import cv2
import random
import numpy as np
img = cv2.imread('A.png')
# 转化成向量
x = img.reshape(1,-1)
# 设置信噪比
SNR = 0.85
# 得到要加噪的像素数目
noise_num = x.size * (1-SNR)
# 得到需要加噪的像素值的位置
list = random.sample(range(0,x.size),int(noise_num))
for i in list:
if random.random() >= 0.5:
x[0][i] = 0
else:
x[0][i] = 255
img1 = x.reshape(img.shape)
cv2.imshow('salt&pepper noise',img1)
cv2.waitKey(0)
Cuanto menor sea la SNR, mayor será el ruido.
4. Ruido de Rayleigh
Generalmente, es causado por un canal insatisfactorio.La relación entre este y la señal se multiplica.Si la señal está presente, no existirá si la señal no está presente.
La densidad de Rayleigh es útil para modelar histogramas con formas sesgadas.
La función de densidad de probabilidad (PDF) es la siguiente:
La distribución de Rayleigh dada en muchos lugares es la siguiente fórmula:
estas dos fórmulas son en realidad la misma fórmula, y solo es necesario realizar la siguiente sustitución de variables para obtener la misma forma que la primera fórmula .
Cuando se genera ruido de Rayleigh, **np.random.rayleigh()**
en realidad se utiliza el método para generarlo, y este método se basa en la segunda fórmula, por lo que solo se necesita especificar un parámetro , y la distribución obtenida es esencialmente la misma que la de la primera fórmula.
código:
import cv2
import random
import numpy as np
img = cv2.imread('A.png')
# 产生瑞利噪声
sigma = 70.0
noise = np.random.rayleigh(sigma, size=img.shape)
# 可以试试下面这个效果
# noise = np.random.rayleigh(img, size=img.shape)
# 加上噪声
img = img + noise
np.clip(img,0,255)
img = img/255
cv2.imshow('Rayleigh noise',img)
cv2.waitKey(0)
print(img.shape)
5. Ruido irlandés (gamma)
La función de densidad de probabilidad (PDF) es la siguiente: (b es un número entero positivo) La
distribución exponencial y la distribución chi-cuadrado en realidad se pueden considerar como formas especiales de la distribución gamma.
Cuando b = 1: distribución exponencial,
cuando b = n/2, a = 1/2: distribución chi-cuadrado.
código:
noise = np.random.gamma(shape=10.0,scale=10.0,size=img.shape)
#其他部分同上
6. Ruido uniforme
La función de densidad de probabilidad (PDF) es la siguiente:
Código:
noise = np.random.uniform(50,100,img.shape)
#其他部分同上
2. Método de eliminación de ruido
1. Filtrado medio
1.1 Filtrado de media aritmética
import cv2
import random
import numpy as np
img = cv2.imread('A.png')
# 产生高斯随机数
noise = np.random.normal(0,50,size=img.size).reshape(img.shape[0],img.shape[1],img.shape[2])
# 加上噪声
img = img + noise
img = np.clip(img,0,255)
img = img/255
# 算术平均滤波
img1 = np.transpose(img,(2,0,1)) #转换成[channel,H,W]形式
m = 3 #定义滤波核大小
n = 3
rec_img = np.zeros((img1.shape[0],img1.shape[1]-m+1,img1.shape[2]-n+1))
for channel in range(rec_img.shape[0]):
for i in range(rec_img[channel].shape[0]):
for j in range(rec_img[channel].shape[1]):
rec_img[channel][i,j] = img1[channel][i:i+m,j:j+n].sum()/(m*n)
rec_img = np.transpose(rec_img,(1,2,0))
cv2.imshow('average',rec_img)
cv2.waitKey(0)
El proceso específico se puede entender con la siguiente figura para comprender
el efecto de eliminación de ruido:
1.2 Filtrado de media geométrica
import cv2
import random
import numpy as np
img = cv2.imread('A.png')
# 产生高斯随机数
noise = np.random.normal(0,50,size=img.size).reshape(img.shape[0],img.shape[1],img.shape[2])
# 加上噪声
img = img + noise
img = np.clip(img,0,255)
img = img/255
# 几何均值滤波
img1 = np.transpose(img,(2,0,1)) #转换成[channel,H,W]形式
m = 3 #定义滤波核大小
n = 3
rec_img = np.zeros((img1.shape[0],img1.shape[1]-m+1,img1.shape[2]-n+1))
for channel in range(rec_img.shape[0]):
for i in range(rec_img[channel].shape[0]):
for j in range(rec_img[channel].shape[1]):
rec_img[channel][i,j] = np.power(np.prod(img1[channel][i:i+m,j:j+n]),1/(m*n))
rec_img = np.transpose(rec_img,(1,2,0))
cv2.imshow('average',rec_img)
cv2.waitKey(0)
Efecto de eliminación de ruido:
El filtrado de media geométrica es muy sensible a los valores 0 , y el defecto también es obvio, es decir, siempre que un píxel en la ventana tenga un valor de 0, el valor calculado es 0.
1.3 Filtrado de promedio de armónicos
rec_img[channel][i,j] = 1/(np.power(img1[channel][i:i+m,j:j+n],-1).sum())*(m*n)
# 其余部分同上
Este método puede manejar tanto el ruido de sal como otros ruidos similares al ruido de Gauss, pero no puede manejar el ruido de pimienta .
### 1.4
P: El orden del filtro. Útil para reducir o eliminar el ruido de sal y pimienta.
Nota: Cuando Q=0. Filtrado simplificado a media aritmética; Q=1, filtrado simplificado a media armónica.
código:
import cv2
import random
import numpy as np
img = cv2.imread('A.png')
#---------椒盐噪声----------
# 转化成向量
x = img.reshape(1,-1)
# 设置信噪比
SNR = 0.85
# 得到要加噪的像素数目
noise_num = x.size * (1-SNR)
# 得到需要加噪的像素值的位置
list = random.sample(range(0,x.size),int(noise_num))
for i in list:
if random.random() >= 0.5:
x[0][i] = 0
else:
x[0][i] = 255
img = x.reshape(img.shape)
img = img/255
#--------------------------
# 反谐波平均滤波
img1 = np.transpose(img,(2,0,1)) #转换成[channel,H,W]形式
m = 3 #定义滤波核大小
n = 3
Q = 0.1
rec_img = np.zeros((img1.shape[0],img1.shape[1]-m+1,img1.shape[2]-n+1))
for channel in range(rec_img.shape[0]):
for i in range(rec_img[channel].shape[0]):
for j in range(rec_img[channel].shape[1]):
rec_img[channel][i,j] = ((np.power(img1[channel][i:i+m,j:j+n],Q+1)).sum())/((np.power(img1[channel][i:i+m,j:j+n],Q)).sum())
rec_img = np.transpose(rec_img,(1,2,0))
cv2.imshow('average',rec_img)
cv2.waitKey(0)
Mapa de ruido:
Efecto de eliminación de ruido:
Nota: El valor de Q no debe ser demasiado grande, de lo contrario, se convertirá en la siguiente imagen (cuando Q=2):
2. Clasificación y filtrado estadístico
2.1 Filtrado mediano
Un método de eliminación de ruido con el que estamos muy familiarizados es reemplazar el valor del píxel con el valor de la mediana gris en la vecindad del píxel.
código:
import cv2
import random
import numpy as np
img = cv2.imread('A.png')
# 产生高斯随机数
noise = np.random.normal(0,50,size=img.size).reshape(img.shape[0],img.shape[1],img.shape[2])
# 加上噪声
img = img + noise
img = np.clip(img,0,255)
img = img/255
# 中值滤波
img1 = np.transpose(img,(2,0,1)) #转换成[channel,H,W]形式
m = 3 #定义滤波核大小
n = 3
rec_img = np.zeros((img1.shape[0],img1.shape[1]-m+1,img1.shape[2]-n+1))
for channel in range(rec_img.shape[0]):
for i in range(rec_img[channel].shape[0]):
for j in range(rec_img[channel].shape[1]):
rec_img[channel][i,j] = np.median(img1[channel][i:i+m,j:j+n])
rec_img = np.transpose(rec_img,(1,2,0))
cv2.imshow('median',rec_img)
cv2.waitKey(0)
Efecto de eliminación de ruido:
o usar directamentecv2.medianBlur()函数
import cv2
import random
import numpy as np
img = cv2.imread('A.png')
# 产生高斯随机数
noise = np.random.normal(0,50,size=img.size).reshape(img.shape[0],img.shape[1],img.shape[2])
# 加上噪声
img = img + noise
img = np.clip(img,0,255)
img = np.uint8(img)
# 中值滤波
rec_img = cv2.medianBlur(img,3)
cv2.imshow('median',rec_img)
cv2.waitKey(0)
2.2 Filtrado máximo y mínimo
Se utiliza principalmente para:np.amax() 和 np.amin()两个函数
2.3 Filtrado de punto medio
código:
rec_img[channel][i,j] = (np.amax(img1[channel][i:i+m,j:j+n]) + np.amin(img1[channel][i:i+m,j:j+n]))/2
Efecto de filtrado en el procesamiento de ruido gaussiano :
2.4 Filtrado de la media alfa modificada
Método de procesamiento: en la vecindad S xy S_{xy}Sx yeliminar dentro de d/2 d/2d /2 valores de gris más bajos yd/2 d/2d /2 valor de gris más alto. g R ( r , c ) g_{R}(r,c)gramoR( R ,c ) significaS xy S_{xy}Sx yEl resto mn − d mn-d enMinnesota−d píxeles.
re = 0 re = 0d=0 : se convierte en filtro de media aritmética
d = mn − 1 d=mn-1d=Minnesota−1 : Filtrado mediano
código:
import cv2
import random
import numpy as np
img = cv2.imread('A.png')
# 产生高斯随机数
noise = np.random.normal(0,50,size=img.size).reshape(img.shape[0],img.shape[1],img.shape[2])
# 加上噪声
img = img + noise
img = np.clip(img,0,255)
img = img/255
# 修正阿尔法均值滤波
img1 = np.transpose(img,(2,0,1)) #转换成[channel,H,W]形式
m = 3 #定义滤波核大小
n = 3
d = 4 #d取偶数
rec_img = np.zeros((img1.shape[0],img1.shape[1]-m+1,img1.shape[2]-n+1))
for channel in range(rec_img.shape[0]):
for i in range(rec_img[channel].shape[0]):
for j in range(rec_img[channel].shape[1]):
img2 = np.sort(np.ravel(img1[channel][i:i+m,j:j+n])) #np.ravel():多维数组变成一维数组
rec_img[channel][i,j] = (img2[int(d/2):-int(d/2)].sum())*(1/(m*n-d))
rec_img = np.transpose(rec_img,(1,2,0))
cv2.imshow('alpha average',rec_img)
cv2.waitKey(0)
Efecto de eliminación de ruido:
Resumir
La introducción trata principalmente sobre algunos filtros muy básicos. La función de filtrado solo puede ser efectiva para cierto tipo de ruido, y su efecto de filtrado generalmente no es muy bueno. Para los tipos de ruido complicados en el entorno real, es necesario usar más adecuados, mejores métodos de filtrado, pero estos métodos se basan más o menos en estos métodos básicos para optimizar y mejorar continuamente. Habrá tiempo para actualizar algunos métodos de eliminación de ruido más fuertes más adelante.
Puede haber problemas y deficiencias en algunos lugares, ¡bienvenido a comunicarse con nosotros!
referencias:
[1] Ruan Qiuqi, traducido por Ruan Yuzhi; (EE. UU.) Raphael C. Gonzalez, Richard E. Woods. Digital Image Processing 4th Edition of Foreign E-books and Communication Textbook Series [M]. Beijing: Electronic Industry Press, 2020