原始图像为:
一:给图像增加噪声
import numpy as np
import random
import cv2
import matplotlib.pyplot as plt
# 展示图像,封装成函数
def cv_show_image(name, img):
cv2.imshow(name, img)
cv2.waitKey(0) # 等待时间,单位是毫秒,0代表任意键终止
cv2.destroyAllWindows()
def sp_noise(image,prob):
'''
添加椒盐噪声
prob:噪声比例
'''
output = np.zeros(image.shape,np.uint8)
# thres = 1 - prob
for i in range(image.shape[0]):
for j in range(image.shape[1]):
rdn = random.random() # 每次取随机值,判断这个位置的像素点是否应该被替换为噪声?
if rdn < prob:
output[i][j] = 255 # 小于某个阈值的设置为255,这个是亮点噪声
# elif rdn > thres:
# output[i][j] = 255 # 大于某个阈值的设置为0,这个就是暗点噪声
else:
output[i][j] = image[i][j]
return output
def gasuss_noise(image, mean=0, var=0.001):
'''
添加高斯噪声
mean : 均值
var : 方差
'''
image = np.array(image/255.0, dtype=float) # 将图像的数值改到 0 ~ 1
noise = np.random.normal(mean, var ** 0.5, image.shape) # 得到一段正态分布的数据,shape值和图像一致
out = image + noise # 二者相加就是带图像的噪声了
# clip 函数解释,对数据做截断操作,a:输入矩阵;a_min:被限定的最小值,所有比a_min小的数都会强制变为a_min;
# a_max:被限定的最大值,所有比a_max大的数都会强制变为a_max;
# out:可以指定输出矩阵的对象,shape与a相同
out = np.clip(out, 0, 1.0)
out = np.uint8(out*255) # 图像数值还原到 0 ~ 255
return out
def normal_noise(img):
noise = np.zeros(img.shape, np.int8)
cv2.randn(noise, (0, 0, 0), (100, 100, 100)) # 图像是(H, W, C),通道是三个,要给每个通道都设置均值和方差
img_noise = cv2.add(img, noise, dtype=cv2.CV_8UC3)
return img_noise
def uniform_noise(img):
noise = np.zeros(img.shape, np.int8)
cv2.randu(noise, (0, 0, 0), (100, 100, 100)) # 图像是(H, W, C),通道是三个,要给每个通道都设置均值和方差
img_noise = cv2.add(img, noise, dtype=cv2.CV_8UC3)
return img_noise
img = cv2.imread('images/naruto.jpg') # 读取原始图像
cv_show_image('img_src', img)
# 增加噪声
img_noise = sp_noise(img, 0.1) # 增加椒盐噪声
cv_show_image('img_noise', img_noise)
# 增加噪声
img_noise = gasuss_noise(img, 0, 0.1) # 增加正态分布的噪声
cv_show_image('img_noise', img_noise)
# 增加噪声
img_noise = normal_noise(img) # 增加正态分布的噪声
cv_show_image('img_noise', img_noise)
# 增加噪声
img_noise = uniform_noise(img) # 增加正态分布的噪声
cv_show_image('img_noise', img_noise)
以椒盐噪声为例
二:各种滤波
代码承接上面的函数
1:均值滤波
# 做滤波操作,平滑处理
# 均值滤波: # 在每个像素点的周围卷积核大小的核的范围内,取其这个范围内所有像素点的平均值。
img = cv2.imread('images/naruto.jpg') # 读取原始图像
img_noise = sp_noise(img, 0.1) # 增加椒盐噪声
cv_show_image('img_noise', img_noise)
blur = cv2.blur(img_noise, (3, 3))
cv_show_image('blur', blur)
2:方框滤波
# 做滤波操作,平滑处理
# 方框滤波: 和均值滤波基本一致,就是可以选择最后有没有可以做归一化的操作,求平均就是归一化的操作
img = cv2.imread('images/naruto.jpg') # 读取原始图像
img_noise = sp_noise(img, 0.1) # 增加椒盐噪声
cv_show_image('img_noise', img_noise)
boxblur = cv2.boxFilter(img_noise, -1, (3, 3), normalize=True) # -1代表使用原图深度,即src.depth()。
cv_show_image('boxblur', boxblur)
boxblur = cv2.boxFilter(img_noise, -1, (3, 3), normalize=False) # -1代表使用原图深度,即src.depth()。
cv_show_image('boxblur', boxblur)
3:高斯滤波
# 做滤波操作,平滑处理
# 高斯滤波: # 在每个像素点的周围卷积核大小的核的范围内,按照高斯分布的特点,距离较近的取更大的权重,距离较远的取较小的权重。
# 上述的均值滤波和方框滤波,每一个像素点的权值都是一样的,
# 而高斯分布是人为距离核心像素点越近的,关系越紧密,越更加重视。距离越远的,关系越小,越不应该重视。
img = cv2.imread('images/naruto.jpg') # 读取原始图像
img_noise = sp_noise(img, 0.1) # 增加椒盐噪声
cv_show_image('img_noise', img_noise)
gauss_blur = cv2.GaussianBlur(img_noise, (3, 3), 1) # 1是sigmaX,表示高斯核函数在X方向的的标准偏差
cv_show_image('gauss_blur', gauss_blur)
4:中值滤波
# 做滤波操作,平滑处理
# 中值滤波: # 在每个像素点的周围卷积核大小的核的范围内,取其这个范围内所有像素点的中位数值。
# 在均值滤波器中,由于噪声成分被放入平均计算中,所以输出受到了噪声的影响,但在中值滤波器中,由于噪声成分很难选上,所以几乎不会影响到输出。因此同样用3x3区域进行处理,中值滤波消除的噪声能力更胜一筹。中值滤波无论是在消除噪声还是保存边缘方面都是一个不错的方法。
img = cv2.imread('images/naruto.jpg') # 读取原始图像
img_noise = sp_noise(img, 0.1) # 增加椒盐噪声
cv_show_image('img_noise', img_noise)
med_blur = cv2.medianBlur(img_noise, 5) # 5是5x5的核大小的意思
cv_show_image('med_blur', med_blur)
5:双边滤波
# 做滤波操作,平滑处理
# 双边滤波(Bilateral filter)是一种非线性的滤波方法,是结合图像的空间邻近度和像素值相似度的一种折衷处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。具有简单、非迭代、局部的特点
img = cv2.imread('images/naruto.jpg') # 读取原始图像
img_noise = sp_noise(img, 0.1) # 增加椒盐噪声
cv_show_image('img_noise', img_noise)
bi_blur = cv2.bilateralFilter(src=img_noise, d=0, sigmaColor=100, sigmaSpace=15)
cv_show_image('bi_blur', bi_blur)