news 2026/3/16 11:24:11

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/3/13 5:44:04

Amazon Connect 智能客服 AI 辅助开发实战:从架构设计到避坑指南

背景:传统客服配置的三座大山 去年公司把 400 路热线全部迁到 Amazon Connect,本以为能“一键上云”,结果客服同学每天都在画流程图。总结下来,最痛的三个点: 动态意图处理难——“我要改收货地址”和“我要查物流”…

作者头像 李华
网站建设 2026/3/16 2:59:38

Gradio Chatbot 颜色定制指南:从基础配置到高级主题适配

痛点::为什么“白底灰泡”总显得不够“我” 第一次把 Gradio Chatbot 拖到客户面前,对方只回了一句:“界面挺干净,就是不像我们家的产品。” 默认配色只有浅灰气泡 深灰文字,品牌主色、暗黑模式、无障碍对…

作者头像 李华
网站建设 2026/3/13 2:28:25

Glyph在教育领域的应用:帮助学生理解复杂图表

Glyph在教育领域的应用:帮助学生理解复杂图表 教育场景中,学生面对统计图表、科学示意图、数学函数图像、化学分子结构图或历史时间轴时,常常陷入“看得见却看不懂”的困境。传统教学依赖教师逐项讲解,但受限于课堂时间与个体差异…

作者头像 李华
网站建设 2026/3/11 7:35:37

重构我的世界光影体验:Photon-GAMS带来电影级视觉革新

重构我的世界光影体验:Photon-GAMS带来电影级视觉革新 【免费下载链接】Photon-GAMS Personal fork of Photon shaders 项目地址: https://gitcode.com/gh_mirrors/ph/Photon-GAMS 你是否厌倦了Minecraft中平淡无奇的方块世界?是否渴望让像素建筑…

作者头像 李华
网站建设 2026/3/13 1:40:13

MGeo结合Airflow调度,批量任务自动化

MGeo结合Airflow调度,批量任务自动化 在地址数据治理实践中,单次推理只是起点,真正考验工程能力的是高频、多源、大规模的地址对齐任务。物流订单清洗、政务地址归一化、POI库跨平台合并——这些场景往往涉及数万至百万级地址对的批量比对&a…

作者头像 李华