1 椒盐噪声是什么?
就是图片上出现的黑白点,类似于老式电视机出现雪花屏幕的感觉。
transforms
是pytorch定义的一个类,对图像进行各种变换,进行图像变换的目的是数据增强,使得模型的鲁棒性更加的强,尽管pytorch已经提供了很多的类别供我们选择,但在实际工程中这些往往还不够。因此需要因地制宜,制作属于自己项目的数据集变换策略。比如,添加椒盐噪声。
2 实际中,怎么进行椒盐噪声的添加呢?
在一张图片上随机的选择像素点,令其像素值为255(黑色)或者0(白色)。如下图是一个3通道的tensor图片,你可以看成是这样子的:每一个小格子上存储的就是像素值,那么上述添加椒盐噪声的问题就转换成了随机选择一些小格子,改变其像素值的问题。
tips:这个图示不是很“完善”,我只想让你直观的感受一下,整个过程类似于一个大的矩阵乘法(请大家意会一下,不要很在意具体数值是啥哈,思想更关键)
其中,mask矩阵中{0,1,2}是按照概率产生的。
0表示该位置处原图像的像素替换为255(白色);
1表示该位置处原图像的像素替换为0(黑色);
2表示该位置处原图像中的像素不变。
变换以后就是最右边的图像啦,关键就是这个mask矩阵的设置。我们需要确定:
mask矩阵的维度:要和原图像的维度一致
mask矩阵里随机生成的数值:依概率生成{0,1,2}
接下来对原图像操作,关键是对应索引处像素值的替换.
找到mask==1和0的位置
记录这个index
带原图像中将对应的index处的像素值按照替换规则替换
为了使模型还是比较好的能识别原图像,我们根据信噪比的大小来控制0,1,2出现的概率.假设信噪比是0.8,那么上述过程中2出现的概率就是0.8,0,1出现的概率均为0.1(概率和为1哦).
整个思路理清楚了,下面就是代码的实现了。附上代码:
class AddPepperNoise(object):
def __init__(self,snr,p):
self.snr = snr
self.p = p
def __call__(self,img):
# img是一个pil的图片格式,如果进行数据处理,就统一数据类型
img_pro = np.asarray(img).copy()## 自己忘记了加.copy(),这里还是不太明白为什么要加入.copy()
h,w,c = img_pro.shape
if np.random.rand() < self.p:
mask = np.random.choice((0,1,2), size = (h,w,1), p = [(1-self.snr)/2,(1-self.snr)/2],self.snr)
# mask_noise = img * mask
mask = np.repeat(mask,c,axis = 2)
img_pro[mask == 0] = 255
img_pro[mask == 1] = 0
img_after = Image.fromarray(img_pro.astype('uint8')).convert('RGB')
# 这里需要确定一下返回的数据的类型是什么,是tensor还是array呢?返回的是image PIL数据
else:
img_after = img
return img_after
3 总结 自己存在的问题:
mask矩阵的张量的shape不清楚,其实是(h,w,c);
在对原图像操作的时候,数据类型不正确;
因为transform接收的是一个数据,输出的也是一个数据,且都是PIL image格式的数据,所以在整个过程中要尤其注意:
\quad 读取image PIL格式数据;
\quad 转换成numpy格式的ndarray;
\quad 进行数学操作;
\quad 再转换为image PIL格式的数据。