Bizzare matplotlib在显示投射为浮点的图像中的行为 [英] Bizzare matplotlib behaviour in displaying images cast as floats

查看:46
本文介绍了Bizzare matplotlib在显示投射为浮点的图像中的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当范围 (0,255) 内的常规 RGB 图像被转换为​​浮点数,然后由 matplotlib 显示时,图像显示为负数.如果将其强制转换为uint8,则显示正确(当然).它给我造成了一些麻烦,无法弄清楚发生了什么,因为我不小心将其中一个图像投射为浮动.

When a regular RGB image in range (0,255) is cast as float, then displayed by matplotlib, the image is displayed as negative. If it is cast as uint8, it displays correctly (of course). It caused me some trouble to figure out what was going on, because I accidentally cast one of images as float.

我很清楚,当转换为浮点数时,图像预计在 (0,1) 范围内,果然,当除以 255 时,显示的图像是正确的.但是,为什么将(0,255)范围内的图像转换为float时显示为负数?我会期望饱和度(全白)还是从输入中自动推断出范围(从而正确显示)?如果发生了这些预期的事情中的任何一个,我将能够更快地调试我的代码.我已经包含了重现行为所需的代码.有没有人知道为什么会发生这种情况?

I am well aware that when cast as float, the image is expected to be in range (0,1), and sure enough, when divided by 255 the image displayed is correct. But, why would an image in range (0,255) that is cast as float displayed as negative? I would have expected either saturation (all white) or automatically inferred the range from the input (and thus correctly displayed)? If either of those expected things happened, I would have been able to debug my code quicker. I have included the required code to reproduce the behaviour. Does anyone have insight on why this happens?

    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):

In the sources, in image.py, in the AxesImage class (what imshow returns) a method _get_unsampled_image is called at some point in the drawing process. The relevant code starts on line 226 for me (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 的类型和大小:

So the type and size of the input A get checked:

if A.dtype == np.uint8 and A.ndim == 3:

在这种情况下,没有预处理.否则,如果不检查输入的范围,您最终会乘以 255 并转换为 uint8:

in which case there is no preprocessing. Otherwise, without checking the range of the input, you ultimately have a multiplication by 255 and a cast to uint8:

x = (x * 255).astype(np.uint8)

而且我们知道如果 x 是从 0 到 255 而不是 0 到 1 会发生什么:

And we know what to expect if x is from 0 to 255 instead of 0 to 1:

In [1]: np.uint8(np.array([1,2,128,254,255])*255)
Out[1]: array([255, 254, 128,   2,   1], dtype=uint8)

所以光变暗了.像我想像的那样,这会使图像反转可能不是计划的行为.

So light becomes dark. That this inverts the image is probably not a planned behavior as I think you assume.

您可以针对每个输入案例,比较从 imshow 返回的对象中的 _rgbacache 的值,以观察结果,例如im._rbacache 其中 im = plt.imshow(np.float64(img)).

You can compare the values of _rgbacache in the object returned from imshow for each of your input cases to observe the result, e.g. im._rbacache where im = plt.imshow(np.float64(img)).

这篇关于Bizzare matplotlib在显示投射为浮点的图像中的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆