当范围 (0,255) 中的常规 RGB 图像被转换为 float ,然后由 matplotlib 显示时,图像显示为负片。如果它被转换为 uint8,它会正确显示(当然)。这让我很难弄清楚发生了什么,因为我不小心将其中一张图像转换为 float 。
我很清楚,当转换为 float 时,图像预计在范围 (0,1) 内,果然,当除以 255 时,显示的图像是正确的。但是,为什么在范围 (0,255) 中转换为 float 的图像会显示为负数?我会期望饱和度(全白)或自动从输入推断范围(并因此正确显示)?如果这些预期的事情中的任何一个发生了,我就能够更快地调试我的代码。我已经包含了重现该行为所需的代码。有谁知道为什么会发生这种情况?
import numpy as np
import matplotlib.pyplot as plt
a = np.random.randint(0,127,(200,400,3))
b = np.random.randint(128,255,(200,400,3))
img=np.concatenate((a,b)) # Top should be dark ; Bottom should be light
plt.imshow(img) # Inverted
plt.figure()
plt.imshow(np.float64(img)) # Still Bad. Added to address sascha's comment
plt.figure()
plt.imshow(255-img) # Displayed Correctly
plt.figure()
plt.imshow(np.uint8(img)) # Displayed Correctly
plt.figure()
plt.imshow(img/255.0) # Displays correctly
最佳答案
在源代码中,在 image.py
中,在 AxesImage
类(imshow
返回的)方法 _get_unsampled_image
在绘图过程中的某个时刻被调用。相关代码对我来说是从第 226 行开始的(matplotlib-1.5.3):
if A.dtype == np.uint8 and A.ndim == 3:
im = _image.frombyte(A[yslice, xslice, :], 0)
im.is_grayscale = False
else:
if self._rgbacache is None:
x = self.to_rgba(A, bytes=False)
# Avoid side effects: to_rgba can return its argument
# unchanged.
if np.may_share_memory(x, A):
x = x.copy()
# premultiply the colors
x[..., 0:3] *= x[..., 3:4]
x = (x * 255).astype(np.uint8)
self._rgbacache = x
因此检查输入 A
的类型和大小:
if A.dtype == np.uint8 and A.ndim == 3:
在这种情况下没有预处理。否则,如果不检查输入范围,您最终会乘以 255 并转换为 uint8
:
x = (x * 255).astype(np.uint8)
而且我们知道如果 x
是从 0 到 255 而不是 0 到 1 会发生什么:
In [1]: np.uint8(np.array([1,2,128,254,255])*255)
Out[1]: array([255, 254, 128, 2, 1], dtype=uint8)
所以光变暗了。这反转图像可能不是我认为你假设的计划行为。
您可以比较每个输入案例从 imshow
返回的对象中 _rgbacache
的值,以观察结果,例如im._rbacache
其中 im = plt.imshow(np.float64(img))
。
关于python - 在显示转换为 float 的图像时出现奇怪的 matplotlib 行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39925420/