尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

YOLOv5乐谱识别实战:数据集构建与训练全流程

发布时间:2026/9/29 18:07:12

资讯中心
01
ARTICLE

YOLOv5乐谱识别实战:数据集构建与训练全流程

YOLOv5乐谱识别实战:数据集构建与训练全流程
简介这份资源面向深度学习入门与计算机视觉实践者提供一套基于YOLOv5的乐谱识别模型训练数据集可用于目标检测练手、乐谱元素定位等场景。压缩包共329个文件约37MB其中162张jpg图像与154个xml标注文件构成核心训练数据xml记录乐谱元素边界框另有6张png、3个yaml配置文件、2个pt权重文件及csv训练日志覆盖数据、配置与训练结果。已有338人学习下载。借助该数据集读者可完成图像增强、标签解析与格式转换结合PyTorch的Dataset与DataLoader搭建训练流程并参考yaml参数与pt权重复现或微调模型理解从数据准备到推理输出的完整链路适合作为乐谱识别项目的起步素材。1. 乐谱识别为什么要用 YOLOv5 做数据集一份能直接开训的工程包如果你手头有一堆扫描版或拍照的乐谱想把五线谱、音符、谱号、小节线这些元素自动框出来第一道坎往往不是模型结构而是数据集。乐谱图像和常规 COCO 类数据差别很大背景几乎全是白纸黑线目标密集、尺寸小、长宽比极端音符之间还经常粘连。用通用检测数据集训出来的权重直接推理召回率会低得让人怀疑人生。这份资源就是围绕这个场景整理的一套 YOLOv5 训练数据集与配套流程标签格式是 YOLO 的 txt目录结构按 images/labels 划分可以直接接进 YOLOv5 的训练脚本。它适合两类人一是想快速跑通乐谱目标检测、验证自己标注方案是否合理的算法工程师二是手里已经有乐谱图片、需要一套可复现的标注与训练范式的从业者。下面从数据组织、环境配置、训练参数到推理后处理把这条链路拆开讲清楚坑在哪儿也一并标出来。2. 数据集结构与 YOLOv5 目录约定先对齐格式再谈训练2.1 乐谱数据的类别设计与标注粒度乐谱识别不是单一目标检测任务它至少包含几类差异很大的元素。常见做法是把类别拆成谱号、调号、拍号、音符、休止符、小节线、连音线这几类但类别一多小目标样本就会被稀释。我一般建议第一版先收敛到四到五类谱号、音符含符头符干、休止符、小节线。原因是 YOLOv5 的 anchor 在极端长宽比目标上本身就不占优势类别越细每一类可分到的正样本越少训练时容易在稀有类上震荡。标注粒度上有个反直觉的点音符不要只框符头。只框符头会让模型学到一堆几像素的小方块mAP 看着还行实际后处理拼乐谱时完全没法用。正确做法是框住符头加符干的整体外接矩形让框具备方向信息。小节线这种细长目标框的宽度可能只有两三个像素标注时要把线两端各留一点余量否则增强裁剪后容易整条丢失。这份数据集的标签是标准 YOLO 格式每行class_id x_center y_center width height坐标全部归一化到 0 到 1。如果你拿到的原始标注是 LabelImg 的 XML 或 COCO json需要先转成这个格式转换脚本在下一节给。2.2 目录树与 data.yaml 的对应关系YOLOv5 对目录结构有硬性约定很多人第一次训练失败不是代码问题而是路径没对上。推荐的结构如下sheet_dataset/ ├── images/ │ ├── train/ │ └── val/ ├── labels/ │ ├── train/ │ └── val/ └── data.yaml注意 images 和 labels 是平级目录不是嵌套。YOLOv5 在加载时会用images替换成labels再替换后缀去找标签文件所以 train 和 val 的子目录名必须完全一致。data.yaml 写法# 乐谱检测数据集配置 path: /data/sheet_dataset # 数据集根目录绝对路径最稳 train: images/train # 相对 path 的训练图目录 val: images/val # 相对 path 的验证图目录 nc: 5 # 类别数必须和标签里的 class_id 最大值1 一致 names: [clef, note, rest, barline, slur]这里nc和names长度必须相等且 class_id 从 0 开始连续。我见过有人标签里出现 class_id 为 5 但 nc 写 4训练不报错但那一类永远学不到属于典型的黑匣子式翻车。2.3 从 XML/COCO 转 YOLO 格式的脚本如果你手里是 LabelImg 的 XML用下面这段转换逻辑是读 XML 的 bndbox做归一化再按图片名写到 labels 对应目录。import os import xml.etree.ElementTree as ET from PIL import Image # 类别名到 id 的映射顺序要和 data.yaml 的 names 完全一致 CLASS_MAP {clef: 0, note: 1, rest: 2, barline: 3, slur: 4} def convert(xml_dir, img_dir, out_dir): os.makedirs(out_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue tree ET.parse(os.path.join(xml_dir, xml_file)) root tree.getroot() # 用对应图片的真实宽高做归一化不能凭经验写死 img_name root.find(filename).text img_path os.path.join(img_dir, img_name) w, h Image.open(img_path).size lines [] for obj in root.iter(object): name obj.find(name).text if name not in CLASS_MAP: continue bbox obj.find(bndbox) x1 float(bbox.find(xmin).text) y1 float(bbox.find(ymin).text) x2 float(bbox.find(xmax).text) y2 float(bbox.find(ymax).text) # 转成中心点加宽高的归一化格式 cx (x1 x2) / 2.0 / w cy (y1 y2) / 2.0 / h bw (x2 - x1) / w bh (y2 - y1) / h lines.append(f{CLASS_MAP[name]} {cx:.6f} {cy:.6f} {bw:.6f} {bh:.6f}) out_file os.path.join(out_dir, xml_file.replace(.xml, .txt)) with open(out_file, w) as f: f.write(\n.join(lines)) convert(./annotations, ./images, ./labels/train)参数说明CLASS_MAP必须和 data.yaml 的 names 顺序严格一致错一位整个数据集就废了归一化用的是每张图自己的宽高不能用统一尺寸否则不同分辨率扫描件会错位。转换完建议随机抽十张用可视化脚本画框检查一遍别直接开训。3. 环境配置与训练启动conda 隔离、超参数与断点续训3.1 conda 环境与依赖版本YOLOv5 对 PyTorch 和 CUDA 的版本比较敏感尤其是你要用 GPU 训练时。常见做法是建一个独立 conda 环境避免和系统里的其他 torch 版本打架。conda create -n sheet_yolo python3.9 -y conda activate sheet_yolo # 按你的 CUDA 版本装 torch这里以 cu118 为例 pip install torch2.0.1 torchvision0.15.2 --index-url https://download.pytorch.org/whl/cu118 git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt装完先跑一句python -c import torch; print(torch.cuda.is_available())返回 True 才算 GPU 可用。如果返回 False八成是 CUDA 版本和 torch 不匹配别急着改代码先解决环境。3.2 训练命令与关键超参数启动训练的核心命令不复杂难的是参数怎么设。乐谱数据的目标普遍偏小输入尺寸和 anchor 是两个关键点。python train.py \ --data /data/sheet_dataset/data.yaml \ --weights yolov5s.pt \ --img 1280 \ --batch-size 8 \ --epochs 200 \ --hyp data/hyps/hyp.scratch-low.yaml \ --cache ram \ --device 0 \ --project runs/sheet \ --name exp1逐项说明--img 1280是因为乐谱里音符很小640 下采样后可能只剩几个像素1280 能明显提升小目标召回代价是显存翻倍batch 要相应调小--weights yolov5s.pt用预训练权重做迁移比从头训收敛快很多--hyp选 low 增强配置乐谱图像本身纹理单一过强的色彩抖动和旋转反而会引入噪声--cache ram在数据集不大时能显著加速但内存要够图多的时候会 OOM。如果显存吃紧把--img降到 1024或者用--batch-size 4配合梯度累积。别硬扛OOM 报错后进程直接挂掉白等。3.3 断点续训与训练日志判读训练中断是常态YOLOv5 支持从 last.pt 续训python train.py \ --data /data/sheet_dataset/data.yaml \ --weights runs/sheet/exp1/weights/last.pt \ --resume--resume会恢复优化器状态和 epoch 计数比重新加载权重再训要正确得多。日志里重点看三个指标box_loss、obj_loss 和 mAP0.5。乐谱场景下 obj_loss 如果一直不降通常是标签里有大量空 txt 或者框坐标越界mAP 卡在某个值不动先检查验证集里是不是有类别根本没出现。提示训练前用python utils/autoanchor.py重新聚类一遍 anchor乐谱的极端长宽比和 COCO 差很远默认 anchor 不一定合适。4. 推理、后处理与乐谱结构化从检测框到可读谱面4.1 推理脚本与置信度阈值训练完拿 best.pt 推理最简方式是用 detect.pypython detect.py \ --weights runs/sheet/exp1/weights/best.pt \ --source /data/test_sheets \ --img 1280 \ --conf-thres 0.35 \ --iou-thres 0.5 \ --save-txt \ --project runs/detect--conf-thres 0.35比默认 0.25 高是因为乐谱背景干净低置信度框大多是噪声--iou-thres 0.5控制 NMS 合并音符密集时这个值不能太低否则相邻音符会被误合并。--save-txt会把框坐标存下来方便后续做结构化。4.2 后处理把检测框还原成谱面顺序检测框本身没有顺序信息要还原成可读乐谱需要按坐标排序。常见做法是先按 y 坐标分行再在每行内按 x 排序。import numpy as np def sort_boxes(boxes, row_thresh30): # boxes: [[x1,y1,x2,y2,cls,conf], ...] boxes sorted(boxes, keylambda b: b[1]) # 先按 y 排 rows, cur [], [boxes[0]] for b in boxes[1:]: # y 中心差小于阈值认为在同一行 if abs((b[1]b[3])/2 - (cur[-1][1]cur[-1][3])/2) row_thresh: cur.append(b) else: rows.append(sorted(cur, keylambda x: x[0])) cur [b] rows.append(sorted(cur, keylambda x: x[0])) return rowsrow_thresh要根据谱面行距调太小会把同一行拆开太大会把相邻行合并。这个参数没有通用值得拿几张典型图试出来。4.3 常见误检与阈值调优乐谱里最容易误检的是连音线和符干两者都是细长目标模型容易混。如果发现某类误检特别多两个方向一是补该类负样本把容易混淆的区域标成背景二是在推理时对这类单独调高 conf 阈值。YOLOv5 的 detect.py 不支持分类别阈值需要自己改 NMS 部分按 class 过滤。5. 避坑与排查乐谱数据集训练里最容易翻车的五件事现象一训练 loss 正常下降但 mAP 一直是 0。原因标签 class_id 和 data.yaml 的 names 顺序对不上或者标签文件路径没被正确索引。解决写个脚本遍历 labels 目录统计每个 class_id 出现次数和 names 对照再确认 images 和 labels 子目录名完全一致。现象二小音符几乎全漏检。原因输入尺寸太小或者 anchor 尺寸偏大。解决把--img提到 1280跑一遍 autoanchor 重新聚类如果还不行检查标注时音符框是不是只框了符头。现象三验证集 mAP 很高实际推理一塌糊涂。原因训练集和验证集来自同一批扫描件分布太接近模型过拟合了纸张和扫描噪声。解决验证集要留出不同来源、不同分辨率的图别随机切分。现象四训练中途 OOM 或进程被杀。原因--cache ram加上大 img 尺寸吃满内存。解决去掉 cache 或改成--cache disk降低 batch-size或者用多卡。现象五推理框大量重叠同一音符出好几个框。原因NMS 的 iou-thres 设太高或者模型没收敛。解决把 iou-thres 降到 0.4 到 0.45 之间试同时确认训练 epoch 够不够。6. 进阶技巧用切片推理和类别重映射把召回再拉一截乐谱图像有个特点整张图分辨率很高但目标很小直接缩放到 1280 会丢细节。我后来固定用切片推理把大图切成带重叠的小块每块单独推理再按坐标拼回去。YOLOv5 本身不带这个功能需要自己写切图逻辑核心是控制重叠比例一般取块尺寸的 20% 到 30%太低会切断目标太高会重复检测。def slice_infer(img, model, size1280, overlap0.25): h, w img.shape[:2] step int(size * (1 - overlap)) results [] for y in range(0, h, step): for x in range(0, w, step): patch img[y:ysize, x:xsize] # 边缘补零到 size避免最后一块尺寸不足 pred model(patch) # 把 patch 内坐标加回全局偏移 for box in pred: box[:4] [x, y, x, y] results.append(box) return results另一个技巧是类别重映射。第一版训练时我把连音线和符干分成两类结果两类互相误检严重。后来合并成一类“线条”召回立刻上去了结构化阶段再用几何规则区分。这说明在乐谱这种目标形态接近的场景里类别设计要服务于后处理不是越细越好。还有个验证习惯每次改完数据或参数先拿十张典型图跑一遍可视化肉眼看框对不对再去看 mAP。指标会骗人图不会。从那以后我每次动数据集或 anchor都强制先过一遍这十张图的肉眼检查再开长训练。希望帮到你。本文还有配套的精品资源点击获取
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。