如何创建uint16高斯噪声图像?

时间:2019-02-08 19:27:40

标签: python numpy

我想创建具有定义的均值和标准偏差的高斯噪声的 uint16 图像。

我尝试为此使用numpy的random.normal,但它返回的是float64数组:

mu = 10
sigma = 100
shape = (1024,1024)
gauss_img = np.random.normal(mu, sigma, shape)

print(gauss_img.dtype)

>>> dtype('float64')

是否有一种方法可以将gauss_img转换为uint16数组,同时保留原始均值和标准差?还是有另一种完全创建uint16噪声图像的方法?

编辑:如评论中所述,np.random.normal在给定sd>均值的情况下将不可避免地对负值进行采样,这对于转换为uint16是一个问题。

所以我认为我需要一种可以直接创建 unsigned 高斯图像的方法。

3 个答案:

答案 0 :(得分:1)

因此,我认为这与您要查找的内容很接近。

导入库并欺骗一些偏斜的数据。在这里,由于输入来源不明,因此我使用np.expm1(np.random.normal())创建了偏斜数据。您也可以使用skewnorm().rvs(),但这是一种作弊,因为这也是您用来表征它的库。

我将原始样本弄平,以使绘制直方图更加容易。

import numpy as np
from scipy.stats import skewnorm

# generate dummy raw starting data
# smaller shape just for simplicity
shape = (100, 100)
raw_skewed = np.maximum(0.0, np.expm1(np.random.normal(2, 0.75, shape))).astype('uint16')

# flatten to look at histograms and compare distributions
raw_skewed = raw_skewed.reshape((-1))

现在找到代表偏斜数据特​​征的参数,并使用这些参数创建一个新的分布以从希望与原始数据很好地匹配的样本中进行采样。

这两行代码正是我想得到的。

# find params
a, loc, scale = skewnorm.fit(raw_skewed)

# mimick orig distribution with skewnorm
new_samples = skewnorm(a, loc, scale).rvs(10000).astype('uint16')

现在绘制每个要比较的分布。

plt.hist(raw_skewed, bins=np.linspace(0, 60, 30), hatch='\\', label='raw skewed')
plt.hist(new_samples, bins=np.linspace(0, 60, 30), alpha=0.65, color='green', label='mimic skewed dist')
plt.legend()

enter image description here

直方图非常接近。如果看起来足够好,请将新数据重塑为所需的形状。

# final result
new_samples.reshape(shape)

现在...这是我认为可能不足的地方。看一下每个的热图。原始分布在右侧的尾巴更长(skewnorm()所没有的异常值)。

这将绘制每个图的热图。

# plot heatmaps of each
fig = plt.figure(2, figsize=(18,9))
ax1 = fig.add_subplot(1, 2, 1)
ax2 = fig.add_subplot(1, 2, 2)

im1 = ax1.imshow(raw_skewed.reshape(shape), vmin=0, vmax=120)
ax1.set_title("raw data - mean: {:3.2f}, std dev: {:3.2f}".format(np.mean(raw_skewed), np.std(raw_skewed)), fontsize=20)

im2 = ax2.imshow(new_samples.reshape(shape), vmin=0, vmax=120)
ax2.set_title("mimicked data - mean: {:3.2f}, std dev: {:3.2f}".format(np.mean(new_samples), np.std(new_samples)), fontsize=20)

plt.tight_layout()

# add colorbar
fig.subplots_adjust(right=0.85)
cbar_ax = fig.add_axes([0.88, 0.1, 0.08, 0.8])  # [left, bottom, width, height]
fig.colorbar(im1, cax=cbar_ax)

看一下它...您会看到黄色的偶发斑点,表明原始分布中的值很高,而没有进入输出。这也显示在输入数据的较高std dev中(请参阅每个热图中的标题,但同样,如对原始问题的评论一样……Mean&std不能真正表征分布,因为它们是不正常的。 。,但它们只是作为相对比较)。

但是...这只是我创建的非常具体的倾斜示例所面临的问题。希望这里有足够的东西可以解决和调整,直到它适合您的需求和您的特定数据集。祝你好运!

enter image description here

答案 1 :(得分:0)

使用该平均值和西格玛,您势必会采样一些负值。因此,我猜选项可能是您在采样后找到了最大的负值,并将其绝对值添加到所有样本中。之后,按照注释中的建议转换为uint。但是,当然,您可以通过这种方式降低均值。

答案 2 :(得分:0)

如果您要提取一系列uint16数字,则应检出this post

通过这种方式,您可以使用scipy.stats.truncnorm生成无符号整数的高斯。