如何利用python正确地为图像添加高斯噪声

作者:howlclat 时间:2023-08-03 08:26:22 

开门见山,直接使用 skimage 库为图像添加高斯噪声是很简单的:

import skimage

origin = skimage.io.imread("./lena.png")
noisy = skimage.util.random_noise(origin, mode='gaussian', var=0.01)

但是如果不用库函数而自己实现的话,有几个问题是值得注意的。

彩图 or 灰度图

读取图片时,图片可能是有三通道的RGB图片,也有可能是单通道的灰度图,甚至四通道的RGBA图。

通道数不同会影响图像数据的 shape ,例如: (256, 256, 3) 、(256, 256)

很多人按照MATLAB的习惯,使用 np.random.randn 来生成高斯噪声,则需要根据通道数调整参数。

# RGB
noise = sigma * np.random.randn(256, 256, 3)
# GRAY
noise = sigma * np.random.randn(256, 256)

为了通用的处理,最好使用 np.random.normal 生成高斯噪声。

noise = np.random.normal(mean, var ** 0.5, image.shape)

前两个参数分别为 均值和标准差,第三个参数为生成数据的 shape,直接将图像本身shape输入进去,更加优雅。

uint8 or float64

一般遇到的图像都是8bit的,用skimage或opencv读取后会发现数据类型是uint8的ndarray,取值范围是 [0, 255] 。

如果手贱直接在整型数据上添加高斯噪声,如:

image = io.imread("lena.png")
noise = np.random.normal(0, 10, image.shape)
noisy = image + noise

你会发现 plt.imshow 出来的是一片空白,或者有零星几个噪点。

以一个像素为例分析原因:

  • 图像本身是[0, 255]的整数:[226 137 125]

  • 生成的噪声是浮点数:[-2.92864248 4.04786763 12.23436435]

  • 相加后最后的数据:[223.07135752 141.04786763 137.23436435]

matplotlib 的 imshow 要求输入是 (0-1 float or 0-255 int),所以上述不伦不类的数据是无法正确显示的(只显示了恰好落在0-1之间的像素)。

如何利用python正确地为图像添加高斯噪声

在很多应用中,为了方便计算,都会将图像数据转换为浮点数,float64,取值范围为 [0, 1]

为了转换数据类型,最简单的方式是直接除以255:

image = io.imread("./lena.png")
print(image.dtype)# uint8

image = image/255
print(image.dtype)# float64

更稳妥的做法,可以使用skimage的img_to_float()

image = img_as_float(image)

这样再添加高斯噪声就可以正确显示。

方差 or 标准差

高斯噪声符合一个均值为0,方差为 σ 2 \sigma^2 σ2 的高斯分布。

均值为0,是保证图像的亮度不会有变化,而方差大小则决定了高斯噪声的强度。

方差/标准差越大,噪声越强。

这里有一点点初中数学的细节,就是在[0, 1]区间内, y = x y=\sqrt{x} y=x  比 y = x y=x y=x 要大。

如何利用python正确地为图像添加高斯噪声

所以,设置方差为0.1,噪声要比设置标准差为0.1大不少。注意不要用混了就可以。

如何利用python正确地为图像添加高斯噪声

是否截断(clip)

由于需要把噪声叠加到原图像中,因此叠加后的数据值就可能超出对应数据类型的取值范围

如果用matplotlib显示超出范围的彩色图像,则可能遇到以下提示:

Clipping input data to the valid range for imshow with RGB data ([0..1] for floats or [0..255] for integers).

matplotlib自动将图片做了截断。

而不知为何,matplotlib并不会自动对灰度图进行截断,例如:

如何利用python正确地为图像添加高斯噪声

叠加噪声之后,图片数据的最小值和最大值分别为 -0.32 和 1.25,这明显超过了[0, 1]的范围。

这样显示出的图片是不正确的(中间图像),更像是重新将图像缩放到了[0, 1]范围内,就像将色阶向外扩了一样,对比度也下降了。

使用 np.clip,将图像截断到 [0, 1]之间,如右图所示,图像明显正常了很多。

来源:https://blog.csdn.net/howlclat/article/details/107216722

标签:python,图像,高斯噪声
0
投稿

猜你喜欢

  • 再读《你是一个职业的页面重构工作者吗?》

    2009-02-11 12:22:00
  • js的正则test,match,exec详细解析

    2024-05-02 17:30:20
  • django的ORM模型的实现原理

    2022-08-26 00:57:33
  • 设计模式-自动完成

    2010-11-30 21:44:00
  • mysql部分替换sql语句分享

    2024-01-23 18:17:35
  • 在Python中编写数据库模块的教程

    2024-01-22 21:28:40
  • python3+openCV 获取图片中文本区域的最小外接矩形实例

    2022-03-16 00:57:11
  • 解决pygal.style的LightColorizedStyle参数问题

    2023-09-20 06:39:02
  • Mysql 如何查询时间段交集

    2024-01-22 09:27:32
  • Python命令行参数解析模块optparse使用实例

    2023-11-04 08:09:08
  • 一些文档中没有介绍的SQL Server DBCC命令

    2008-12-09 14:24:00
  • Linux系统下mysqlcheck修复数据库命令(详解)

    2024-01-24 14:42:10
  • 很酷的JQuery Solar System

    2007-12-15 08:09:00
  • Windows下Anaconda的安装和简单使用方法

    2022-04-21 16:46:50
  • 详解vue-cli 脚手架 安装

    2024-05-09 10:40:06
  • Python利器openpyxl之操作excel表格

    2022-11-16 18:46:58
  • MySQL约束与索引概念详解

    2024-01-28 17:06:39
  • python正则过滤字母、中文、数字及特殊字符方法详解

    2022-02-20 10:14:47
  • JSP安全开发之XSS漏洞详解

    2023-06-13 13:07:24
  • python opencv捕获摄像头并显示内容的实现

    2021-12-08 23:16:24
  • asp之家 网络编程 m.aspxhome.com