图像噪声是指存在于图像数据中的不必要的或多余的干扰信息。在噪声的概念中,通常采用信噪比(Signal-Noise Rate, SNR)衡量图像噪声。通俗的讲就是信号占多少,噪声占多少,SNR越小,噪声占比越大。
1.常见的图像噪声
(1)高斯噪声
高斯噪声Gaussian noise,是指它的概率密度函数服从高斯分布(即正态分布)的一类噪声,通常是因为不良照明和高温引起的传感器噪声。
(2) 椒盐噪声
椒盐噪声salt-and-pepper noise,又称为脉冲噪声,它是一种随机出现的白点(盐噪声)或者黑点(椒噪声),通常是由图像传感器,传输信道,解压处理等产生的黑白相间的亮暗点噪声(椒-黑,盐-白)。常用的去除这种噪声的有效手段是使用中值滤波器。
2.生成图像噪声
在原始图像基础上加上噪声分量,即可生成图像噪声
(1)高斯噪声
def gaussian_noise(image, mean=0.1, sigma=0.1): """ 添加高斯噪声 :param image:原图 :param mean:均值 :param sigma:标准差 值越大,噪声越多 :return:噪声处理后的图片 """ image = np.asarray(image / 255, dtype=np.float32) # 图片灰度标准化 noise = np.random.normal(mean, sigma, image.shape).astype(dtype=np.float32) # 产生高斯噪声 output = image + noise # 将噪声和图片叠加 output = np.clip(output, 0, 1) output = np.uint8(output * 255) return output
(2) 椒盐噪声(速度慢)
常规的方法,需要遍历每个像素,添加椒盐噪声,该方法十分缓慢。Python语言十分不建议进行图像像素遍历操作,毕竟性能太差,速度太慢了(除非写成C/C++版本)。我们可以借助numpy的矩阵处理,实现快速的添加椒盐噪声。
def salt_pepper_noise(image: np.ndarray, prob=0.01): """ 添加椒盐噪声,该方法需要遍历每个像素,十分缓慢 :param image: :param prob: 噪声比例 :return: """ for i in range(image.shape[0]): for j in range(image.shape[1]): if random.random() < prob: image[i][j] = 0 if random.random() < 0.5 else 255 else: image[i][j] = image[i][j] return image
(3) 椒盐噪声(快速版)
我们可以借助numpy的矩阵处理,实现快速的添加椒盐噪声。基本思路:利用np.random.uniform生成0~1的均匀噪声( uniform distribution noise),然后将noise > prob的像素设置0或者255,这样通过矩阵的处理,可以快速添加椒盐噪声。
def fast_salt_pepper_noise(image: np.ndarray, prob=0.02): """ 随机生成一个0~1的mask,作为椒盐噪声 :param image:图像 :param prob: 椒盐噪声噪声比例 :return: """ image = add_uniform_noise(image, prob * 0.51, vaule=255) image = add_uniform_noise(image, prob * 0.5, vaule=0) return image def add_uniform_noise(image: np.ndarray, prob=0.05, vaule=255): """ 随机生成一个0~1的mask,作为椒盐噪声 :param image:图像 :param prob: 噪声比例 :param vaule: 噪声值 :return: """ h, w = image.shape[:2] noise = np.random.uniform(low=0.0, high=1.0, size=(h, w)).astype(dtype=np.float32) # 产生高斯噪声 mask = np.zeros(shape=(h, w), dtype=np.uint8) + vaule index = noise > prob mask = mask * (~index) output = image * index[:, :, np.newaxis] + mask[:, :, np.newaxis] output = np.clip(output, 0, 255) output = np.uint8(output) return output
3. Demo性能测试
需要用到pybaseutils工具,pip安装即可
# -*-coding: utf-8 -*- """ @Author : panjq @E-mail : [email protected] @Date : 2022-07-27 15:23:24 @Brief : """ import cv2 import random import numpy as np from pybaseutils import time_utils @time_utils.performance("gaussian_noise") def gaussian_noise(image, mean=0.1, sigma=0.1): """ 添加高斯噪声 :param image:原图 :param mean:均值 :param sigma:标准差 值越大,噪声越多 :return:噪声处理后的图片 """ image = np.asarray(image / 255, dtype=np.float32) # 图片灰度标准化 noise = np.random.normal(mean, sigma, image.shape).astype(dtype=np.float32) # 产生高斯噪声 output = image + noise # 将噪声和图片叠加 output = np.clip(output, 0, 1) output = np.uint8(output * 255) return output @time_utils.performance("salt_pepper_noise") def salt_pepper_noise(image: np.ndarray, prob=0.01): """ 添加椒盐噪声,该方法需要遍历每个像素,十分缓慢 :param image: :param prob: 噪声比例 :return: """ for i in range(image.shape[0]): for j in range(image.shape[1]): if random.random() < prob: image[i][j] = 0 if random.random() < 0.5 else 255 else: image[i][j] = image[i][j] return image @time_utils.performance("fast_salt_pepper_noise") def fast_salt_pepper_noise(image: np.ndarray, prob=0.02): """ 随机生成一个0~1的mask,作为椒盐噪声 :param image:图像 :param prob: 椒盐噪声噪声比例 :return: """ image = add_uniform_noise(image, prob * 0.51, vaule=255) image = add_uniform_noise(image, prob * 0.5, vaule=0) return image def add_uniform_noise(image: np.ndarray, prob=0.05, vaule=255): """ 随机生成一个0~1的mask,作为椒盐噪声 :param image:图像 :param prob: 噪声比例 :param vaule: 噪声值 :return: """ h, w = image.shape[:2] noise = np.random.uniform(low=0.0, high=1.0, size=(h, w)).astype(dtype=np.float32) # 产生高斯噪声 mask = np.zeros(shape=(h, w), dtype=np.uint8) + vaule index = noise > prob mask = mask * (~index) output = image * index[:, :, np.newaxis] + mask[:, :, np.newaxis] output = np.clip(output, 0, 255) output = np.uint8(output) return output def cv_show_image(title, image, use_rgb=True, delay=0): """ 调用OpenCV显示RGB图片 :param title: 图像标题 :param image: 输入是否是RGB图像 :param use_rgb: True:输入image是RGB的图像, False:返输入image是BGR格式的图像 :return: """ img = image.copy() if img.shape[-1] == 3 and use_rgb: img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR) # 将BGR转为RGB # cv2.namedWindow(title, flags=cv2.WINDOW_AUTOSIZE) cv2.namedWindow(title, flags=cv2.WINDOW_NORMAL) cv2.imshow(title, img) cv2.waitKey(delay) return img if __name__ == "__main__": test_file = "test.png" image = cv2.imread(test_file) prob = 0.02 for i in range(10): out1 = gaussian_noise(image.copy()) out2 = salt_pepper_noise(image.copy(), prob=prob) out3 = fast_salt_pepper_noise(image.copy(), prob=prob) print("----" * 10) cv_show_image("image", image, use_rgb=False, delay=1) cv_show_image("gaussian_noise", out1, use_rgb=False, delay=1) cv_show_image("salt_pepper_noise", out2, use_rgb=False, delay=1) cv_show_image("fast_salt_pepper_noise", out3, use_rgb=False, delay=0)
循环机10次,salt_pepper_noise平均耗时125.49021ms,而fast_salt_pepper_noise平均耗时6.12011ms ,性能提高60倍左右,其生成的效果是基本一致的
call gaussian_noise elapsed: avg:19.42925ms total:194.29255ms count:10
call salt_pepper_noise elapsed: avg:125.49021ms total:1254.90212ms count:10
call fast_salt_pepper_noise elapsed: avg:6.12011ms total:61.20110ms count:10
原图
高斯噪声
salt_pepper_noise
fast_salt_pepper_noise
到此这篇关于Python实现图像随机添加椒盐噪声和高斯噪声的文章就介绍到这了,更多相关Python图像添加噪声内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!