【问题标题】:Equal arrays but not the same visually数组相等但视觉上不一样
【发布时间】:2016-09-20 11:35:34
【问题描述】:

我有一个 32x32x3 的图像,例如 keras 中的 cifar10 图像之一。 现在,假设我想做一些操作。首先,为了确保我做的事情是正确的,我试图复制图像(那不是我想做的,所以请不要告诉我如何在不做三个循环的情况下复制图像,我需要三个循环来操作一些值)。

from keras.datasets import cifar10
import matplotlib.pyplot as plt

(X_train, Y_train), (X_test, Y_test) = cifar10.load_data()
im = numpy.reshape(X_train[0], (3, 32, 32))
im = im.transpose(1,2,0)
imC = numpy.zeros((32,32,3))

for k in range(3):
  for row in range(0,32):
    for col in range(0,32):
      imC[row][col][k] = im[row][col][k]

现在,如果我测试它们是否相同,它们实际上是,我看到打印出来的“酷”

if (im==imC).all():
  print "cool"

但是当我尝试将它们可视化时,它们是不同的:

plt.imshow( imC )
plt.show()

plt.imshow( im )
plt.show()

发生了什么事?

【问题讨论】:

  • 它们有何不同?也许你可以将情节添加到这个问题中
  • 这两个数组的元素类型是什么? (im.dtype, imC.dtype)
  • @Gareth,我认为你的想法是正确的,我得到 (im.dtype, imC.dtype) = (uint8, float64)
  • 我认为imshow 期望浮点 m×n×3 数组中的 RGB 值归一化为 0..1 范围。如果你这样做 plt.imshow(imC/255) 会发生什么?
  • 重点是imshow 显式查看你给它的数组的元素类型,并为uint8float64 做不同的事情。

标签: python numpy matplotlib keras


【解决方案1】:

Python CIFAR10 数据集中的图像具有numpy.uint8 类型的像素值。 (大概它们是从 PNG 文件或类似文件中读取的。)所以 X_train.dtype == numpy.uint8 和因此 im.dtype == numpy.uint8

您创建的数组的默认元素类型为numpy.float64。换句话说,imC.dtype == numpy.uint8

matplotlib.pyplot.imshow 会根据其元素类型对其输入进行不同的处理。特别是,如果你给它一个元素类型为 uint8m-by-n-by-3 数组,则 0 表示最暗,255 表示最亮如您所料,对于三个颜色通道中的每一个;如果你给它一个元素类型为float64m-by-n-by-3数组,它希望所有值都在0范围内(最暗)到 1(最亮),并且文档没有说明超出该范围的值会发生什么。

我将冒险猜测超出该范围的值会发生什么:我认为代码可能会执行以下操作:乘以 255,舍入为整数,视为uint8。这意味着 0 变为 0,1 变为 255。

但是,如果最后一步意味着除了低 8 位之外的所有位都被丢弃,这也意味着 2 变为 254,3 变为 253,...,255 变为 1!换句话说,如果你犯了一个非常容易理解的错误,给imshow 一个像素值在 0..255 范围内浮动的图像,那么这些值将被有效地取反,因此 0->0, 1->255, 2 ->254,...,255->1。 (这与将范围完全倒置并不完全相同,因为保留了 0。)

这就是发生在你身上的事情:imC 的每个元素在数值上都等于im 的相应元素,但是因为imC 是一个浮点数组而不是一个无符号小整数数组,所以它得到了如上所述的处理,您得到的图像几乎是您预期的照片底片。

【讨论】:

  • 我在某个问题上得到的最佳答案!
  • 谢谢。很高兴为您服务!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-06
  • 2022-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多