所以我使用这个非常简单的图像来理解图像如何存储在数组中以及如何操作它。
侧面说明
任何人都可以向我推荐一本以这些基础知识开头的书/博客,因为他们中的大多数都跳过了这一部分,即使是微不足道但我不能 这些细微差别让我头疼的进展
它的8x8像素图像,在左上角的像素中有一个点。
#import modules
import matplotlib.pyplot as plt
from PIL import Image
%matplotlib inline
import numpy as np
#Load image as array
i=Image.open("dot.png")
iar=np.asarray(i)
现在进行分析,首先我开始显示一些数组,然后我终于显示" dot.png"
LINK TO dot.png图片(使用ctrl + s将其保存为非常小的2x2像素,因此不可见)https://i.stack.imgur.com/y2ot9.png
plt.imshow([0])
TypeError: Invalid dimensions for image data
但是
plt.imshow([[0]])
plt.imshow([[255]])
plt.imshow([[255,0]])
plt.imshow([[255,0,128]])
plt.imshow([[255,0],[23,128]])
plt.imshow(iar[0])
plt.imshow(iar[0:1])
# Checking attributes of iar[0]
subset1=iar[0]
subset1.shape
Out[144]: (8L, 4L)
In [140]:iar[0]
Out[140]:
array([[ 0, 0, 0, 255],
[255, 255, 255, 255],
[255, 255, 255, 255],
[255, 255, 255, 255],
[255, 255, 255, 255],
[255, 255, 255, 255],
[255, 255, 255, 255],
[255, 255, 255, 255]], dtype=uint8)
# Checking attributes of iar[0:1]
subset2=iar[0:1]
subset2.shape
Out[146]: (1L, 8L, 4L)
In [142]:iar[0:1]
Out[141]:
array([[[ 0, 0, 0, 255],
[255, 255, 255, 255],
[255, 255, 255, 255],
[255, 255, 255, 255],
[255, 255, 255, 255],
[255, 255, 255, 255],
[255, 255, 255, 255],
[255, 255, 255, 255]]], dtype=uint8)
我的问题: -
plt.imshow([0])
失败但plt.imshow([[0]])
有效?plt.imshow([[0]])
和& plt.imshow([[255]])
只显示蓝色?尽管0并不意味着蓝色,也不意味着蓝色
255表示蓝色。plt.imshow([[0]])
正在显示尺寸为1x1的图片。它是一个像素图像?如果是的话
plt.imshow([[255,0]])
表示2像素?plt.imshow([[255,0,128]])
显示所有颜色模糊
边界。这是怎么回事?答案 0 :(得分:7)
好的,所以你的一些问题是关于pyplot.imshow
的行为。
imshow
显示一个图像,并将"类似数组的"作为参数,形状为(n, m)
(对于灰度图像),{{1} (对于彩色图像)或(n, m, 3)
(对于具有透明度或alpha信息的彩色图像)。
执行(n, m, 4)
时,您传递的形状为plt.imshow([0])
的参数,这就是您收到错误的原因。列表(1,)
是一维的,而不是两个,因此[0]
无法显示。相比之下,imshow
是一个二维数组,代表一个像素,因此可以显示。
[[0]]
和[[0]]
都会显示为蓝色方块。这是因为matplotlib对灰度图像的像素值进行了颜色映射。颜色映射意味着matplotlib在您传递的数据中找到值的范围,并将最低值设为一种颜色,将最高值设为另一种颜色,将地图之间的所有值设置为某些颜色范围设计为漂亮,或者在解释数据时很有用。如果您的图像只有一个像素,则没有颜色范围,因此整个图像将以相同的颜色显示。请注意,如果您没有为参数[[255]]
指定不同的值,则matplotlib默认使用jet
colourmap。
cmap
正在显示两像素图像;您传递的数组有一行有两列。 Matplotlib将其显示为两种颜色:我们可以看到红色表示高(plt.imshow([[255,0]])
)和蓝色低(255
)。
图像模糊,因为matplotlib会插入图像数据。您可以通过为0
提供interpolation
参数的值来更改此行为(matplotlib默认使用imshow
,这样可以获得"抗锯齿"外观)
'bilinear'
接下来,您将显示3像素灰度图像(plt.imshow([[255,0]], interpolation='none')
)。这显示为从红色到蓝色到绿色的渐变;这些颜色再次从[[255,0,128]]
颜色图中获取(红色为高,绿色为中,蓝色为低)。 jet
将为红色,蓝色,蓝色,因为此数据的范围是128到255,因此128将是新的低(蓝色)。
好的,最后,我们来看你的8x8图像。您的PNG图像可能只包含黑白像素,但它以RGB格式存储。我们可以看到这一点,例如,使用ImageMagick:
[[255,128,128]]
所以这意味着每个像素由三个字节表示(红色,绿色和蓝色)。 PIL在RGBA模式下打开它,为alpha通道添加另一个字节:
$ identify ~/Downloads/y2ot9.png
/home/user/Downloads/y2ot9.png PNG 8x8 8x8+0+0 8-bit sRGB 138B 0.010u 0:00.059
第一个像素是黑色,其他像素是白色。我们可以看到黑色是元组>>> from PIL import Image
>>> import os
>>> i = Image.open(os.path.expanduser('~/Downloads/y2ot9.png'))
>>> i.size
(8, 8)
>>> i.mode
'RGBA'
(即0红色,0绿色,0蓝色和255,或完整,alpha)。同样,白色为(0, 0, 0, 255)
:
(255, 255, 255, 255)
当您将此图像放入numpy数组时,您将获得这些相同的像素值。数组的形状为>>> i.getpixel((0,0))
(0, 0, 0, 255)
>>> i.getpixel((1,0))
(255, 255, 255, 255)
:
(8, 8, 4)
这意味着每个像素(红色,绿色,蓝色,alpha)有8行,8列和4个组件。
使用>>> import numpy as np
>>> a = np.asarray(i)
>>> a.shape
(8, 8, 4)
会为您提供此数组的第一行,其形状为a[0]
。有8列像素,每列有4个分量。当您将其发送到(8, 4)
时,它会被解释为大小为8x4的灰度图像,因为您已经获得了二维数据。您将获得图像第一行的颜色映射显示。您可以将第一个像素视为三个蓝色值(黑色像素的三个imshow
)。图像的最后一列到处都是红色,因为你的图像到处都是完整的alpha。
0
为您提供了一个数组;这将是a[0:1]
的形状。当您将其发送到(1, 8, 4)
时,它会被解释为大小为1x8的彩色图像(因为它的三维数据,最后一个维度为4,表示带有alpha信息的颜色)。这就是为什么要显示这个为你提供一个黑白条,这是你可能期望看到的图片。您可以通过显示imshow
来获得相同的结果。
由于您正在处理黑白图像数据,因此以灰度表示数据可能更直观。您可以通过将PNG文件更改为灰度来执行此操作,也可以使用PIL在Python中转换图像:
[a[0]]
如果您使用灰度数据,>>> i2 = i.convert('L')
>>> a2 = np.asarray(i2)
>>> a2.shape
(8, 8)
将始终对所有内容进行颜色映射,因此您不会在颜色映射的灰度信息和全色信息之间进行这种不可预测的切换(这取决于形状你发送给imshow
的数组数据。
要点:
imshow
显示数组中的值。数组的形状很重要,因为imshow
会自动在显示彩色映射的灰度数据或显示全彩数据之间切换。imshow
会插值,从而导致图像模糊。imshow
通常用于显示具有单个组件的二维数据(灰度);颜色映射有助于使绘图更具吸引力,并且显示出变化,如果一切都只是灰色则更难以看到。另一方面,图像数据通常包括颜色信息。我不知道在哪里可以获得初学者对图像处理的概述(也许可以尝试阅读How do I get started with image processing?)。我之前已经听过Lecture 1 Introduction to Digital Image Processing推荐,您也可以继续探索,例如,通过阅读简单Netpbm format等图像数据格式。 / p>