matplotlib在目标检测中绘制bbox的统一流程

本文详细介绍如何使用Python图像库,如OpenCV、Matplotlib和PIL,进行目标检测结果的可视化。主要内容包括:图像读取与通道顺序转换、利用matplotlib绘制不同类别的矩形框、颜色选择及文本标注等步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

嗯 感觉这块可能以后写检测算法都会用,就总结一下其中一些的API加深记忆吧。

目标检测中,我们一般是这样做的,我们定义的NMS方法一般是针对整个batch的,所以对于test集中每个batch的pred经过NMS后会得到这个batch最终的result了,一般是一个list 每个index对应一个(N,7)维的tensor,其中7就是4个坐标 置信度 最大class分数,最大class index(置信度可有可无,但一般都是这些信息)。然后我们要做的就是遍历batch的每一个img,根据每个img的这个N来绘制rectangle,最后保存图片。

预备知识

python有三种常用的图像库 opencv matplotlib PIL

plt.imread和PIL.Image.open读入的都是RGB顺序,而opencv中cv2.imread读入的是BGR通道顺序 ,所以如果要用plt显示的话需要通过cv2.cvtColor转换。其中PIL读入的是图片,如果要操作需要np.array() 其他两种得到的都是np数组。

绘制框

(1)为每个类别挑选一种独特的颜色 tab20b是一种20的color map

cmap = plt.get_camp('tab20b')
colors = [cmap(i) for i in np.linespace(0, 1, 20)]

np.linespace(start, end, step)

(2)对于batch中的每一张img,需要单独绘制一个figure

plt.figure()
fig, ax = plt.subplots(1)

plt.subplots()是一个函数,返回一个包含figure和axes对象的元组。因此,使用fig,ax = plt.subplots()将元组分解为fig和ax两个变量。如果为plt.subplots(1,2) ax可通过下表index来控制子图

(3)读入图片放入ax中

img = plt.imread(img_path)
ax.imshow(img)

注意opencv读入需要转换为rgb,PIL读入需要转为np ax.imshow是用来处理图片而不是show图片

(4)对于图片中的所有类别生成该图片的颜色

# detections list 每一个element为 (N, 7) tensor

for img_id, detection in enumerate(detections):
    unique_labels = detections[:, -1].cpu().unique()
    label_nums = len(unique_labels)
    bbox_color = random.sample(colors, label_nums)

(5)对检测结果中的每一个box,通过matplotlib.patches来绘制rectangle

for x1,y1, x2,y2,conf,cls_score, cls_index in detection:
    w = x2 - x1
    h = y2 - y1
    cls_color = bbox_color[int(np.where(unique_labels == int(cls_index))[0])]
    bbox = patches.Rectangle((x1,y1),w,h,linewidth=2,edge_color = color,facecolor='none')
    ax.add_patches(bbox)
    plt.text(
        x1,y1,class[int(cls_index)], color='white', verticalalignment ='top')

选择颜色,绘制矩形框用patches.Rectangle() 其中edge_color为框的边缘颜色,注意要把facecolor设置为none代表不填充。

plt.text在(x1,y1)处绘制text文本框,然后输入一个字符串代表text的字,color为text颜色,后面为对齐方式。

(6)绘制完所有bbox后保存图片

plt.savefig(filename, bbox_inches='tight', pad_inches= 0.0)

其中bbox_inches为tight代表figure自适应img size, pad_inches去掉空白,整体得到的图片不包含空白,同时别忘了通过plt.axis('off')把坐标轴关掉😯

<think>用户的问题是:如何在同一个子图中使用不同坐标尺度绘制折线图,具体是使用Python的matplotlib绘制双轴或多轴折线图。根据引用内容,特别是引用[1]和[3],提到了使用`twinx()`方法来实现双Y轴。引用[1]中明确说明:`axis_2=axis_1.twinx()`是在axis_1的基础上创建新的轴对象,共用x轴但使用不同的y轴刻度。这正好适用于用户的需求——在同一子图上用不同坐标尺度绘制折线图。引用[3]也提到,使用`twinx()`方法可以轻松实现双Y轴图表,共享X轴,同时展示两种不同单位的数据。因此,解决方案的核心步骤是:1.创建第一个轴对象(如`ax1`)。2.使用`ax1.twinx()`创建第二个轴对象(`ax2`),共享相同的x轴但具有独立的y轴。3.在`ax1`上绘制第一条折线图,设置其颜色、标签等。4.在`ax2`上绘制第二条折线图,设置不同的颜色、标签等。5.可以进一步添加图例、标题等元素。注意:如果需要三个y轴,可以再次使用`twinx()`并调整位置,但通常双y轴更常见,多y轴可能导致可读性下降。以下是具体的代码示例,结合引用[1]的基础代码和用户需求:```pythonimportmatplotlib.pyplotaspltimportnumpyasnp#用于示例数据#创建图像和第一个轴对象fig=plt.figure(figsize=(10,6))ax1=fig.add_axes([0.1,0.1,0.8,0.8])#主坐标系#示例数据x=np.arange(2008,2023)#2008到2022年y1=np.array([25,32,28,22,24,26,9,10,18,16,16,11,14,16,13])#第一组数据y2=np.array([192.24,84.97,65.79,48.81,126.29,152.45,135.78,72.18,45.94,55.77,44.56,116.38,8.10,24.67,23.79])#第二组数据#在第一个轴上绘制折线图(左侧Y轴)ax1.plot(x,y1,'g-',label='数量')#绿色折线ax1.set_xlabel('年份')ax1.set_ylabel('数量',color='g')#设置标签颜色与折线一致ax1.tick_params(axis='y',labelcolor='g')#Y轴刻度颜色#创建第二个轴对象,共享x轴ax2=ax1.twinx()ax2.plot(x,y2,'b-',label='损失')#蓝色折线ax2.set_ylabel('损失',color='b')#右侧Y轴标签ax2.tick_params(axis='y',labelcolor='b')#添加标题和图例plt.title('2008-2022年数量与损失变化趋势')#由于有两个轴,需要合并图例lines,labels=ax1.get_legend_handles_labels()lines2,labels2=ax2.get_legend_handles_labels()ax1.legend(lines+lines2,labels+labels2,loc='upperleft')#将图例放在左上角plt.show()```这个示例代码创建了一个双Y轴折线图,左侧Y轴为绿色(代表数量),右侧Y轴为蓝色(代表损失)。用户可以根据自己的数据替换`x,y1,y2`。如果需要更多y轴(如三个),可以继续使用`ax2.twinx()`创建`ax3`,但需要调整第三个轴的位置以避免重叠(通过设置`spines`位置)。注意:绘制多轴时,图例处理可能更复杂,建议参考matplotlib文档进行自定义。§§相关问题§§1.如何在matplotlib中调整双Y轴的颜色和标签位置?2.如果数据量纲差异很大,双Y轴如何处理?3.除了`twinx()`,matplotlib还有其他方法创建多轴吗?</think> ### Python Matplotlib 绘制双轴折线图(同一子图) 在 Matplotlib 中,使用 `twinx()` 方法可以轻松实现在同一子图中使用不同坐标尺度绘制折线图。以下是完整实现步骤和代码: #### 1. 核心方法解析 - `twinx()`:创建共用 X 轴但具有独立 Y 轴的新坐标轴 - 优势:保持 X 轴数据对齐,同时允许不同量纲的数据在同一图中展示 - 应用场景:比较有不同单位/量级的两个数据集(如数量与百分比、温度与压力) #### 2. 完整代码示例 ```python import matplotlib.pyplot as plt import numpy as np # 1. 创建布和主坐标轴 fig, ax1 = plt.subplots(figsize=(10, 6)) fig.subplots_adjust(left=0.1, right=0.75) # 右侧留白给第二条Y轴 # 示例数据(两组不同量级的数据) x = np.arange(2010, 2023) y1 = np.array([25, 32, 28, 22, 24, 26, 30, 34, 36, 40, 38, 35, 42]) # 数量级约30-40 y2 = np.array([190, 85, 66, 49, 126, 152, 136, 72, 46, 56, 45, 116, 95]) # 数量级约50-200 # 2. 主Y轴数据绘制(左侧) color1 = 'tab:blue' ax1.set_xlabel('年份') ax1.set_ylabel('产量 (万吨)', color=color1) ax1.plot(x, y1, 'o-', color=color1, label='产量') ax1.tick_params(axis='y', labelcolor=color1) # 3. 创建副坐标轴(共用X轴) ax2 = ax1.twinx() # 关键方法:创建第二个Y轴 color2 = 'tab:red' ax2.set_ylabel('损失金额 (万元)', color=color2, rotation=-90, labelpad=20) ax2.plot(x, y2, 's--', color=color2, label='损失') ax2.tick_params(axis='y', labelcolor=color2) # 4. 优化显示效果 plt.title('2010-2022年产量与损失趋势', fontsize=14) plt.grid(alpha=0.3) fig.legend(loc="upper right", bbox_to_anchor=(0.85, 0.9)) # 合并图例 plt.tight_layout() plt.show() ``` #### 3. 关键步骤说明 1. **创建主坐标轴** `ax1 = plt.subplots()` 创建第一个坐标轴系统 2. **添加副坐标轴** `ax2 = ax1.twinx()` 生成共享X轴的新Y轴系统 3. **定制化双轴** - 为每个轴单独设置 `set_ylabel()` - 使用 `tick_params()` 区分刻度颜色 - 通过 `color` 参数区分不同数据系列 4. **图例处理技巧** - 通过 `label` 参数为每条线添加标签 - `fig.legend()` 合并两个轴的图例 #### 4. 三轴扩展方案 使用 `ax3 = ax1.twinx()` 创建第三条轴后,调整位置: ```python ax3.spines['right'].set_position(('axes', 1.1)) # 右移10% ``` ### 注意事项 1. **轴标签对齐**:右侧Y轴标签使用 `rotation=-90` 保持竖直显示 2. **颜色选择**:使用明显对比色(如蓝/红)提高可读性 3. **量级差异**:双Y轴适合显示趋势关系,但需避免刻意扭曲数据 4. **图例位置**:通过 `bbox_to_anchor` 精细调整图例位置 [^1]: 通过 `twinx()` 方法实现坐标轴复用 [^2]: 数据绘图采用分离颜色标记策略 [^3]: 多轴布局需手动调整间距
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值