文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

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

2024-04-02 19:55

关注

开门见山,直接使用 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 出来的是一片空白,或者有零星几个噪点。

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

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

int or float

在很多应用中,为了方便计算,都会将图像数据转换为浮点数,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 要大。

sqrtx

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

sigma

是否截断(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并不会自动对灰度图进行截断,例如:

clip

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

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

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

总结

完整的代码如下:

from skimage import io, img_as_float
import numpy as np

mean = 0
var = 0.01

image = io.imread("./lena.png")

image = img_as_float(image)
noise = np.random.normal(mean, var**0.5, image.shape)
noisy = image + noise
noisy = np.clip(noisy, 0.0, 1.0)

当然,上述问题在 skimage.util.random_noise 中都已解决,工程中可以直接使用。

import skimage

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

推荐学习skimage的源码。

参考

https://zhuanlan.zhihu.com/p/50820267

https://www.jb51.net/article/241120.htm

https://matplotlib.org/3.1.1/api/_as_gen/matplotlib.pyplot.imshow.html

https://github.com/scikit-image/scikit-image/blob/v0.17.2/skimage/util/noise.py#L8

到此这篇关于如何利用python正确地为图像添加高斯噪声的文章就介绍到这了,更多相关python为图像加高斯噪声内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯