椒盐噪声 Python实现
最近碰到一个过拟合问题(感觉在工程里大部分时间都在解决过拟合,只要选正确模型~),想通过增加椒盐噪声来增加训练样本的多样性,对椒盐噪声有了新的认识——原来 椒盐噪声 = 椒噪声 + 盐噪声
椒盐噪声概念
椒盐噪声又称为脉冲噪声,它是一种随机出现的白点或者黑点,如下图。
在机器学习的图像分类任务中,为图像增加椒盐噪声是一种常用的数据增强方法,这里就介绍添加椒盐噪声的函数(基于python)。
椒盐噪声数学定义
信噪比
在噪声的概念中,通常采用信噪比(Signal-Noise Rate, SNR)衡量图像噪声。通俗的讲就是信号占多少,噪声占多少,SNR越小,噪声占比越大。
在信号系统中,计量单位为dB,为10lg(PS/PN), PS和PN分别代表信号和噪声的有效功率。
在这里,采用信号像素点的占比充当SNR,以衡量所添加噪声的多少。
举个例,假设一张图像的宽x高 = 10x10 ,共计100个像素,想让其中20个像素点变为噪声,其余80个像素点保留原值,则这里定义的SNR=80/100 = 0.8 。
一开始也说了,椒盐噪声 = 椒噪声 + 盐噪声 ,椒盐噪声的值为0(黑色)或者255(白色),这里假设为等概率的出现0或者255。
为图像添加椒盐噪声的的步骤如下:
- 依SNR制作mask,用于判断像素点是原始信号,还是噪声
- 依mask给原图像赋噪声值
椒盐噪声代码实现
def addsalt_pepper(img, SNR):
img_ = img.copy()
c, h, w = img_.shape
mask = np.random.choice((0, 1, 2), size=(1, h, w), p=[SNR, (1 - SNR) / 2., (1 - SNR) / 2.])
mask = np.repeat(mask, c, axis=0) # 按channel 复制到 与img具有相同的shape
img_[mask == 1] = 255 # 盐噪声
img_[mask == 2] = 0 # 椒噪声
return img_
注意事项,输入的img的shape有规定,需要是 c,h,w。可自行修改
执行以下脚本,可以查看不同SNR下添加椒盐噪声的效果。
# coding: utf-8
import numpy as np
import cv2
from matplotlib import pyplot as plt
def addsalt_pepper(img, SNR):
img_ = img.copy()
c, h, w = img_.shape
mask = np.random.choice((0, 1, 2), size=(1, h, w), p=[SNR, (1 - SNR) / 2., (1 - SNR) / 2.])
mask = np.repeat(mask, c, axis=0) # 按channel 复制到 与img具有相同的shape
img_[mask == 1] = 255 # 盐噪声
img_[mask == 2] = 0 # 椒噪声
return img_
img = cv2.imread('your_path.jpg')
SNR_list = [0.9, 0.7, 0.5, 0.3]
sub_plot = [221, 222, 223, 224]
plt.figure(1)
for i in range(len(SNR_list)):
plt.subplot(sub_plot[i])
img_s = addsalt_pepper(img.transpose(2, 1, 0), SNR_list[i]) # c,
img_s = img_s.transpose(2, 1, 0)
cv2.imshow('PepperandSalt', img_s)
cv2.waitKey(0)
plt.imshow(img_s[:,:,::-1]) # bgr --> rgb
plt.title('add salt pepper noise(SNR={})'.format(SNR_list[i]))
plt.show()
最终得到小猫图像如下: