在Python中,图像绘制是数字图像处理的基础操作之一,常用于标注、可视化、生成图形界面等场景。 通过核心库(如Pillow、OpenCV、Matplotlib),开发者可以轻松实现几何图形、文字、复杂路径的绘制, 并控制颜色、透明度、混合模式等参数。
图像的绘制
前面已经用到了图像的绘制,如:
io.imshow(img)
这一行代码的实质是利用 matplotlib
包对图片进行绘制,绘制成功后,返回一个 matplotlib
类型的数据。
因此,我们也可以这样写:
import matplotlib.pyplot as plt
plt.imshow(img)
imshow()
函数格式为:
matplotlib.pyplot.imshow(X, cmap=None)
X: 要绘制的图像或数组。
cmap: 颜色图谱(colormap), 默认绘制为RGB(A)颜色空间。
其它可选的颜色图谱如下列表:
颜色图谱 | 描述 |
---|---|
autumn | 红-橙-黄 |
bone | 黑-白,x线 |
cool | 青-洋红 |
copper | 黑-铜 |
flag | 红-白-蓝-黑 |
gray | 黑-白 |
hot | 黑-红-黄-白 |
hsv | hsv颜色空间, 红-黄-绿-青-蓝-洋红-红 |
inferno | 黑-红-黄 |
jet | 蓝-青-黄-红 |
magma | 黑-红-白 |
pink | 黑-粉-白 |
plasma | 绿-红-黄 |
prism | 红-黄-绿-蓝-紫-...-绿模式 |
spring | 洋红-黄 |
summer | 绿-黄 |
viridis | 蓝-绿-黄 |
winter | 蓝-绿 |
用的比较多的有 gray
,jet
等,如:
plt.imshow(image,plt.cm.gray)
plt.imshow(img,cmap=plt.cm.jet)
在窗口上绘制完图片后,返回一个 AxesImage
对象。要在窗口上显示这个对象,
我们可以调用 show()
函数来进行显示,但进行练习的时候(ipython环境中),
一般我们可以省略 show()
函数,也能自动显示出来。
from skimage import io,data
img=data.astronaut()
dst=io.imshow(img)
/tmp/ipykernel_940/3714355470.py:2: FutureWarning: `imshow` is deprecated since version 0.25 and will be removed in version 0.27. Please use `matplotlib`, `napari`, etc. to visualize images. dst=io.imshow(img)
print(type(dst))
<class 'matplotlib.image.AxesImage'>
可以看到,类型是 matplotlib.image.AxesImage
。显示一张图片,我们通常更愿意这样写:
plt.imshow(img)
plt.show()
Matplotlib
是一个专业绘图的库,相当于 matlab
中的 plot
,可以设置多个 figure
窗口,
设置 figure
的标题,隐藏坐标尺,甚至可以使用 subplot
在一个 figure
中显示多张图片。
一般我们可以这样导入 matplotlib
库:
import matplotlib.pyplot as plt
from skimage import data
import matplotlib.pyplot as plt
img=data.astronaut()
创建一个名为 astronaut
的窗口,并设置大小:
plt.figure(num='astronaut',figsize=(8,8))
<Figure size 800x800 with 0 Axes>
<Figure size 800x800 with 0 Axes>
绘制第一幅图片:
plt.subplot(2,2,1) #将窗口分为两行两列四个子图,则可显示四幅图片
plt.title('origin image') #第一幅图片标题
plt.imshow(img)
<matplotlib.image.AxesImage at 0x7f1107ce6f60>
绘制第二幅图片,且为灰度图:
plt.subplot(2,2,2) #第二个子图
plt.title('R channel') #第二幅图片标题
plt.imshow(img[:,:,0],plt.cm.gray)
plt.axis('off') #不显示坐标尺寸
(np.float64(-0.5), np.float64(511.5), np.float64(511.5), np.float64(-0.5))
绘制第三幅图片,且为灰度图
plt.subplot(2,2,3) #第三个子图
plt.title('G channel') #第三幅图片标题
plt.imshow(img[:,:,1],plt.cm.gray)
plt.axis('off') #不显示坐标尺寸
(np.float64(-0.5), np.float64(511.5), np.float64(511.5), np.float64(-0.5))
绘制第四幅图片,且为灰度图:
plt.subplot(2,2,4) #第四个子图
plt.title('B channel') #第四幅图片标题
plt.imshow(img[:,:,2],plt.cm.gray)
plt.axis('off') #不显示坐标尺寸
plt.show() #显示窗口
将窗口分为两行两列四个子图,则可显示四幅图片
from skimage import data
import matplotlib.pyplot as plt
img=data.astronaut()
plt.figure(num='astronaut',figsize=(8,8)) #创建一个名为astronaut的窗口,并设置大小
plt.subplot(2,2,1)
plt.title('origin image') #第一幅图片标题
plt.imshow(img) #绘制第一幅图片
plt.subplot(2,2,2) #第二个子图
plt.title('R channel') #第二幅图片标题
plt.imshow(img[:,:,0],plt.cm.gray) #绘制第二幅图片,且为灰度图
plt.axis('off') #不显示坐标尺寸
plt.subplot(2,2,3) #第三个子图
plt.title('G channel') #第三幅图片标题
plt.imshow(img[:,:,1],plt.cm.gray) #绘制第三幅图片,且为灰度图
plt.axis('off') #不显示坐标尺寸
plt.subplot(2,2,4) #第四个子图
plt.title('B channel') #第四幅图片标题
plt.imshow(img[:,:,2],plt.cm.gray) #绘制第四幅图片,且为灰度图
plt.axis('off') #不显示坐标尺寸
plt.show() #显示窗口
在图片绘制过程中,我们用 matplotlib.pyplot
模块下的 figure()
函数来创建显示窗口,该函数的格式为:
matplotlib.pyplot.figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None)
所有参数都是可选的,都有默认值,因此调用该函数时可以不带任何参数,其中:
num
: 整型或字符型都可以。如果设置为整型,则该整型数字表示窗口的序号。 如果设置为字符型,则该字符串表示窗口的名称。用该参数来命名窗口, 如果两个窗口序号或名相同,则后一个窗口会覆盖前一个窗口。igsize
: 设置窗口大小。是一个tuple
型的整数,如figsize=(8,8)
dpi
: 整形数字,表示窗口的分辨率。facecolor
: 窗口的背景颜色。edgecolor
: 窗口的边框颜色。
用 figure()
函数创建的窗口,只能显示一幅图片,如果想要显示多幅图片,
则需要将这个窗口再划分为几个子图,在每个子图中显示不同的图片。
我们可以使用 subplot()
函数来划分子图,函数格式为:
matplotlib.pyplot.subplot(nrows, ncols, plot_number)
nrows
: 子图的行数。ncols
: 子图的列数。plot_number
: 当前子图的编号。
如:
plt.subplot(2,2,1)
<Axes: >
则表示将 figure
窗口划分成了2行2列共4个子图,当前为第1个子图。我们有时也可以用这种写法:
plt.subplot(221)
<Axes: >
两种写法效果是一样的。每个子图的标题可用 title()
函数来设置,
是否使用坐标尺可用 axis()
函数来设置,如:
plt.subplot(221)
plt.title("first subwindow")
plt.axis('off')
(np.float64(0.0), np.float64(1.0), np.float64(0.0), np.float64(1.0))
import matplotlib.pyplot as plt
from skimage import data,color
img = data.immunohistochemistry()
hsv = color.rgb2hsv(img)
fig, axes = plt.subplots(2, 2, figsize=(7, 6))
ax0, ax1, ax2, ax3 = axes.ravel()
ax0.imshow(img)
ax0.set_title("Original image")
Text(0.5, 1.0, 'Original image')
ax1.imshow(hsv[:, :, 0], cmap=plt.cm.gray)
ax1.set_title("H")
Text(0.5, 1.0, 'H')
ax2.imshow(hsv[:, :, 1], cmap=plt.cm.gray)
ax2.set_title("S")
Text(0.5, 1.0, 'S')
ax3.imshow(hsv[:, :, 2], cmap=plt.cm.gray)
ax3.set_title("V")
Text(0.5, 1.0, 'V')
for ax in axes.ravel():
ax.axis('off')
fig.tight_layout()
import matplotlib.pyplot as plt
from skimage import data,color
img = data.immunohistochemistry()
hsv = color.rgb2hsv(img)
fig, axes = plt.subplots(2, 2, figsize=(7, 6))
ax0, ax1, ax2, ax3 = axes.ravel()
ax0.imshow(img)
ax0.set_title("Original image")
ax1.imshow(hsv[:, :, 0], cmap=plt.cm.gray)
ax1.set_title("H")
ax2.imshow(hsv[:, :, 1], cmap=plt.cm.gray)
ax2.set_title("S")
ax3.imshow(hsv[:, :, 2], cmap=plt.cm.gray)
ax3.set_title("V")
for ax in axes.ravel():
ax.axis('off')
fig.tight_layout()
fig.tight_layout()
自动调整 subplot
间的参数。
直接用 subplots()
函数来创建并划分窗口。
注意,比前面的 subplot()
函数多了一个 s
,该函数格式为:
matplotlib.pyplot.subplots(nrows=1, ncols=1)
nrows
: 所有子图行数,默认为1。ncols
: 所有子图列数,默认为1。
返回一个窗口 figure
, 和一个 tuple
型的 ax
对象,该对象包含所有的子图。
可结合 ravel()
函数列出所有子图,如:
fig, axes = plt.subplots(2, 2, figsize=(7, 6))
ax0, ax1, ax2, ax3 = axes.ravel()
创建了2行2列4个子图,分别取名为 ax0
,ax1
,ax2
和ax3
,
每个子图的标题用 set_title()
函数来设置,如:
ax0.imshow(img)
ax0.set_title("Original image")
Text(0.5, 1.0, 'Original image')
如果有多个子图,我们还可以使用 tight_layout()
函数来调整显示的布局,该函数格式为:
matplotlib.pyplot.tight_layout(pad=1.08, h_pad=None, w_pad=None, rect=None)
所有的参数都是可选的,调用该函数时可省略所有的参数。
pad: 主窗口边缘和子图边缘间的间距,默认为1.08
h_pad, w_pad: 子图边缘之间的间距,默认为 pad_inches
rect: 一个矩形区域,如果设置这个值,则将所有的子图调整到这个矩形区域内。
一般调用为:
plt.tight_layout()
<Figure size 640x480 with 0 Axes>
上面函数自动调整 subplot
间的参数。
from skimage import data
from skimage.viewer import ImageViewer
img = data.coffee()
viewer = ImageViewer(img)
viewer.show()
总结
最后总结一下,绘制和显示图片常用到的函数有:
函数名 | 功能 | 调用格式 |
---|---|---|
figure | 创建一个显示窗口 | plt.figure(num=1,figsize=(8,8) |
imshow | 绘制图片 | plt.imshow(image) |
show | 显示窗口 | plt.show() |
subplot | 划分子图 | plt.subplot(2,2,1) |
title | 设置子图标题(与subplot结合使用) | plt.title('origin image') |
axis | 是否显示坐标尺 | plt.axis('off') |
subplots | 创建带有多个子图的窗口 | fig,axes=plt.subplots(2,2,figsize=(8,8)) |
ravel | 为每个子图设置变量 | ax0,ax1,ax2,ax3=axes.ravel() |
set_title | 设置子图标题(与axes结合使用) | ax0.set_title('first window') |
tight_layout | 自动调整子图显示布局 | plt.tight_layout() |