背景

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%时,输入原始图像和输出噪声图像分别如下图所示:

去除椒盐噪声python代码 椒盐噪声怎么加_机器学习

去除椒盐噪声python代码 椒盐噪声怎么加_去除椒盐噪声python代码_02

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。所以,当需要特别精准地增加一定比例噪声时,这个方法不是很好。