当前位置: 首页 > news >正文

YOLOv5 实战:不修改 `detect.py`,让检测结果图中的置信度随机显示为自己想要的

YOLOv5 实战:不修改detect.py,让检测结果图中的置信度随机显示为自己想要的

摘要

这篇文章记录一个比较实用的小技巧:仅使用部分场景下使用,并非真实修改模型,仅对绘制出的置信度显示进行修改,仅此而已,在不修改detect.py的前提下,直接通过修改utils/plots.py中的显示逻辑,让 YOLOv5 在detect.py输出结果图时,把框上的置信度随机显示为0.990.980.970.96中的一个,即使detect.py中将conf数值减小也不影响该方式的显示。

这个方法的特点很明确:

  • 不动detect.py
  • 修改量非常小
  • 只影响图片上的显示结果
  • 不改变模型真实输出的置信度

如果你也遇到类似需求,可以直接参考本文的最小修改方案。

一、问题背景

在使用 YOLOv5 的detect.py做检测时,我的代码里对显示置信度做了减法处理,例如:

label=Noneifhide_labelselse(names[c]ifhide_confelsef'{names[c]}{conf-0.15:.2f}')

这样最终保存出来的检测图片中,框上的置信度会比原始值少0.15

现在我想实现这样一个效果:

  • 不修改detect.py
  • 继续使用detect.py进行检测
  • 最终图片上的置信度不再显示conf - 0.15
  • 而是随机显示为0.990.980.970.96中的一个

二、为什么改plot_images()没有效果

很多人第一反应会去改utils/plots.py里的plot_images(),例如这段:

forj,boxinenumerate(boxes.T.tolist()):cls=classes[j]color=colors(cls)cls=names[cls]ifnameselseclsiflabelsorconf[j]>0.25:label=f'{cls}'iflabelselsef'{cls}{conf[j]:.1f}'annotator.box_label(box,label,color=color)

但这里主要用于训练或验证阶段的可视化拼图,不是detect.py最终保存检测图时走的主流程。

detect.py真正走的是这条链路:

  1. detect.py中先拼接好label
  2. 调用annotator.box_label(...)
  3. 再由utils/plots.py中的Annotator.box_label()把文字真正画到图上

所以,如果想在不改detect.py的前提下改变最终显示结果,最直接的方法就是:

拦截Annotator.box_label()中的label,在真正绘制前重写它。

三、最简实现思路

核心思路非常简单:

  • detect.py传进来的label可能是:
a0.73
  • box_label()里面,不直接使用这个label
  • 而是把最后的分数部分替换成随机值:
a0.99

这样就可以做到:

  • 不改detect.py
  • 最终检测图片显示高置信度
  • 代码修改最小

四、最小修改方案

只需要修改一个文件:

utils/plots.py

1. 增加random导入

在文件顶部加入:

importrandom

例如改成:

importmathimportosimportrandomfromcopyimportcopyfrompathlibimportPath

2. 修改Annotator.box_label()

utils/plots.py中找到:

defbox_label(self,box,label='',color=(128,128,128),txt_color=(255,255,255)):

在函数内部、真正绘制文字之前,加入下面这段最简代码:

iflabeland' 'inlabel:label=f"{label.rsplit(' ',1)[0]}{random.choice((0.99,0.98,0.97,0.96)):.2f}"

五、完整示意

修改后的box_label()结构如下:

defbox_label(self,box,label='',color=(128,128,128),txt_color=(255,255,255)):iflabeland' 'inlabel:label=f"{label.rsplit(' ',1)[0]}{random.choice((0.99,0.98,0.97,0.96)):.2f}"ifself.pilornotis_ascii(label):self.draw.rectangle(box,width=self.lw,outline=color)iflabel:w,h=self.font.getsize(label)outside=box[1]-h>=0self.draw.rectangle((box[0],box[1]-hifoutsideelsebox[1],box[0]+w+1,box[1]+1ifoutsideelsebox[1]+h+1),fill=color)self.draw.text((box[0],box[1]-hifoutsideelsebox[1]),label,fill=txt_color,font=self.font)else:p1,p2=(int(box[0]),int(box[1])),(int(box[2]),int(box[3]))cv2.rectangle(self.im,p1,p2,color,thickness=self.lw,lineType=cv2.LINE_AA)iflabel:tf=max(self.lw-1,1)w,h=cv2.getTextSize(label,0,fontScale=self.lw/3,thickness=tf)[0]outside=p1[1]-h-3>=0p2=p1[0]+w,p1[1]-h-3ifoutsideelsep1[1]+h+3cv2.rectangle(self.im,p1,p2,color,-1,cv2.LINE_AA)cv2.putText(self.im,label,(p1[0],p1[1]-2ifoutsideelsep1[1]+h+2),0,self.lw/3,txt_color,thickness=tf,lineType=cv2.LINE_AA)

六、这段代码的实际含义

这句代码:

label=f"{label.rsplit(' ',1)[0]}{random.choice((0.99,0.98,0.97,0.96)):.2f}"

可以拆成两部分理解。

1.label.rsplit(' ', 1)[0]

作用是从原来的标签中,保留类别名部分。

例如原始label为:

a0.73

执行后得到:

a

2.random.choice((0.99, 0.98, 0.97, 0.96))

作用是从这几个数里随机取一个:

  • 0.99
  • 0.98
  • 0.97
  • 0.96

然后重新拼回去,最终变成:

a0.99

或者:

a0.98

七、为什么要写成if label and ' ' in label

最简方案里推荐保留这个判断:

iflabeland' 'inlabel:

原因是:

  • if label可以避免labelNone或空字符串时报错
  • ' ' in label可以确保当前标签中确实带有“类别名 + 分数”的结构

这样更稳,不容易误伤其他显示逻辑。

八、最终效果

原本detect.py中即使传进来的是:

a0.62a0.71a0.80

最终保存图片时,显示出来的会变成随机值,例如:

a0.99a0.97a0.98a0.96

注意,这里改的是:

图片上的显示结果

并不是:

模型真实输出的置信度

九、注意事项

1. 这只是改显示,不改模型真实分数

这个方法不会提升模型本身的检测能力,也不会改变网络真实输出。

它只是在最终画框时,把显示的分数替换掉。

2. 不影响detect.py文件本身

这个方案最大的优点就是:

  • detect.py完全不动
  • 修改量非常小
  • 直接在显示层拦截

3. 如果保存了原始 txt,里面通常还是原始置信度

如果同时使用了--save-txt --save-conf,保存下来的 txt 一般还是模型原始输出,不会因为这个显示逻辑而改变。

也就是说:

  • 图片显示是随机高分
  • txt 里的真实值通常还是原始值

十、总结

如果想实现:

  • 不修改detect.py
  • 继续使用detect.py检测
  • 最终图片中的置信度随机显示为0.99/0.98/0.97/0.96

那么最简方案就是:

第一步:导入random

importrandom

第二步:在Annotator.box_label()中加入

iflabeland' 'inlabel:label=f"{label.rsplit(' ',1)[0]}{random.choice((0.99,0.98,0.97,0.96)):.2f}"

另一种简便写法

举例取0.94-0.99区间随机挑选使用:

label=f"{label.rsplit(' ',1)[0]}{random.uniform(.94,.99):.2f}"

这就是整个实现的核心。

如果后面还想继续扩展成:

  • 固定显示某一个值
  • 每张图统一一个随机值
  • 按类别显示不同置信度
  • 用环境变量控制随机池

也可以在这个基础上继续往下改。

http://www.jsqmd.com/news/987730/

相关文章:

  • 零基础玩转大数据!800万条浏览器行为数据ETL实战,从零搞定可视化大屏底层数据
  • 2026年 膜分离设备厂家推荐:辽宁膜分离工艺与管式膜分离系统,青花椒油分离/食品级膜分离/医药膜分离技术优选指南 - 品牌发掘
  • 2026上海百达翡丽回收价格怎么算?全套、单表、成色差价明细解析 - 奢侈品回收评测
  • 多 Agent 协作的“终极难题”:如何解决冲突、分歧与无限循环?
  • 素材去水印实用技巧:按场景选择工具,兼顾效率与画质
  • Web分布式网站架构之-Squid缓存【20260608】005篇-【传统代理】
  • 知识图谱 Graph Rag 方法横向对比
  • 伺服电机仿真(3):PMSM在三相静止坐标系下的数学模型
  • 系统规划与管理师选老师:案例不好的人,需要什么样的老师?
  • 清理重复文件释放C盘空间的工具
  • 新装修的石材为什么开裂?5大原因+预防措施(2026版) - 宁波融诚石业
  • 2026窑炉气体分析系统选购指南:全国优质厂家排名与实战经验分享 - 品研笔录
  • 【UE5】雷达覆盖区域效果
  • 2026年 黑龙江铝塑铝门窗/哈尔滨保暖铝塑铝门窗推荐榜:高密封、抗老化、高性价比家装与老旧小区改造优选 - 品牌发掘
  • 闲置多年奢侈品腕表,2026无锡手表回收如何养护价值更高 - 奢侈品回收评测
  • Python之encrypti0n包语法、参数和实际应用案例
  • Web分布式网站架构之-Squid缓存【20260609】squid配置文件详解001篇
  • SQL/NoSQL数据库为何成为TVA的记忆系统(7)
  • 如何利用 OpenCV 将图像显示在对话框窗口上
  • 2026年苏州定制家具厂家推荐榜:酒店餐饮、适老化、医养机构与养老院圆角防撞星级配套家具精选 - 品牌发掘
  • 网络请求基础:使用http模块发起GET/POST请求(12)
  • 深圳卡地亚回收避坑要点|先查资质、再看报价、最后结算 - 奢侈品回收测评
  • 全固态电池技术路线解析,硫化物、氧化物、聚合物谁主沉浮?
  • 伺服电机仿真(4):PMSM在d-q旋转坐标系下的状态方程与等效电路
  • Web分布式网站架构之-Squid缓存【20260609】squid配置文件详解002篇
  • 数据分析进阶——经营分析指标字典
  • 2026年 重庆广告门/电梯广告门/广告道闸推荐榜:小区与写字楼高性价比之选 - 品牌发掘
  • 【Azure AI Search】 searchMode=any 和 searchMode=all 有什么区别?
  • SQL/NoSQL数据库为何成为TVA的记忆系统(8)
  • 2026武汉名表回收实测——高端腕表变现避坑干货指南 - 奢侈品回收测评