背景
1. Python加上for循环速度超级慢,特别是放在比较大型工程中,会使整个工程的运行效率大大降低
2. 在一些情况下,需要对图像加入噪声,检验模型的鲁棒性
基于以上背景,需要不加for循环的椒盐噪声增加方法,实现在不降低程序运行速度的前提下,为图像增加特定比例的椒盐噪声。‘
工具
numpy, random 和 cv2
具体实现步骤
步骤拆解:
import random
import cv2 as cv
import numpy as np
# 读入图像并获取图像尺寸
image = cv.imread(r'E:\a_data_refine\Stone331\image\738.jpg', cv.IMREAD_UNCHANGED)
h, w, c = image.shape
# 生成椒盐噪声,噪声比例为 10%
pepper = random.choice(range(10)) * 0.01 # 黑胡椒噪声比例
salt = 0.1 - pepper # 盐噪声比例
# 使用random.choice()函数获取椒盐噪声图像
# 其中,(0, -255, 255) 表示从这三个数中随机选取, size表示输出数组尺寸
# p表示上面三个数所占比例
# 最后使用repeat函数,使得每个通道相同位置像元值一致
noise = np.random.choice((0, -255, 255), size=(h, w, 1), p=[0.9, pepper, salt])
noise = np.repeat(noise, c, axis=2)
# 将噪声加到输入图像上
# 将噪声数组和输入图像相加,并将数组的值限制在0~255之间
# 使低于0的像元值为0,高于255的像元值为255
noisy_image = np.clip(image + noise, 0, 255)
noisy_image = noisy_image.astype(np.uint8)
对应函数:
def add_noise(root, pro):
"""
:param root: 图像路径
:param pro: 噪声比例, 使用百分数表示, 如 10, 20
"""
# 读入图像并获取图像尺寸
image = cv.imread(root, cv.IMREAD_UNCHANGED)
h, w, c = image.shape
# 生成椒盐噪声,噪声比例为 pro%
pepper = random.choice(range(pro)) * 0.01 # 黑胡椒噪声比例
salt = pro/100 - pepper # 盐噪声比例
# 使用random.choice()函数获取椒盐噪声图像
# 其中,(0, -255, 255) 表示从这三个数中随机选取, 其中255表示图像值为0~255
# size表示输出数组尺寸
# p表示上面三个数所占比例
# 最后使用repeat函数,使得每个通道相同位置像元值一致
noise = np.random.choice((0, -255, 255), size=(h, w, 1), p=[1-pro/100, pepper, salt])
noise = np.repeat(noise, c, axis=2)
# 将噪声加到输入图像上
# 将噪声数组和输入图像相加,并将数组的值限制在0~255之间
# 使低于0的像元值为0,高于255的像元值为255
noisy_image = np.clip(image + noise, 0, 255)
noisy_image = noisy_image.astype(np.uint8)
return noisy_image
效果图:
当指定噪声比例为10%时,输入原始图像和输出噪声图像分别如下图所示:
Fig. 1 原始图像 | Fig. 2 噪声图像 |
注意:
最后,值得注意的是,本方法实现的噪声比例是不精准的。也就是说,当指定增加10%噪声时,可能这个噪声比例不是正好的10%,请看示例:
noise = np.random.choice((0, 1), size=(100, 100, 1), p=[0.9, 0.1])
np.sum(noise)
Out[304]: 1018
1018/(100*100)
Out[305]: 0.1018
可以看出,当指定出现1的概率为0.1时,返回数组中1出现的概率为0.1018。所以,当需要特别精准地增加一定比例噪声时,这个方法不是很好。