我有一个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()
发生了什么事?
答案 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数组它得到了上面描述的处理,你几乎得到了你期望的图像的负面照片。