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

目录
  • 彩图or灰度图
  • uint8orfloat64
  • 方差or标准差
  • 是否截断(clip)
  • 总结
  • 参考

开门见山,直接使用 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之间的像素)。

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

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

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

叠加噪声之后,图片数据的最小值和最大值分别为 -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为图像加高斯噪声内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Python实现对图像添加高斯噪声或椒盐噪声

    目录 内容简介 加噪声的代码(高斯噪声,椒盐噪声) 在pytorch中如何使用 内容简介 展示如何给图像叠加不同等级的椒盐噪声和高斯噪声的代码,相应的叠加噪声的已编为对应的类,可实例化使用.以下主要展示自己编写的: 加噪声的代码(高斯噪声,椒盐噪声) add_noise.py #代码中的noisef为信号等级,例如我需要0.7的噪声,传入参数我传入的是1-0.7 from PIL import Image import numpy as np import random import torch

  • 使用Python-OpenCV向图片添加噪声的实现(高斯噪声、椒盐噪声)

    在matlab中,存在执行直接得函数来添加高斯噪声和椒盐噪声.Python-OpenCV中虽然不存在直接得函数,但是很容易使用相关的函数来实现. 代码: import numpy as np import random import cv2 def sp_noise(image,prob): ''' 添加椒盐噪声 prob:噪声比例 ''' output = np.zeros(image.shape,np.uint8) thres = 1 - prob for i in range(image.

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

    目录 彩图or灰度图 uint8orfloat64 方差or标准差 是否截断(clip) 总结 参考 开门见山,直接使用 skimage 库为图像添加高斯噪声是很简单的: import skimage origin = skimage.io.imread("./lena.png") noisy = skimage.util.random_noise(origin, mode='gaussian', var=0.01) 但是如果不用库函数而自己实现的话,有几个问题是值得注意的. 彩图 o

  • python使用opencv对图像添加噪声(高斯/椒盐/泊松/斑点)

    目录 1.高斯噪声 2.椒盐噪声 3.泊松噪声 4.speckle噪声 导读: 这篇文章主要介绍如何利用opencv来对图像添加各类噪声,原图: 1.高斯噪声 高斯噪声就是给图片添加一个服从高斯分布的噪声,可以通过调节高斯分布标准差(sigma)的大小来控制添加噪声程度,sigma越大添加的噪声越多图片损坏的越厉害 #读取图片 img = cv2.imread("demo.png") #设置高斯分布的均值和方差 mean = 0 #设置高斯分布的标准差 sigma = 25 #根据均值

  • 利用python实现.dcm格式图像转为.jpg格式

    如下所示: import pydicom import matplotlib.pyplot as plt import scipy.misc import pandas as pd import numpy as np import os def Dcm2jpg(file_path): #获取所有图片名称 c = [] names = os.listdir(file_path) #路径 #将文件夹中的文件名称与后边的 .dcm分开 for name in names: index = name.

  • Python+Matplotlib实现给图像添加文本标签与注释

    目录 1.添加文本标签 plt.text() 2. 添加注释 plt.annotate() 1.添加文本标签 plt.text() 用于在绘图过程中,在图像上指定坐标的位置添加文本.需要用到的是plt.text()方法.  其主要的参数有三个: plt.text(x, y, s) 其中x,y表示传入点的x和y轴坐标.s表示字符串. 需要注意的是,这里的坐标,如果设定有xticks.yticks标签,则指的不是标签,而是绘图时x.轴的原始值. 因为参数过多,不再一一解释,根据代码学习其用法. ha

  • 利用python3如何给数据添加高斯噪声

    目录 Background 原始数据 源码 总结 Background 高斯噪声,顾名思义是指服从高斯分布(正态分布)的一类噪声.有的时候我们需要向标准数据中加入合适的高斯噪声让数据更加符合实际. python中的random库中集成了高斯正态分布,可以直接使用. 我们可以通过调整高斯噪声均值和方差,获取不同效果的处理数据. 原始数据 高斯噪声sigma = 0.05 高斯噪声sigma = 0.1 高斯噪声sigma = 0.15 源码 import random import numpy a

  • C++实现点云添加高斯噪声功能

    0 添加高斯噪声后的点云 红色为添加的高斯噪声点,白色为原始点 1 什么是高斯噪声 高斯噪声是指它的概率密度函数服从高斯分布(即正态分布)的一类噪声.(百度百科) 高斯分布,也称正态分布,又称常态分布,记为 N ( μ , σ 2 ) ),其中 μ , σ 2 为分布的参数,分别为高斯分布的期望和方差,其中 σ > 0 ,称为标准差.当 μ , σ 有确定值时,p ( x ) 也就确定了,特别当 μ = 0 , σ 2 = 1时,x 的分布为标准正态分布. 高斯分布函数 2 怎样添加高斯噪声 磨

  • Python实现对图像加噪(高斯噪声 椒盐噪声)

    目录 内容简介 加噪声的代码(高斯噪声,椒盐噪声) 在pytorch中如何使用 补充 内容简介 展示如何给图像叠加不同等级的椒盐噪声和高斯噪声的代码,相应的叠加噪声的已编为对应的类,可实例化使用.以下主要展示自己编写的: 加噪声的代码(高斯噪声,椒盐噪声) add_noise.py #代码中的noisef为信号等级,例如我需要0.7的噪声,传入参数我传入的是1-0.7 from PIL import Image import numpy as np import random import to

  • Python实现图像随机添加椒盐噪声和高斯噪声

    目录 1.常见的图像噪声 (1)高斯噪声 (2) 椒盐噪声 2.生成图像噪声 (1)高斯噪声 (2) 椒盐噪声(速度慢) (3) 椒盐噪声(快速版) 3. Demo性能测试 图像噪声是指存在于图像数据中的不必要的或多余的干扰信息.在噪声的概念中,通常采用信噪比(Signal-Noise Rate, SNR)衡量图像噪声.通俗的讲就是信号占多少,噪声占多少,SNR越小,噪声占比越大. 1.常见的图像噪声 (1)高斯噪声 高斯噪声Gaussian noise,是指它的概率密度函数服从高斯分布(即正态

随机推荐