当范围(0,255)中的常规RGB图像被转换为浮点数,然后由matplotlib显示时,图像显示为负数.如果它被转换为uint8,它会正确显示(当然).找出发生的事情让我有些麻烦,因为我意外地将其中一张图像投射为浮动图像.
我很清楚,当转换为float时,图像应该在范围(0,1)内,当然,当除以255时,显示的图像是正确的.但是,为什么投射为浮点数的范围(0,255)中的图像显示为负数?我原本期望饱和度(全白)或自动推断输入范围(从而正确显示)?如果发生了其中任何一个预期的事情,我就能更快地调试我的代码.我已经包含了重现行为所需的代码.有没有人知道为什么会这样?
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
Run Code Online (Sandbox Code Playgroud)
在源代码中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
Run Code Online (Sandbox Code Playgroud)
这样A
就检查了输入的类型和大小:
if A.dtype == np.uint8 and A.ndim == 3:
Run Code Online (Sandbox Code Playgroud)
在这种情况下,没有预处理。否则,在不检查输入范围的情况下,您最终将乘以255,并将其强制转换为uint8
:
x = (x * 255).astype(np.uint8)
Run Code Online (Sandbox Code Playgroud)
而且我们知道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)
Run Code Online (Sandbox Code Playgroud)
所以光变暗了。我认为您认为,这会使图像反转,这可能不是计划的行为。
您可以比较每个输入用例从中_rgbacache
返回的对象中的值,imshow
以观察结果,例如im._rbacache
where im = plt.imshow(np.float64(img))
。