如何将图像的像素值标准化为0~1?

김수환*_*김수환 3 python numpy image normalization

我的train_data的类型是“单元 16 的数组”。大小为(96108,7,7)。因此,共有 96108 张图像。

该图像与一般图像不同。我的图像有一个 7x7 的传感器,49 个像素包含检测到的光的数量。而一张图像就是0到1秒检测到的光的数量。由于传感器在单位时间内随机检测,因此像素的最大值都不同。

如果所有图像的最大值是 255,我可以执行“训练数据/255”,但我无法使用除法,因为我拥有的图像的最大值都不同。我想让所有图像的像素值都为0到1,该怎么办?

Kav*_*era 9

对比度标准化(或对比度拉伸)不应与将数据映射到 0.0-1.0 之间的数据标准化相混淆。


数据标准化

我们使用以下公式对数据进行标准化。min ()max()值是数据类型内支持的可能的最小值和最大值。

在此输入图像描述

当我们将它用于图像时,x是整个图像,i是该图像的单个像素。如果您使用 8 位图像,则min()max()值分别变为 0 和 255。不应将其与相关图像中显示的最小值和最大值混淆。

要将 8 位图像转换为浮点图像,当 min() 值达到 0 时,简单的数学计算是image/255。

img = img/255
Run Code Online (Sandbox Code Playgroud)

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

image = np.random.randint(0,255, (7,7),  dtype=np.uint8)
normalized_image = image/255
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

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

normalized_image_2 = np.true_divide(image, 255, dtype=np.float32)
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

对比度标准化

@3dSpatialUser 所示的方法有效地进行了部分对比度归一化,这意味着它在可用强度范围内拉伸图像的强度。使用以下代码使用 8 位数组进行测试。

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())
Run Code Online (Sandbox Code Playgroud)

对比度现已拉伸,最小对比度 64 映射到 0.0,最大对比度 127 映射到 1.0。

在此输入图像描述

对比度归一化的公式如下所示。

在此输入图像描述

将上述公式与 NumPy 结合使用,并在对比度归一化后将数据重新映射回 8 位输入格式,图像应乘以 255,然后将数据类型更改回 unit8:

cn_image_correct = (c_image - c_image.min()) / (c_image.max()- c_image.min()) * 255
cn_image_correct = cn_image_correct.astype(np.int8)
Run Code Online (Sandbox Code Playgroud)

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

在此输入图像描述

出现混乱的地方

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