【问题标题】:Why can't I assign uint16 array to array vector in Python?为什么我不能在 Python 中将 uint16 数组分配给数组向量?
【发布时间】:2017-10-07 20:47:55
【问题描述】:

我运行以下代码:

    colored = np.empty((299, 299, 3), dtype=float) # dtype=`uint16` doesn't work too!
    colored[:, :, 0] = image
    colored[:, :, 1] = image
    colored[:, :, 2] = image

如果我绘制image(uint16 的二维数组),我可以看到正确的图片。但是,如果我绘制 colored 数组,则会得到以下垃圾图像:

我使用以下代码进行绘图:

    import matplotlib.pyplot as plt
    plt.imshow(colored, cmap='gray')
    plt.show()

当我绘制image 时,它可以工作。当我绘制colored 时,它没有。这是怎么回事,我该如何解决?

【问题讨论】:

  • 你使用什么绘图命令?数字看起来对吗?
  • 我使用plt.imshow(colored, cmap='gray')。数字看起来正确!所以,绘图功能出了点问题……
  • 但我正在尝试绘制colored,它应该是float 的数组。当我以同样的方式绘制image(uint16 的数组)时,它可以工作!
  • imshow(colored[:,:,0]) 怎么样?创建 3d 数组时,您是否对值进行了标准化。 imshow 表示值应在 0.0 到 1.0 范围内。
  • 2D 数组和 0.0-1.0 值的 3D 数组都可以正常工作。但我认为imshow 可以与值为 0..255 的 3 色图像一起使用...

标签: python arrays numpy floating-point type-conversion


【解决方案1】:

当传递给 imshow 的数组是 3 维的并且具有浮点 dtype 时, plt.show() 致电this piece of code:

if x.ndim == 3:
    ...    
    if xx.dtype.kind == 'f':
        if bytes:
            xx = (xx * 255).astype(np.uint8)
    return xx

所以colored 中的值乘以 255,然后将astyped 乘以np.uint8。 这发生在之前值被标准化为区间[0, 1]。您可以通过在 matplotlib/cm.py 文件中添加打印语句来验证这一点:

if x.ndim == 3:
    ...    
    if xx.dtype.kind == 'f':
        if bytes:
            print(xx.max())
            xx = (xx * 255).astype(np.uint8)
    return xx

并运行此脚本:

import numpy as np
import matplotlib.pyplot as plt

maxval = np.iinfo('uint16').max
uint16_image = np.linspace(0, maxval, (16**2)).astype('uint16')
uint16_image = uint16_image.reshape(16, 16)

colored = np.empty(uint16_image.shape + (3,), dtype=float)
colored[:, :, 0] = uint16_image
colored[:, :, 1] = uint16_image
colored[:, :, 2] = uint16_image

fig, ax = plt.subplots(nrows=2)
ax[0].imshow(uint16_image)
ax[1].imshow(colored)
plt.show()

打印出来的

65535.0
65535.0

并显示

故事的寓意是,如果您将 3D 浮点数组传递给 plt.imshow,则值必须介于 0 和 1(或 NaN)之间,否则您可能会得到(图形) mojibake。

【讨论】:

  • 使用上面的示例,除了左上角的黑色方块之外,什么会导致第二个绘图渐变为blank?
  • 行为上的差异是this change对matplotlib源码造成的。 (见pull 10220)。此时代码中self._A 的dtype 为float64,因此high 设置为1。self._A = np.clip(self._A, 0, high) 现在将所有内容剪辑为0 或1。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-14
相关资源
最近更新 更多