news 2026/4/18 12:10:27

YOLOE官版镜像Gradio定制:YOLOE-v8l-seg界面添加历史记录与导出功能

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
YOLOE官版镜像Gradio定制:YOLOE-v8l-seg界面添加历史记录与导出功能

YOLOE官版镜像Gradio定制:YOLOE-v8l-seg界面添加历史记录与导出功能

1. 为什么需要给YOLOE Gradio界面加历史记录和导出功能

YOLOE官版镜像开箱即用,但原生Gradio界面只提供基础的单次推理交互——上传一张图、输入几个词、点一下运行,结果一闪而过。你没法回看上一次检测了什么物体,不能对比不同提示词的效果,更无法把分割掩码、边界框坐标或检测日志保存下来做后续分析。

这在实际工作中很不方便。比如你在调试一个新场景的文本提示词时,想对比“person, dog, bicycle”和“human, pet, two-wheeler”的识别差异;又比如你要批量处理一批工业零件图像,需要把每次的分割掩码和类别置信度导出成JSON供下游系统使用;再比如团队协作时,同事想复现你昨天跑出的那个高精度分割结果,却找不到参数和输入图。

所以,我们对YOLOE-v8l-seg的Gradio界面做了轻量但实用的增强:不改模型、不重写推理逻辑、不增加依赖,只在前端交互层添加两个刚需功能——自动保存历史记录一键导出结构化结果。整个过程只需修改不到50行Python代码,所有改动都兼容原镜像环境,部署后立即生效。

2. 环境准备与定制前确认

2.1 确认YOLOE官版镜像已就绪

请确保你正在使用的容器已按官方指南完成初始化:

  • Conda环境yoloe已激活
  • 项目路径/root/yoloe存在且可读写
  • gradio库版本 ≥ 4.30(本定制基于Gradio 4.35测试通过)

你可以用以下命令快速验证:

conda activate yoloe cd /root/yoloe python -c "import gradio as gr; print(f'Gradio version: {gr.__version__}')"

如果输出类似Gradio version: 4.35.2,说明环境完全就绪。

2.2 原生Gradio入口定位

YOLOE官版镜像中,Gradio演示界面由app.py启动。它默认位于:

/root/yoloe/app.py

该文件调用predict_text_prompt.py的核心逻辑,构建了一个简洁的三栏界面:左侧上传区、中间提示词输入框、右侧结果展示区。我们的所有定制都将围绕这个文件展开,不触碰任何模型代码或预测脚本

重要提醒:定制前建议先备份原文件:

cp /root/yoloe/app.py /root/yoloe/app.py.bak

3. 添加历史记录功能:让每一次推理都可追溯

3.1 历史记录的设计思路

我们不采用数据库或外部存储,而是用最轻量的方式——内存+本地JSON文件双备份

  • 内存缓存:实时保存最近10次推理记录(防止页面刷新丢失)
  • 磁盘持久化:每次新记录自动追加到/root/yoloe/history.json,关机也不丢
  • 记录内容:原始图片名(哈希ID)、提示词、检测时间、物体列表(含类别、置信度、框坐标、掩码尺寸)、处理耗时

这样既保证响应速度,又确保数据不丢失,还完全符合镜像的离线部署要求。

3.2 修改app.py实现历史记录

打开/root/yoloe/app.py,找到gr.Interface创建部分,在其上方添加以下代码:

import json import time import os from pathlib import Path HISTORY_FILE = "/root/yoloe/history.json" # 初始化历史记录 def load_history(): if os.path.exists(HISTORY_FILE): try: with open(HISTORY_FILE, "r", encoding="utf-8") as f: return json.load(f) except: return [] return [] def save_history(record): history = load_history() history.append(record) # 只保留最近10条 history = history[-10:] with open(HISTORY_FILE, "w", encoding="utf-8") as f: json.dump(history, f, indent=2, ensure_ascii=False) # 全局历史缓存(用于页面内实时显示) history_cache = load_history()

接着,找到原推理函数(通常是run_inference或类似名称),在其返回结果前插入记录逻辑:

# 假设原函数返回值为 result_dict,包含 'boxes', 'masks', 'names', 'confidences' def run_inference(image, text_prompt): # ... 原有推理代码保持不变 ... # 新增:构造历史记录项 record = { "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"), "prompt": text_prompt.strip(), "image_hash": str(hash(image.tobytes()))[:8] if hasattr(image, 'tobytes') else "unknown", "objects": [ { "name": name, "confidence": float(conf), "bbox": [int(x) for x in box] if 'box' in locals() else [] } for name, conf, box in zip(result_dict['names'], result_dict['confidences'], result_dict['boxes']) ], "mask_shape": list(result_dict['masks'].shape) if 'masks' in result_dict else [], "inference_time_ms": int((time.time() - start_time) * 1000) } # 保存到磁盘和内存 save_history(record) history_cache.append(record) return result_dict

3.3 在Gradio界面中展示历史记录

gr.Interface创建之后,添加一个独立的历史面板:

with gr.Blocks() as demo: # 原有界面代码(保持不变)... # 新增:历史记录区域 gr.Markdown("### 📜 最近10次推理记录") history_table = gr.Dataframe( headers=["时间", "提示词", "检测物体数", "耗时(ms)", "图片ID"], datatype=["str", "str", "number", "number", "str"], interactive=False, row_count=(10, "fixed") ) # 刷新按钮 refresh_btn = gr.Button(" 刷新历史") # 绑定刷新逻辑 def refresh_history(): history = load_history() # 格式化为表格数据 table_data = [ [ h["timestamp"], h["prompt"][:30] + "..." if len(h["prompt"]) > 30 else h["prompt"], len(h["objects"]), h["inference_time_ms"], h["image_hash"] ] for h in reversed(history) # 最新在最上 ] return table_data refresh_btn.click(refresh_history, outputs=history_table) # 页面加载时自动刷新一次 demo.load(refresh_history, outputs=history_table)

现在启动python app.py,你会在界面底部看到一个动态更新的历史表格,点击“刷新”即可同步最新记录。

4. 添加导出功能:一键生成结构化结果文件

4.1 导出内容定义

我们支持导出三种格式,覆盖不同下游需求:

格式内容适用场景
JSON完整检测结果:坐标、掩码、类别、置信度、元信息开发者集成、算法评测
CSV表格化物体列表:每行一个检测框,含类别、置信度、x1,y1,x2,y2Excel分析、业务报表
PNG掩码二值分割掩码图(透明背景,物体区域白色)图像标注、视觉验证

所有导出文件自动命名为yoloe_export_时间戳.格式,保存在/root/yoloe/exports/目录下。

4.2 实现导出逻辑

app.py中添加导出函数:

import csv from PIL import Image, ImageDraw, ImageFont import numpy as np EXPORT_DIR = "/root/yoloe/exports" os.makedirs(EXPORT_DIR, exist_ok=True) def export_results(image, text_prompt, result_dict): timestamp = int(time.time()) base_name = f"yoloe_export_{timestamp}" # 1. JSON导出 json_path = os.path.join(EXPORT_DIR, f"{base_name}.json") export_data = { "prompt": text_prompt, "timestamp": time.strftime("%Y-%m-%d %H:%M:%S"), "image_size": list(image.shape[:2]) if hasattr(image, 'shape') else [0, 0], "objects": [] } for i, (name, conf, box, mask) in enumerate(zip( result_dict['names'], result_dict['confidences'], result_dict['boxes'], result_dict['masks'] )): export_data["objects"].append({ "id": i + 1, "class": name, "confidence": float(conf), "bbox": [int(x) for x in box], "mask_shape": list(mask.shape), "mask_sum": int(np.sum(mask)) # 掩码像素总数,便于快速判断 }) with open(json_path, "w", encoding="utf-8") as f: json.dump(export_data, f, indent=2, ensure_ascii=False) # 2. CSV导出 csv_path = os.path.join(EXPORT_DIR, f"{base_name}.csv") with open(csv_path, "w", newline="", encoding="utf-8") as f: writer = csv.writer(f) writer.writerow(["ID", "Class", "Confidence", "X1", "Y1", "X2", "Y2"]) for i, (name, conf, box) in enumerate(zip( result_dict['names'], result_dict['confidences'], result_dict['boxes'] )): writer.writerow([i + 1, name, f"{conf:.3f}", int(box[0]), int(box[1]), int(box[2]), int(box[3])]) # 3. PNG掩码导出(仅取第一个物体掩码作示例,如需全部可扩展) if len(result_dict['masks']) > 0: mask_img = Image.fromarray((result_dict['masks'][0] * 255).astype(np.uint8)) mask_path = os.path.join(EXPORT_DIR, f"{base_name}_mask.png") mask_img.save(mask_path) return json_path, csv_path, mask_path if len(result_dict['masks']) > 0 else ""

4.3 在界面中添加导出组件

gr.Interfaceoutputs参数后,新增三个输出组件,并在按钮区域添加导出按钮:

# 在原有outputs列表中追加 outputs = [ # ... 原有outputs,如 gr.Image(), gr.JSON() 等 ... gr.File(label=" 导出JSON(完整结果)"), gr.File(label=" 导出CSV(物体列表)"), gr.File(label="🖼 导出PNG(首物体掩码)"), ] # 在按钮区域添加 with gr.Row(): export_btn = gr.Button(" 一键导出所有格式", variant="primary") # 绑定导出事件 export_btn.click( fn=export_results, inputs=[input_image, text_prompt_input, *original_outputs], # 注意:需传入原始输出作为输入 outputs=outputs[-3:] # 只更新最后三个File组件 )

注意:export_results函数的输入需与Gradio组件严格对应。若原界面无显式输出组件变量,可将run_inference改为返回元组,并在gr.Interface中明确声明outputs类型。

5. 定制后效果实测与使用技巧

5.1 实际操作流程演示

以一张街景图bus.jpg为例,输入提示词person, bus, traffic light

  1. 上传图片→ 选择ultralytics/assets/bus.jpg

  2. 输入提示person, bus, traffic light

  3. 点击运行→ 界面右侧显示带分割掩码的检测结果

  4. 查看历史→ 底部表格自动新增一行,显示“2025-04-12 14:22:05 | person, bus... | 3 | 428 | 9a3b1c7d”

  5. 导出结果→ 点击“一键导出”,三秒后弹出下载链接,点击即可获取:

    • yoloe_export_1744467725.json:含所有物体的坐标、掩码形状、置信度
    • yoloe_export_1744467725.csv:Excel可直接打开的表格
    • yoloe_export_1744467725_mask.png:首物体(person)的纯白掩码图

5.2 高效使用小技巧

  • 快速复现历史:复制历史表格中的提示词,粘贴到输入框,换图即测
  • 批量导出管理:所有文件存于/root/yoloe/exports/,可用ls -lt /root/yoloe/exports/按时间排序查看
  • 清理历史:手动删除/root/yoloe/history.json即可清空(下次运行自动重建)
  • 调整保存数量:修改save_history函数中的history[-10:][-20:]即可存20条

6. 总结:小改动带来大价值

这次对YOLOE官版镜像的Gradio定制,没有改动一行模型代码,没有引入新依赖,却实实在在解决了三个高频痛点:

  • 不再凭记忆调试:历史记录让每次提示词尝试都有据可查,告别“我刚才输的是什么?”
  • 无缝对接下游:JSON/CVS/PNG三格式导出,让检测结果能直接喂给标注平台、BI系统或训练流水线
  • 零学习成本上手:所有功能都集成在原界面,老用户无需适应新操作,新用户看一眼就会用

更重要的是,这套方案是可复用的模式——你完全可以把它迁移到YOLOE-v8s-seg、YOLOE-v8m-seg,甚至其他基于Gradio的AI镜像上。只需要替换对应的推理函数名和结果字段名,5分钟就能完成同类定制。

技术的价值不在于多炫酷,而在于多实在。当你不用再手动截图、不用再复制粘贴坐标、不用再写临时脚本导出数据时,那才是工具真正长出了牙齿。


获取更多AI镜像

想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。

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

一键启动Qwen3Guard-Gen-WEB,网页推理零配置搞定审核任务

一键启动Qwen3Guard-Gen-WEB,网页推理零配置搞定审核任务 你是否经历过这样的场景:刚部署好一个AI应用,正准备测试内容安全能力,却卡在了模型加载、API服务配置、前端联调这一连串繁琐步骤上?命令行里反复调试端口冲突…

作者头像 李华
网站建设 2026/4/18 9:40:13

AI辅助开发实战:如何用Command Prompt提升开发效率

背景痛点:传统 Command Prompt 的“四堵墙” 日常开发中,Command Prompt(cmd.exe)依旧是最低成本的“万能入口”:拉代码、起容器、跑测试脚本,一键直达。但用久了,你会发现它像一间没窗的仓库—…

作者头像 李华
网站建设 2026/4/18 8:37:17

2026年适合计算机本科大学生的难度适中、有创新点且易通过的毕业设计选题推荐:实战导向与技术落地指南

2026年适合计算机本科大学生的难度适中、有创新点且易通过的毕业设计选题推荐:实战导向与技术落地指南 摘要:面对毕业设计选题难、创新不足、实现复杂度高三大痛点,本文聚焦实战应用,精选多个2026年适合计算机本科生的毕业设计方向…

作者头像 李华
网站建设 2026/4/18 1:43:32

一看就会!Qwen2.5-7B自我认知微调操作指南

一看就会!Qwen2.5-7B自我认知微调操作指南 1. 这不是“调参”,是给模型换身份——为什么微调自我认知特别适合新手 你有没有试过问一个大模型:“你是谁?” 它老老实实回答:“我是阿里云研发的通义千问……” 但你想让…

作者头像 李华
网站建设 2026/4/18 8:50:03

Z-Image-Turbo效果展示:这AI画的像真人拍摄?

Z-Image-Turbo效果展示:这AI画的像真人拍摄? 你有没有试过输入一段文字,几秒钟后,一张堪比专业摄影师棚拍的照片就出现在屏幕上?不是那种带点“AI味”的生硬感,而是皮肤纹理自然、光影过渡柔和、连发丝都带…

作者头像 李华