news 2026/6/21 2:37:57

【程序干货】YOLO 预测检测结果不顺心?手把手教你自定义“红框白字”专业视觉效果(附完整代码)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
【程序干货】YOLO 预测检测结果不顺心?手把手教你自定义“红框白字”专业视觉效果(附完整代码)

目录

0. 前言——为什么需要自定义可视化?

1. 核心功能点

2. 技术细节:如何实现“红底白字”?

3. 完整代码实现

4. 使用说明

5. 总结


0. 前言——为什么需要自定义可视化?

在使用 Ultralytics YOLO(v8/v9/v10/v11)进行目标检测时,我们通常直接调用 model.predict(save=True)。虽然官方自带的可视化很方便,但它会根据不同的类别分配不同的颜色。

在某些学术论文、工业报告特定演示场景下,我们往往需要更统一、更专业的视觉风格——例如:亮红色的检测框、红色的标签背景,搭配纯白色的文字

今天分享一个实用的 Python 脚本,直接绕过官方 UI,利用OpenCV重新绘制:红色边框、红色标签底、纯白文字。让你的检测结果图瞬间达到出版级水准!

1. 核心功能点

  1. 极简视觉风格:统一采用“红框 + 红底 + 白字”,重点突出,风格专业。

  2. 双重输出:既生成自定义样式的图片,也支持同步保存标准 YOLO 格式的 .txt 标签。

  3. 坐标精准处理:自动处理标签背景框越界问题(当物体在图片顶部时,标签会自动调整位置)。

  4. 参数化配置:支持通过命令行调整置信度、框粗细、字体大小等。


2. 技术细节:如何实现“红底白字”?

官方的 plot() 函数高度封装,难以精细修改颜色逻辑。本脚本通过以下逻辑实现:

  • 提取结果:利用 result.boxes 获取坐标、类别和置信度。

  • OpenCV 绘制

    • cv2.rectangle:画出红色(BGR: 0, 0, 255)的边框。

    • cv2.getTextSize:计算文字宽度,动态生成背景红色矩形。

    • cv2.putText:在红色背景上叠写白色文字。

3. 完整代码实现

您可以直接将以下代码保存为 custom_predict.py 并运行。

import argparse import os import warnings import cv2 from ultralytics import YOLO warnings.filterwarnings("ignore") def save_txt_yolo_format(result, img_w, img_h, txt_path, save_conf=True): """ 保存 YOLO 格式标签: class x_center y_center w h [conf] 归一化到 0~1 """ lines = [] if result.boxes is None or len(result.boxes) == 0: open(txt_path, "w").close() return boxes_xyxy = result.boxes.xyxy.cpu().numpy() clss = result.boxes.cls.cpu().numpy().astype(int) confs = result.boxes.conf.cpu().numpy() if result.boxes.conf is not None else None for i, (x1, y1, x2, y2) in enumerate(boxes_xyxy): x1, y1, x2, y2 = float(x1), float(y1), float(x2), float(y2) xc = (x1 + x2) / 2.0 / img_w yc = (y1 + y2) / 2.0 / img_h bw = (x2 - x1) / img_w bh = (y2 - y1) / img_h if save_conf and confs is not None: lines.append(f"{clss[i]} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f} {confs[i]:.6f}") else: lines.append(f"{clss[i]} {xc:.6f} {yc:.6f} {bw:.6f} {bh:.6f}") with open(txt_path, "w") as f: f.write("\n".join(lines)) def draw_red_box_red_bg_white_text(results, out_dir, save_txt=False, save_conf=True, line_thickness=2, font_scale=0.6): """ 框=红、标签底=红、文字=白色(类别+置信度) """ os.makedirs(out_dir, exist_ok=True) labels_dir = os.path.join(out_dir, "labels") if save_txt: os.makedirs(labels_dir, exist_ok=True) red = (0, 0, 255) # BGR 红色 white = (255, 255, 255) # BGR 白色 for r in results: img_path = r.path img = cv2.imread(img_path) if img is None: print(f"⚠️ 读图失败: {img_path}") continue h, w = img.shape[:2] names = r.names # dict: class_id -> class_name # 保存 txt if save_txt: base = os.path.splitext(os.path.basename(img_path))[0] txt_path = os.path.join(labels_dir, base + ".txt") save_txt_yolo_format(r, w, h, txt_path, save_conf=save_conf) # 画框 + 标签 if r.boxes is not None and len(r.boxes) > 0: boxes = r.boxes.xyxy.cpu().numpy() confs = r.boxes.conf.cpu().numpy() if r.boxes.conf is not None else None clss = r.boxes.cls.cpu().numpy().astype(int) if r.boxes.cls is not None else None for i, (x1, y1, x2, y2) in enumerate(boxes): x1, y1, x2, y2 = map(int, [x1, y1, x2, y2]) # 红框 cv2.rectangle(img, (x1, y1), (x2, y2), red, line_thickness) # 标签文本:class + conf label = "" if clss is not None: label += names.get(int(clss[i]), str(int(clss[i]))) if save_conf and confs is not None: label += f" {confs[i]:.2f}" if label.strip(): (tw, th), baseline = cv2.getTextSize( label, cv2.FONT_HERSHEY_SIMPLEX, font_scale, 2 ) # 标签放在框上方,避免越界;放不下就顶到0 y_top = max(0, y1 - th - baseline - 6) # 标签背景:红色 cv2.rectangle( img, (x1, y_top), (x1 + tw + 6, y1), red, -1 ) # 标签文字:白色 cv2.putText( img, label, (x1 + 3, y1 - 4), cv2.FONT_HERSHEY_SIMPLEX, font_scale, white, 2, cv2.LINE_AA ) save_path = os.path.join(out_dir, os.path.basename(img_path)) cv2.imwrite(save_path, img) def main(opt): model = YOLO(opt.weights) print(f"🔍 开始预测:{opt.source}") print(f"✅ 权重:{opt.weights}") # 预测:关闭官方保存,自己画(才能控颜色) results = model.predict( source=opt.source, imgsz=opt.img_size, device=opt.device, conf=opt.conf, save=False, verbose=False ) out_dir = os.path.join(opt.project, opt.name) draw_red_box_red_bg_white_text( results, out_dir=out_dir, save_txt=opt.save_txt, save_conf=True, line_thickness=opt.thickness, font_scale=opt.font_scale ) print(f"✅ 完成(红框+红底+白字),输出目录:{out_dir}") if opt.save_txt: print(f"✅ txt 已保存到:{os.path.join(out_dir, 'labels')}") if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument( "--weights", type=str, default="/root/autodl-tmp/ultralytics-main/runs/detect/train3/weights/best.pt", help="model weight path" ) parser.add_argument( "--source", type=str, default="/root/autodl-tmp/ultralytics-main/images", help="image dir or image file" ) parser.add_argument("--img_size", type=int, default=640, help="image size") parser.add_argument("--device", type=str, default="0", help="cuda device") parser.add_argument("--conf", type=float, default=0.25, help="confidence threshold") parser.add_argument("--project", type=str, default="runs/predict", help="save root dir") parser.add_argument("--name", type=str, default="train1_pred", help="save sub dir name") parser.add_argument("--save_txt", action="store_true", help="save yolo txt labels") parser.add_argument("--thickness", type=int, default=2, help="box line thickness") parser.add_argument("--font_scale", type=float, default=0.6, help="label font scale") opt = parser.parse_args() main(opt)

4. 使用说明

1. 基础预测:

codeBash

downloadcontent_copy

expand_less

python custom_predict.py --weights ./runs/train/best.pt --source ./data/test_images

2. 调整线条粗细与字体(适合高分辨率图):

codeBash

downloadcontent_copy

expand_less

python custom_predict.py --weights best.pt --source ./images --thickness 4 --font_scale 0.8

3. 同时生成标签文件(用于辅助标注):

codeBash

downloadcontent_copy

expand_less

python custom_predict.py --weights best.pt --source ./images --save_txt

5. 总结

通过简单的 OpenCV 二次开发,我们可以轻松突破 YOLO 官方库的可视化限制。这种红底白字的风格不仅统一了视觉语言,更在复杂背景下提供了极佳的辨识度。

如果你觉得这个脚本有用,欢迎点赞、收藏,并关注我的 CSDN 账号,获取更多深度学习实用工具!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/19 6:46:41

66、组策略与VDI:优化指南与实用技巧

组策略与VDI:优化指南与实用技巧 1. 总结与资源推荐 在管理桌面系统时,我们借助登录和启动脚本实现用户任务自动化,运用新技术管理Internet Explorer设置,利用硬件控制阻止不良设备接入网络,并确保用户在需要时能使用打印机。 为了进一步提升技能,你可以访问 www.GPa…

作者头像 李华
网站建设 2026/6/19 23:57:34

67、VDI、组策略与安全配置管理全解析

VDI、组策略与安全配置管理全解析 1. VDI 与组策略的最终思考 在管理计算机时,组织单位(OU)的创建通常会与管理者相对应。然而,对于虚拟桌面基础架构(VDI)机器,其管理方式可能需要区别于传统的桌面或笔记本电脑。为了实现这一目标,建议为 VDI 机器设置独立的 OU 结构…

作者头像 李华
网站建设 2026/6/19 22:05:15

零基础入门树莓派烧录与SD卡分区关联

从零开始搞懂树莓派烧录:不只是“写入镜像”,更是构建启动生态 你有没有试过把系统镜像拖进SD卡,插上树莓派却黑屏?红灯常亮、绿灯不闪,或者卡在彩虹画面动不了?别急——这很可能不是硬件坏了,…

作者头像 李华
网站建设 2026/6/18 12:06:18

异或门在TTL集成电路中的时序特性分析:系统学习

异或门在TTL电路中的真实表现:不只是逻辑,更是时序的艺术你有没有遇到过这样的情况——系统明明逻辑正确,却在高速运行时频频出错?信号毛刺、数据错位、校验失败……排查到最后,问题竟藏在一个看似最简单的元件里&…

作者头像 李华
网站建设 2026/6/13 10:03:52

LangFlow企业内训课程设计助手

LangFlow企业内训课程设计助手 在企业加速推进AI落地的今天,一个现实问题日益凸显:如何让非技术背景的员工也能真正“动手”参与大模型应用的设计与实验?许多公司组织了多轮AI培训,但学员往往止步于听懂概念,一旦涉及代…

作者头像 李华
网站建设 2026/6/18 19:12:36

树莓派5引脚定义入门必看:GPIO基础功能详解

树莓派5 GPIO入门指南:从引脚定义到实战控制 你刚拿到一块树莓派5,准备点亮第一颗LED,却在接线时犯了难—— “物理引脚11到底对应哪个GPIO?” “为什么程序运行后外设没反应,甚至板子还发热了?” …

作者头像 李华