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

How do I normalize the pixel value of an image to 0~1?

我的train_data的类型是'第16单元数组'。大小为 (96108,7,7)。因此,有96108张图片。

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

如果所有图片的最大值都是255,我可以'train data/255',但是我不能使用除法,因为我有的图片的最大值都不一样。 我想让所有图像的像素值都为 0 到 1。 我该怎么办?

您可以使用 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)
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:我看到了评论,我看到了不同之处。我将重写我的代码,使其“更干净”,具有更少的额外变量,但使用 min/max:

仍然正确
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

对比度归一化(或对比度拉伸)不应与 数据归一化 混淆,后者将数据映射到 0.0-1.0 之间。


数据规范化

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

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

要将8位图像转换为floating-point图像,当min()值达到0时,简单的数学运算是image/255.

img = img/255

NumPy 方法默认以 64 位 floating-point 输出数组。为了使用 NumPy 有效地测试应用于 8 位图像的方法,需要一个 8 位数组作为输入:

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

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

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

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

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

对比度归一化

方法 有效地进行了部分对比度归一化,这意味着它在可用强度范围内拉伸图像的强度。使用以下代码用 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())

对比度现在已拉伸,最小对比度为 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)

64 现在映射到 0 并且 174 映射到 255 以拉伸对比度。

混淆出现的地方

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