将float64类型的np.array转换为uint8类型的缩放值



我有一个特定的np.array数据,它表示一个特定灰度图像。我需要使用SimpleBlobDetector(),不幸的是它只接受8位图像,所以我需要转换这个图像,显然会有质量损失。

我已经试过了:

import numpy as np
import cv2
[...]
data = data / data.max() #normalizes data in range 0 - 255
data = 255 * data
img = data.astype(np.uint8)
cv2.imshow("Window", img)

但是cv2.imshow并没有给出预期的图像,而是有奇怪的失真。。。

最后,我只需要将np.float64转换为np.uint8即可缩放所有值并截断其余值,例如65535变为255,65534变为254,依此类推……有什么帮助吗?

谢谢。

规范化图像的更好方法是取每个值并除以数据类型所经历的最大值。这样可以确保图像中动态范围较小的图像保持较小,并且它们不会因疏忽而归一化,从而变灰。例如,如果您的图像的动态范围为[0-2],那么现在的代码会将其缩放为强度为[0, 128, 255]。您希望这些在转换为np.uint8后保持较小。

因此,将每个值除以图像类型可能的最大值,而不是实际图像本身。然后将其缩放255以生成标准化结果。使用numpy.iinfo并为其提供图像的类型(dtype),您将获得该类型的信息结构。然后,您将从此结构中访问max字段,以确定最大值。

因此,使用以上内容,对您的代码进行以下修改:

import numpy as np
import cv2
[...]
info = np.iinfo(data.dtype) # Get the information of the incoming image type
data = data.astype(np.float64) / info.max # normalize the data to 0 - 1
data = 255 * data # Now scale by 255
img = data.astype(np.uint8)
cv2.imshow("Window", img)

请注意,我还将图像转换为np.float64,以防传入的数据类型不是这样,并在进行除法时保持浮点精度。

考虑到您正在使用OpenCV,在数据类型之间转换的最佳方式是使用normalize函数。

img_n = cv2.normalize(src=img, dst=None, alpha=0, beta=255, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_8U)

然而,如果你不想使用OpenCV,你可以在numpy 中这样做

def convert(img, target_type_min, target_type_max, target_type):
imin = img.min()
imax = img.max()
a = (target_type_max - target_type_min) / (imax - imin)
b = target_type_max - a * imax
new_img = (a * img + b).astype(target_type)
return new_img

然后像这个一样使用

imgu8 = convert(img16u, 0, 255, np.uint8)

这是基于我在这个解决方案下的交叉验证板上的评论中找到的答案https://stats.stackexchange.com/a/70808/277040

您可以使用skimage.img_as_ubyte(yourdata),它将使您的数组范围从0到>255

from skimage import img_as_ubyte
img = img_as_ubyte(data)
cv2.imshow("Window", img)

相关内容

最新更新