等数组但在视觉上不一样

时间:2016-05-23 14:19:16

标签: python numpy matplotlib keras

enter image description here

我有一个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()

发生了什么事?

1 个答案:

答案 0 :(得分:4)

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

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

恰好matplotlib.pyplot.imshow根据元素类型对输入的处理方式不同。特别是,如果你给它一个 m -by- n -by-3元素类型uint8的数组,它将取0代表最暗,255代表正如您所料,三种颜色通道中的每种通道都是最轻的;但是,如果你给它一个 m -by- n -by-3元素类型float64数组,它希望所有值都在范围内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是一个浮点数而不是一个无符号的小数组-integer数组它得到了上面描述的处理,你几乎得到了你期望的图像的负面照片。