前言
经常使用COCO格式数据集的同学们肯定会经常对模型的输出结果进行可视化,可视化最常用的包是matplotlib.pyplot,下面就让我们看一下如何使用plt包对COCO格式的数据进行可视化。
这是第一部分,主要讲解用plt的原理和基本使用方法,对于COCO数据集的可视化可以直接看第二部分。
理论知识
matplotlib.pyplot是python中画图常用的包,在使用前通常用import matplotlib.pyplot as plt
引入,以下都用plt代替这个包。
plt包中有l两个重要的对象:Figure(画布对象)
、aiex(子图对象)
。
figure对象
就是一个空白的画布
,子图对象
就是画布上一块内容
(这块内容可以显示图表,也可以显示图像),一个画布上可以有多个子图
,所以也就有下文将要讲的多子图显示技术。
举个例子,figure对象可以使用plt.figure()
创建,然后使用plt.show()
进行显示,此时结果如下图,可以看到因为画布上没有任何子图对象,所以是空白的。
有了上面的理论,我们就有了一个直观的认识:当我们使用plt进行可视化时,无论是显示单个子图还是多个子图,首先要做的就是创建一个空白的画布对象
,然后创建一个个子图对象
,在对应的子图上进行相应的操作。
有些同学可能会问,显示图片的时候直接用plt.imshow(image)
就可以了啊,也没有手动创建一个Figure对象,这是因为这个函数内部自己新建了一个画布对象~
好了,有了前面知识的铺垫,就让我们从最简单的显示单张图片开始看一下到底如何使用plt包进行绘图吧!
在单个子图上显示、保存图片
如果显示图片,可以使用plt.imshow(image,cmap='')
,其中image_path代表图片,可以是io.imread()读取的Image对象,cmap代表图片的色彩空间,默认是RGB。如果显示灰度图片,需要让cmap='gray'
才能正确显示。
为了使图片显示在屏幕上,调用上面的函数后还需要调用plt.show()
使画布绘制在桌面上。
如果保存图片,可以使用plt.savefig(image_name)
保存当前画布中的内容,其中,image_name代表所要保存的路径和文件名。
在多个子图上显示图片
上面的例子我们在一个子图上显示了图片,但是如果我们想要用多个子图显示不同的图片应该怎么做呢?
首先应该在建好的空白画布上创建子图对象,然后使用plt.subplot(row, col, idx)
在子图上绘制图片,其中row代表画布的行数
,col代表画布的列数
,idx表示当前激活的子图下标
,下标从1开始,按从左往右的顺序依次递增。
为什么还需要传入子图的坐标呢?这是因为这样做即使我们不用变量接收子图对象,plt包也可以正确地知道接下来的操作应该在哪个子图上执行。具体代码如下:
I = io.imread('C:/Users/hejianfei/Desktop/ski10病理切片/001-houqi-077.jpg')
plt.subplot(1, 2, 1) # 子图分为一行两列,当前选择第一个
plt.imshow(I) # 显示图片
plt.subplot(1, 2, 2) # 子图分为一行两列,当前选择第二个
plt.imshow(I)
plt.show()
或者也可以手动得到每个子图对象,然后在子图对象上显示图片
I = io.imread('C:/Users/hejianfei/Desktop/ski10病理切片/001-houqi-077.jpg')
ax = plt.subplot(1, 2, 1) # 用ax接收当前子图对象
ax.imshow(I) # 显示图片
ax = plt.subplot(1, 2, 2)
ax.imshow(I)
plt.show()
最终的结果是一样的,如下:
在图片上绘制检测框
上面我们知道了如何在多个子图上显示图片,现在来考虑如何在图片上绘制检测框。
先来考虑如何实现这个功能,为了实现效果,我们肯定需要先显示出图片,然后再在原图上叠加上检测框,那么如何实现叠加的效果呢?
plt包中有一个ax.add_patch(obj)
函数可以实现这个功能,其中ax
代表当前的子图实例,obj
是plt包内置的形状类,可以是矩形,椭圆,多边形等等,这里我们主要用矩形类(绘制检测框)和多边形类(绘制掩码)。
检测框就是一个矩形框,可以用左上角坐标和右下角坐标
来表示这个矩形。plt包中有专门的Rectangle
类来表示一个矩形,关于此类详细的用法可以百度。
具体代码如下:
I = io.imread('C:/Users/hejianfei/Desktop/ski10病理切片/001-houqi-077.jpg')
# 实例化矩形对象:设置边框的宽度,边框的颜色,填充颜色
rect = plt.Rectangle((0.0, 0.0), 100, 100, alpha=0.8, linewidth=1, edgecolor='r', facecolor='none')
ax = plt.subplot(1, 2, 1) # 用ax接收当前子图对象
ax.imshow(I) # 显示图片
ax.add_patch(rect) # 在已有的图片上添加其他对象
ax = plt.subplot(1, 2, 2)
ax.imshow(I)
plt.show()
我们在第一个子图上显示了一个矩形框,结果如下:
如果要绘制mask,可以借助plt包中的多边形类(Poly)来实现,下面介绍COCO时会讲到。
多子图显示图片,设置窗口的属性(名称,坐标范围)
上面创建多个子图时,使用的函数为plt.subplot()
函数。实际上,还有一个常用的函数plt.add_subplot()
函数也可以用来创建子图。
二者的不同在于,在使用plt.subplot()
函数前,不需要手动调用plt.figure()
函数创建一个画布对象,而在使用plt.add_subplot
函数前需要手动调用plt.figure()
函数创建一个画布对象,具体代码如下:
I = io.imread('C:/Users/hejianfei/Desktop/ski10病理切片/001-houqi-077.jpg')
# ax = plt.subplot(1, 2, 1) # 用ax接收当前子图对象
# ax.imshow(I) # 显示图片
# ax = plt.subplot(1, 2, 2)
# ax.imshow(I)
# plt.show()
fig = plt.figure() # 创建figure对象
ax = fig.add_subplot(1, 2, 1) # 添加子图
ax.imshow(I)
ax = fig.add_subplot(1, 2, 2)
ax.imshow(I)
plt.show()
多子图显示时可以通过ax.set_title()
函数设置子图名称,ax.set_xlim(-10, 20)
ax.set_ylim(-10, 20)
设置子图显示的坐标范围,具体代码如下:
fig = plt.figure()
titles = ['iou', 'giou', 'diou', 'ciou']
for i in range(4):
ax = fig.add_subplot(2, 2, i + 1)
ax.set_title(titles[i])
rect1 = plt.Rectangle(
(recs[i*2][0][0], recs[i*2][0][1]), # (x,y)矩形左下角
recs[i*2][0][3] - recs[i*2][0][1], # width长
recs[i*2][0][2] - recs[i*2][0][0], # height宽
color='maroon',
alpha=0.5)
ax.add_patch(rect1)
rect2 = plt.Rectangle(
(recs[i * 2 + 1][0][0], recs[i * 2 + 1][0][1]), # (x,y)矩形左下角
recs[i * 2 + 1][0][3] - recs[i * 2 + 1][0][1], # width长
recs[i * 2 + 1][0][2] - recs[i * 2 + 1][0][0], # height宽
color='green',
alpha=0.5)
ax.add_patch(rect2)
ax.set_xlim(-10, 20)
ax.set_ylim(-10, 20)
plt.show()