numpy 如何将图像的像素值归一化为0~1?

x3naxklr  于 2022-12-13  发布在  其他
关注(0)|答案(3)|浏览(779)

我的train_data的类型是“单元数组16”。大小是**(96108,7,7)**。因此,有96108个图像。
这个图像和一般的图像不一样,我的图像是7 x7的传感器,49个像素包含了检测到的光的数量,一个图像是0到1秒检测到的光的数量,由于传感器在单位时间内是随机检测的,所以像素的最大值都不一样。
如果所有图像的最大值都是255,我可以做'train data/255',但我不能使用除法,因为我拥有的图像的最大值都是不同的。我想让所有图像的像素值都是0到1。我该怎么做?

mklgxw1f

mklgxw1f1#

对比度归一化(或对比度拉伸)不应与Map0.0-1.0之间数据的数据归一化混淆。

数据规范化

我们使用下面的公式来规范化数据。min()max() 值是数据类型中可能支持的最小值和最大值。

当我们将其用于图像时,x 是整个图像,i 是该图像的单个像素。如果您使用的是8位图像,则 min()max() 值将分别变为0和255。这不应与所讨论图像中的最小值和最大值混淆。
要将8位图像转换为浮点图像,当min()值达到0时,简单的数学运算是 image/255。

img = img/255

NumPy方法喜欢默认输出64位浮点数组。为了有效地测试应用于NumPy的8位图像的方法,需要一个8位数组作为输入:

image = np.random.randint(0,255, (7,7),  dtype=np.uint8)
normalized_image = image/255

当我们检查以上两行的输出时,我们可以看到图像的最大值是252,它现在Map到64位标准化图像上的0.9882352941176471。

然而,在大多数情况下,您不需要64位图像。您可以使用以下代码将其输出(换句话说,转换)为32位(或16位)。如果您尝试将其转换为8位,则会引发错误。使用'/'进行除法是 np.true_divide 的简写,但缺乏定义输出数据格式的能力。

normalized_image_2 = np.true_divide(image, 255, dtype=np.float32)

新数组的属性如下所示。您可以看到位数现在减少了,252现在被重新Map为0.9882353。

对比度标准化

方法shown by @3dSpatialUser有效地进行了部分对比度归一化,这意味着它在可用的强度范围内拉伸图像的强度。

c_image = np.random.randint(64,128, (7,7),  dtype=np.uint8)
cn_image = (c_image - c_image.min()) / (c_image.max()- c_image.min())

对比度现在已拉伸,将最小对比度64Map到0.0,将最大对比度127Map到1.0。

对比度标准化的公式如下所示。
x1c4d 1x指令集
使用上面的公式和NumPy并在对比度标准化后将数据重新Map回8位输入格式,图像应乘以255,然后将数据类型更改回unit 8:

cn_image_correct = (c_image - c_image.min()) / (c_image.max()- c_image.min()) * 255
cn_image_correct = cn_image_correct.astype(np.int8)

64现在Map到0,174Map到255,拉伸对比度。

哪里出现了混乱

在大多数应用中,图像的强度值分布在其最小值和最大值附近,因此当我们使用图像中呈现的最小值和最大值而不是可用范围的最小值和最大值来应用归一化公式时,将输出更好看的图像(在大多数情况下)在0.0-1.0范围内,这有效地同时使数据和对比度归一化。图像编辑软件在图像数据类型8/16/32位之间切换时进行伽马校正或重新Map。

kse8i1jr

kse8i1jr2#

import numpy as np

data = np.random.normal(loc=0, scale=1, size=(96108, 7, 7))
data_min = np.min(data, axis=(1,2), keepdims=True)
data_max = np.max(data, axis=(1,2), keepdims=True)

scaled_data = (data - data_min) / (data_max - data_min)

编辑:我已经投票支持另一个答案,因为那是一个更干净的方式(在我看来),但原则是一样的。
EDIT v2:我看到了注解,我看到了不同之处。我将重写我的代码,这样它就“更干净”,减少了额外的变量,但仍然使用最小/最大正确:

data -= data.min(axis=(1,2), keepdims=True)
data /= data.max(axis=(1,2), keepdims=True)

首先将最小值移到零,此后可以取最大值以得到特定图像的全范围(max-min)。
经过这一步np.array_equal(data, scaled_data) = True

31moq8wy

31moq8wy3#

您可以使用np.ndarray.max跨多个轴收集最大值:这里是axis=1axis=2(即分别在每一张图像上)。然后用它规范化初始数组。为了避免自己广播这个最大值数组,可以使用keepdims选项:

>>> x = np.random.rand(96108,7,7)

>>> x.max(axis=(1,2), keepdims=True).shape
(96108, 1, 1)

x.max(axis=(1,2))单独返回的数组形状为(96108,) ...
这样,您就可以执行以下操作:

>>> x /= x.max(axis=(1,2), keepdims=True)

相关问题