Bizzare matplotlib在显示投射为浮动的图像时的行为

Pro*_*ies 8 python matplotlib

当范围(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)

tsj*_*tsj 6

在源代码中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._rbacachewhere im = plt.imshow(np.float64(img))