跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
PythonAI算法

基于改进 YOLOv8 的美食图像分割系统与训练部署实战

基于改进 YOLOv8 的美食图像分割系统利用 3800 张包含 136 类美食的数据集进行训练。项目涵盖实时检测、Web 端部署及模型训练全流程。核心实现包括使用 MD5 哈希生成稳定类别颜色、OpenCV 实时视频流处理以及 Ultralytics 框架下的姿态估计与分割训练逻辑。通过优化数据路径配置与损失函数计算,系统实现了高精度的目标识别与分割,适用于餐饮分析、营养评估等场景。

SecGuard发布于 2026/4/8更新于 2026/10/2581 浏览
基于改进 YOLOv8 的美食图像分割系统与训练部署实战

背景与意义

随着计算机视觉技术的深入,图像分割在餐饮行业、食品安全监测及营养分析等领域的应用价值日益凸显。YOLO(You Only Look Once)系列模型凭借其高效的实时检测能力,成为该领域的热门选择。特别是 YOLOv8 的推出,进一步提升了复杂场景下的表现。

本研究旨在构建一个基于改进 YOLOv8 的美食图像分割系统。通过精确分割美食图像,不仅能实现自动识别,还能为后续的营养分析、热量计算和个性化推荐提供数据支持。此外,该技术还能提升美食内容的可读性,助力餐饮企业的品牌推广。

数据集说明

本项目使用的数据集名为'food',包含 3800 张图像,涵盖 136 种不同类别的美食,如主菜、配菜、调料等。丰富的类别设置(包括青柠、加拿大龙虾、各类披萨、汉堡包等)为模型提供了充足的训练样本,帮助其学习在不同光照、角度和背景下准确识别目标。

为了确保模型的泛化能力,图像来源涵盖了不同的烹饪风格和文化背景。每一张图像都经过精心挑选和标注,保证了训练数据的高质量,为改进 YOLOv8-seg 模型奠定了坚实基础。

[图:美食分割效果展示]

核心实现

运行脚本封装

为了简化 Streamlit 应用的启动过程,我们编写了一个 Python 脚本作为入口。它利用 subprocess 模块调用当前环境中的 Python 解释器来运行主程序,并处理路径问题。

import sys
import subprocess
from QtFusion.path import abs_path

def run_script(script_path):
    """
    使用当前 Python 环境运行指定的脚本。
    Args:
        script_path (str): 要运行的脚本路径
    """
    # 获取当前 Python 解释器的路径
    python_path = sys.executable
    # 构建运行命令,使用 streamlit 运行指定的脚本
    command = f'"{python_path}" -m streamlit run "{script_path}"'
    # 执行命令并等待其完成
    result = subprocess.run(command, shell=True)
    # 检查命令执行的返回码,非零表示出错
    if result.returncode != 0:
        print("脚本运行出错。")

if __name__ == "__main__":
    # 获取脚本的绝对路径
    script_path = abs_path("web.py")
    # 运行指定的脚本
    run_script(script_path)

这段代码的核心在于动态获取 Python 解释器路径并构建命令,确保在不同环境下都能正确启动 Web 服务。同时增加了错误码检查,方便排查启动失败的原因。

实时视频流处理

在实时检测场景中,我们需要处理摄像头输入的视频流,并在每一帧上绘制检测结果。这里有一个细节值得注意:为了让同一类别始终显示相同的颜色,我们使用了 MD5 哈希算法生成稳定的颜色值。

import cv2
import numpy as np
from PIL import ImageFont, ImageDraw, Image
from hashlib import md5
from model import Web_Detector
from chinese_name_list import Label_list

def generate_color_based_on_name(name):
    # 使用哈希函数生成稳定的颜色
    hash_object = md5(name.encode())
    hex_color = hash_object.hexdigest()[:6]
    r, g, b = int(hex_color[0:2], 16), int(hex_color[2:4], 16), int(hex_color[4:6], 16)
    return (b, g, r)  # OpenCV 使用 BGR 格式

def draw_with_chinese(image, text, position, font_size=20, color=(255, 0, 0)):
    image_pil = Image.fromarray(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
    draw = ImageDraw.Draw(image_pil)
    font = ImageFont.truetype("simsun.ttc", font_size, encoding="unic")
    draw.text(position, text, font=font, fill=color)
    return cv2.cvtColor(np.array(image_pil), cv2.COLOR_RGB2BGR)

def draw_detections(image, info):
    name, bbox = info['class_name'], info['bbox']
    x1, y1, x2, y2 = bbox
    cv2.rectangle(image, (x1, y1), (x2, y2), color=(0, 0, 255), thickness=3)
    image = draw_with_chinese(image, name, (x1, y1 - 10), font_size=20)
    return image

def process_frame(model, image):
    pre_img = model.preprocess(image)
    pred = model.predict(pre_img)
    det = pred[0]
    if det is not None and len(det):
        det_info = model.postprocess(pred)
        for info in det_info:
            image = draw_detections(image, info)
    return image

if __name__ == "__main__":
    model = Web_Detector()
    model.load_model("./weights/yolov8s-seg.pt")
    cap = cv2.VideoCapture(0)
    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break
        processed_frame = process_frame(model, frame)
        cv2.imshow('Camera Feed', processed_frame)
        if cv2.waitKey(1) & 0xFF == ord('q'):
            break
    cap.release()
    cv2.destroyAllWindows()

主程序初始化模型后打开摄像头,进入循环读取帧。process_frame 负责预处理、预测和后处理,最后将结果绘制回原图。按 'q' 键即可退出并释放资源。

模型训练配置

训练脚本需要灵活配置设备、批次大小以及数据路径。为了避免硬编码路径导致跨平台运行困难,我们在加载前动态解析 YAML 配置文件。

import os
import torch
import yaml
from ultralytics import YOLO

if __name__ == '__main__':
    workers = 1
    batch = 8
    device = "0" if torch.cuda.is_available() else "cpu"
    
    # 获取数据集配置文件的绝对路径
    data_path = "datasets/data/data.yaml"  # 请根据实际路径调整
    
    with open(data_path, 'r', encoding='utf-8') as file:
        data = yaml.safe_load(file)
    
    # 修改数据集路径为相对路径或当前目录路径
    directory_path = os.path.dirname(data_path)
    if 'train' in data and 'val' in data and 'test' in data:
        data['train'] = directory_path + '/train'
        data['val'] = directory_path + '/val'
        data['test'] = directory_path + '/test'
    
    with open(data_path, 'w', encoding='utf-8') as file:
        yaml.dump(data, file, allow_unicode=True)
    
    # 加载 YOLO 模型配置和预训练权重
    model = YOLO("./config/yolov8-seg.yaml").load("./weights/yolov8s-seg.pt")
    
    results = model.train(
        data=data_path,
        device=device,
        workers=workers,
        imgsz=640,
        epochs=100,
        batch=batch
    )

这里特别处理了 YAML 文件中的路径,确保训练时能正确找到数据集。同时,根据 GPU 可用性自动切换设备,避免显存溢出。

跟踪与匹配逻辑

在目标跟踪任务中,线性分配算法用于将检测框与现有轨迹进行匹配。我们实现了基于 IoU 和特征嵌入的距离计算,以优化匹配精度。

import numpy as np
from scipy.spatial.distance import cdist
from ultralytics.utils.metrics import bbox_ioa

try:
    import lap
    assert lap.__version__
except (ImportError, AssertionError, AttributeError):
    from ultralytics.utils.checks import check_requirements
    check_requirements('lapx>=0.5.2')
import lap

def linear_assignment(cost_matrix, thresh, use_lap=True):
    if cost_matrix.size == 0:
        return np.empty((0, 2), dtype=int), tuple(range(cost_matrix.shape[0])), tuple(range(cost_matrix.shape[1]))
    if use_lap:
        _, x, y = lap.lapjv(cost_matrix, extend_cost=True, cost_limit=thresh)
        matches = [[ix, mx] for ix, mx in enumerate(x) if mx >= 0]
        unmatched_a = np.where(x < 0)[0]
        unmatched_b = np.where(y < 0)[0]
    else:
        x, y = scipy.optimize.linear_sum_assignment(cost_matrix)
        matches = np.asarray([[x[i], y[i]] for i in range(len(x)) if cost_matrix[x[i], y[i]] <= thresh])
        if len(matches) == 0:
            unmatched_a = list(np.arange(cost_matrix.shape[0]))
            unmatched_b = list(np.arange(cost_matrix.shape[1]))
        else:
            unmatched_a = list(set(np.arange(cost_matrix.shape[0])) - set(matches[:, 0]))
            unmatched_b = list(set(np.arange(cost_matrix.shape[1])) - set(matches[:, 1]))
    return matches, unmatched_a, unmatched_b

def iou_distance(atracks, btracks):
    if (len(atracks) > 0 and isinstance(atracks[0], np.ndarray)) or (len(btracks) > 0 and isinstance(btracks[0], np.ndarray)):
        atlbrs = atracks
        btlbrs = btracks
    else:
        atlbrs = [track.tlbr for track in atracks]
        btlbrs = [track.tlbr for track in btracks]
    ious = np.zeros((len(atlbrs), len(btlbrs)), dtype=np.float32)
    if len(atlbrs) and len(btlbrs):
        ious = bbox_ioa(np.ascontiguousarray(atlbrs, dtype=np.float32), np.ascontiguousarray(btlbrs, dtype=np.float32), iou=True)
    return 1 - ious

这部分代码是跟踪系统的底层支撑,通过成本矩阵最小化来实现最优匹配,结合 IoU 和外观特征能有效减少 ID 切换。

总结

本系统整合了从数据准备、模型训练到实时推理的全流程。通过改进 YOLOv8 架构并结合实用的工程优化,实现了高效的美食图像分割。在实际部署中,建议根据硬件资源调整 batch size 和 workers 数量,并注意字体文件的兼容性以确保中文正常显示。

目录

  1. 背景与意义
  2. 数据集说明
  3. 核心实现
  4. 运行脚本封装
  5. 实时视频流处理
  6. 模型训练配置
  7. 跟踪与匹配逻辑
  8. 总结

更多推荐文章

查看全部
  • Web 团队开发 App 是否适合选择 Capacitor
  • ERNIE-4.5-0.3B:文心一言轻量级大模型的产业落地实践
  • Vue3 + PlayCanvas 实战:3D 地图自由巡视与多关卡闯关系统
  • Ubuntu 部署 OpenClaw 完整教程
  • C++ 初步学习(需 C 语言基础)
  • 行星减速器原理、减速比计算及 C++ 实现
  • 如何为 Llama 系列模型定制专属 TensorRT 优化方案?
  • 配置钉钉 OpenClaw 机器人调用 OpenMetadata
  • KIMI 与文心一言、通义千问大模型能力对比评测
  • Noname:开源三国杀游戏平台完全指南
  • VsCode 插件开发实战:实现 Git 代码自动提交推送
  • Python 基础与环境配置
  • SAP 对接钉钉 Webhook 实现方案及证书问题排查
  • FPGA 加速图像处理:核心算法全解析
  • ManiSkill 机器人模拟环境安装与使用指南
  • Spring Boot 定时任务与调度系统
  • FPGA FIR 滤波器设计中的时序艺术:从使能打拍到流水线优化
  • WebPShop 插件:Photoshop 处理 WebP 格式的完整指南
  • 前端 AI 应用:浏览器中的机器学习模型
  • Cosmos-Reason1-7B 实战:工业巡检中设备异常动作识别与推理

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • curl 转代码

    解析常见 curl 参数并生成 fetch、axios、PHP curl 或 Python requests 示例代码。 在线工具,curl 转代码在线工具,online