ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

YOLO实战:615张带标签图像实现鸡蛋品质分级全流程

YOLO实战:615张带标签图像实现鸡蛋品质分级全流程 简介面向YOLO系列算法目标检测的鸡蛋品质分级数据集含615张实拍标注图像覆盖血染鸡蛋、棕色鸡蛋、脏兮兮鸡蛋、白鸡蛋、钙沉积蛋等外观类型适合目标检测学习者、研究者和农业质检项目开发者用于模型训练与验证。包内共1846个文件除615张jpg原图外还提供615个YOLO格式txt标注和615个VOC格式xml标注并附数据配置文件data.yamlYOLO格式按类别索引、归一化中心点坐标和宽高记录目标框VOC格式可直接配合LabelImg等工具复核两种格式均已按训练/验证/测试划分适配YOLOv5、YOLOv7、YOLOv8、YOLOv9、YOLOv10、YOLO11等版本。压缩包整体约25.41MB目前已有104人学习。借助这份数据可快速开展蛋品外观缺陷检测实验、毕业设计或农产品自动化分拣原型验证节省数据采集与手工标注时间也能直观对比不同YOLO系列模型在血染、脏污、钙沉积等复杂外观上的识别效果。1. 一枚脏鸡蛋就能让分拣线跳闸YOLO算法做鸡蛋品质分级到底值不值YOLO算法做鸡蛋品质分级听起来像杀鸡用牛刀但我见过不少分拣现场真正卡壳的却是那枚脏兮兮的鸡蛋——它和棕色鸡蛋在普通RGB图像里实在太像了。这个615张图像带标签的鸡蛋品质分级数据集正好覆盖血染鸡蛋、棕色鸡蛋、脏兮兮的鸡蛋、白鸡蛋、钙沉积蛋五类典型样本是YOLO目标检测最合适的动手样本类别少、目标小、背景杂、标签质量直接决定模型上限。它适合两类人一是想用YOLOv8/YOLOv5训练自己数据集的新手需要一份能快速跑通全流程的带标签图像集二是做禽蛋分级设备选型的人先评估检测方案能否把钙沉积和脏污分开。2. 拆开ZIP先摸清家底615张图像的标签结构、类别分布与YOLO格式转换拿到标题里这个zip别急着训练。先解压把目录和标注格式看清楚否则后面每一步都在给自己埋雷。常见做法是images目录里放原图labels目录里放同名txt也有的包会把标注做成VOC的xml或COCO的json。先讲清楚五类标签怎么定义再讲怎么把它整理成YOLO能直接吃的格式。2.1 五类鸡蛋标签分别长什么样血染、棕色、脏兮兮、白色、钙沉积的判定边界五类鸡蛋在图像上并不是天然可分的。棕色鸡蛋和脏兮兮鸡蛋在低照度下几乎同色血染鸡蛋和钙沉积蛋都是表面斑块白鸡蛋则很容易被高光过曝洗掉边缘。标注者通常按整颗蛋的外壳整体外观给框而不是标缺陷区域。这意味着你的检测框会包含整颗蛋类别是蛋的属性不是局部瑕疵的类别。类别典型视觉特征最容易混的类别标注建议血染鸡蛋壳面有暗红/褐色血迹常呈片状脏兮兮鸡蛋、钙沉积蛋框整蛋血迹面积大也按整蛋给框棕色鸡蛋均匀褐壳无明显附着物脏兮兮鸡蛋只要表面干净就归棕色脏兮兮的鸡蛋泥点、鸡粪、羽毛附着边缘不光滑棕色鸡蛋、血染鸡蛋附着物超过10%再归脏兮兮白鸡蛋白壳高光容易过曝钙沉积蛋白底白斑框紧贴蛋缘别留大片背景钙沉积蛋壳面有白色钙质凸起/粗糙斑白鸡蛋斑块立体感强和白蛋的区别在于表面不平这个判定边界直接决定类别间的混淆矩阵。如果标注时把表面沾了一点泥的棕色蛋都归为脏兮兮模型会对棕色蛋产生偏见反过来钙沉积蛋只在某个光照角度下明显时模型学到的就不是钙沉积而是那个角度下的高光。很多公开数据集的翻车现场问题不是网络不够深而是标签从一开始就没立好标准。2.2 从ZIP目录到YOLO训练集目录组织、txt标签格式与train/val划分脚本YOLO系列v5/v8训练时默认找images目录和同名的labels目录label文件名与原图文件名一致只是扩展名换成.txt。每个txt文件里一行代表一个目标class_id x_center y_center width height四个坐标都是归一化到0~1的相对值x_center和y_center是框中心点在图像上的比例width和height是框宽高占图像宽高的比例。归一化让不同分辨率的图像可以混着训练。有些人会误把坐标写成像素值训练时loss直接爆炸——这是新手最容易犯的错。下面这个脚本把zip解压后的原始目录假设叫raw_images标注在labels_raw按7:2:1划分成train/val/test并把文件复制到标准目录结构里。import os import random import shutil random.seed(42) # 固定随机种子保证多次运行划分一致 src_images raw_images src_labels labels_raw out_root egg_data # 目标目录结构 # egg_data/images/train egg_data/images/val egg_data/images/test # egg_data/labels/train egg_data/labels/val egg_data/labels/test for split in [train, val, test]: os.makedirs(os.path.join(out_root, images, split), exist_okTrue) os.makedirs(os.path.join(out_root, labels, split), exist_okTrue) files [f for f in os.listdir(src_images) if f.lower().endswith((.jpg, .jpeg, .png))] random.shuffle(files) n len(files) n_train int(n * 0.7) n_val int(n * 0.2) for i, fname in enumerate(files): if i n_train: split train elif i n_train n_val: split val else: split test base os.path.splitext(fname)[0] src_img os.path.join(src_images, fname) src_lab os.path.join(src_labels, base .txt) if not os.path.exists(src_lab): print(f[跳过] {fname} 没有对应标签 {base}.txt) continue shutil.copy(src_img, os.path.join(out_root, images, split, fname)) shutil.copy(src_lab, os.path.join(out_root, labels, split, base .txt)) print(f划分完成train{n_train}, val{n_val}, test{n - n_train - n_val})这段代码有三个地方要按实际包改一是src_labels里的标注若叫“血染鸡蛋_001.txt”只要基名和原图一致脚本就能对应二是如果你的图不止jpg一种后缀下面的后缀列表要多补webp/bmp三是random.seed(42)必须固定否则每次跑出来的训练集和验证集不同实验结果没法复现。划分时还可以顺手统计每个split的类别数量如果某个类别在test里只有3张后期看混淆矩阵会非常抖宁可手动把它挪到train里去。2.3 从VOC/COCO标注转向YOLOXML/JSON转txt的字段对齐与归一化有的数据集包不给YOLO格式给的是VOC的XML或者COCO的JSON。COCO2017数据集结构是images、annotations、categories三个字段但鸡蛋这个场景常见的是VOC。VOC的XML里每个object有name和bndboxbndbox给的是xmin、ymin、xmax、ymax像素坐标转成YOLO时要先换算。import os import xml.etree.ElementTree as ET def voc_to_yolo(xml_path, out_txt, class_map): tree ET.parse(xml_path) root tree.getroot() width int(root.find(size/width).text) height int(root.find(size/height).text) lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_map: print(f[跳过] 类别 {name} 不在 class_map 中) continue bnd obj.find(bndbox) xmin float(bnd.find(xmin).text) ymin float(bnd.find(ymin).text) xmax float(bnd.find(xmax).text) ymax float(bnd.find(ymax).text) # 像素坐标转归一化YOLO坐标 x_center (xmin xmax) / 2 / width y_center (ymin ymax) / 2 / height w (xmax - xmin) / width h (ymax - ymin) / height cls_id class_map[name] lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {w:.6f} {h:.6f}) with open(out_txt, w) as f: f.write(\n.join(lines)) class_map { blood: 0, brown: 1, dirty: 2, white: 3, calcium: 4, } xml_dir voc_xml out_dir yolo_labels os.makedirs(out_dir, exist_okTrue) for xml_file in os.listdir(xml_dir): if not xml_file.endswith(.xml): continue base os.path.splitext(xml_file)[0] voc_to_yolo(os.path.join(xml_dir, xml_file), os.path.join(out_dir, base .txt), class_map)这段脚本按class_map把字符串类名映射成从0开始的整数注意COCO里的category_ids不一定连续YOLO要求从0开始连续编号。转换时还要留意VOC里被标记为difficult的objectYOLO训练时最好直接跳过否则会把难样本当正常框算loss让指标变差。常见处理是在循环里加一句判断如果difficult字段值为1就continue掉这个目标。转换完成后必须抽三张图人工核对把txt里归一化坐标画回原图看框是否紧贴蛋体。很多坑不是转换脚本写错而是原始标注本身就框到了蛋托或传送带上这一层不查后面训练全是白费。3. 用YOLOv8在本地跑通鸡蛋分级的最小方案环境、data.yaml、训练参数与首次推理数据整理好之后下一步就是用YOLOv8训练自己的数据集。YOLOv8是目前把数据管线做得最省事的目标检测版本YOLOv5的指令也几乎一样这里以v8为主遇到v5的差异我会单独说明。3.1 装环境先过三件事CUDA版本、显存、ultralytics版本训练YOLO不需要从源码编译一条pip命令即可。但装完别急着跑先确认三件事torch能不能调用GPU、显存有多大、ultralytics装成了哪个版本。版本差一个minor部分参数名就会变网上的命令抄下来可能直接报错。pip install -U ultralytics python -c import torch; print(torch.__version__, torch.cuda.is_available()) python -c import ultralytics; print(ultralytics.__version__)如果torch.cuda.is_available()输出False说明你装的是CPU版torch要重新按PyTorch官网命令装CUDA版。显存方面有个很实用的估算输入分辨率640batch16用yolov8n大约需要6~8GB显存如果你只有4GB显存batch降到8或者把imgsz降到512不要强行把batch设成文档里的默认值。CPU也能训但615张图在CPU上跑100个epoch可能要数小时建议先用10个epoch验证流程。3.2 写data.yaml五个类名、路径变量与三个不能对不上的位置YOLOv8用data.yaml描述数据集。路径可以写相对路径也可以写绝对路径我习惯写相对于yaml文件的路径这样整个项目挪位置不用改内部字段。一个典型的data.yaml长这样path: ../egg_data # 数据集根目录相对于本yaml文件所在目录 train: images/train # 训练图像目录 val: images/val # 验证图像目录 test: images/test # 测试图像目录训练时不使用只在验证时单独指定 nc: 5 # 类别总数必须等于names列表长度 names: 0: blood_egg # 血染鸡蛋 1: brown_egg # 棕色鸡蛋 2: dirty_egg # 脏兮兮的鸡蛋 3: white_egg # 白鸡蛋 4: calcium_egg # 钙沉积蛋这里最容易踩的就是“三个位置对不上”第一个位置是data.yaml的nc和names长度第二个是labels目录txt里的class_id不能超过nc-1第三个是如果你想加载预训练模型继续微调模型的输出通道数和nc要匹配。前两个错了会直接报index out of range第三个错了通常不报错但loss曲线非常怪异、mAP一直上不去。yolov5训练自己的数据集时还会检查每个类别至少有一个实例如果你的钙沉积蛋在train里只有一张图它会在数据校验阶段直接警告类别不平衡。3.3 启动训练img、batch、epochs、patience、workers怎么设615张图是小数据集新手最容易犯的错是把epochs设成300然后挂机跑一夜。对于这种规模我的建议是img640、batch16、epochs100、patience20先跑通再调参。数据增强部分我建议先把mosaic关掉具体原因在避坑章细说。yolo detect train \ dataegg_data.yaml \ modelyolov8n.pt \ imgsz640 \ batch16 \ epochs100 \ patience20 \ device0 \ workers2 \ projectegg_runs \ nameexp_baseline \ mosaic0.0参数说明modelyolov8n.pt是加载COCO预训练权重做迁移学习数据少时比随机初始化快得多收敛也更顺利patience20表示20个epoch内验证集mAP没有提升就早停防止过拟合workers2在Windows上很关键设成默认的8经常在数据加载时卡死Linux可以设成4~8device0是第一张显卡没有GPU就写cpu。mosaic0.0关掉四图拼接增强这在小数据集上能减少很多伪影。训练过程中主要看两个输出每个epoch末尾的metrics/mAP50(B)和results.png里画的损失曲线。损失曲线持续下降但mAP停滞说明模型在死记训练集两者一起涨才算正常。第一次跑最好把epochs临时改成10确认流程通了再跑完整版。如果发现显存不够不要直接加batch先把imgsz降到512对鸡蛋检测的影响远小于显存爆掉的代价。3.4 训练完立刻做一次预测权重路径、conf阈值与画框可视化训练结束后最好的验证方式是拿test目录里没见过的图像直接预测。YOLOv8会把最优权重存在egg_runs/exp_baseline/weights/best.pt用命令行和Python API都能做推理。yolo detect predict \ modelegg_runs/exp_baseline/weights/best.pt \ sourceegg_data/images/test \ conf0.25 \ iou0.45 \ saveTrue \ projectegg_runs \ namepredict_testPython API适合需要二次处理的场景比如我要按检测框坐标做鸡蛋大小分级就得拿到每个框的位置和类别from ultralytics import YOLO model YOLO(egg_runs/exp_baseline/weights/best.pt) results model.predict( sourceegg_data/images/test, conf0.25, iou0.45, saveTrue, ) for r in results: boxes r.boxes.xyxy.cpu().numpy() # [N, 4] 像素坐标 classes r.boxes.cls.cpu().numpy() # [N] 类别id scores r.boxes.conf.cpu().numpy() # [N] 置信度 for box, cls, score in zip(boxes, classes, scores): x1, y1, x2, y2 [round(v, 2) for v in box] print(f类别{int(cls)} 置信度{score:.2f} 框({x1},{y1},{x2},{y2}))conf0.25是置信度阈值低于它的预测框直接丢掉iou0.45是NMS的IoU阈值值越大保留的重叠框越多。鸡蛋这种密集摆放的场景我一般把iou设到0.5因为相邻鸡蛋的框天然重叠阈值太严会误删一个蛋。预测结果里的类别id对应的是data.yaml里names的顺序不是原始中文名做产线逻辑时一定要映射回业务名。4. 鸡蛋分级训练绕不开的5个坑脏标签、类别不平衡、过拟合与推理翻车这一章是我做过几个农业检测项目后的血泪经验。615张图像看起来够用但实际训练时每个坑都会以非常隐蔽的方式出现指标好看和现场好用是两回事。4.1 验证集mAP很高现场新鸡蛋却漏检现象在验证集上mAP50有0.95把模型拿到另一条产线上测鸡蛋漏检一大片特别是浅色的白鸡蛋和钙沉积蛋。原因训练集和验证集来自同一个采集批次背景、光照、传送带材质完全一致模型记住了背景而不是鸡蛋。这种情况在数据增强不足时尤其明显。另一个诱因是划分时用了随机划分同一批次的相似图像被拆到两边验证集等于开卷考试。解决把划分改成按采集批次划分而不是按图像随机划分。比如这批鸡蛋是上午拍的那批是下午拍的那就让train和val分别来自不同时段。我还会保留一个硬测试集专门收集不同光源、不同角度的图像任何调参阶段都不去碰它。这个坑如果不处理后面所有对比实验的结论都是假的。4.2 棕色蛋和脏兮兮蛋互相误判现象混淆矩阵里brown和dirty的交叉项特别亮预测结果里脏蛋被标成棕色棕色蛋被标成脏蛋业务上完全没法用。原因标注时把沾了一点泥的棕色蛋也归为脏兮兮蛋类别边界不干净或者光照偏黄时棕色蛋和脏兮兮蛋在RGB上几乎同色。像素分布几乎重合再好的网络也很难分开。解决先回标注把边界收紧脏兮兮蛋必须显著有泥或粪便附着物普通棕色蛋哪怕颜色暗也归棕色。然后给训练集做色彩增强把HSV的饱和度和明度各做小幅度扰动让模型不把暗和脏绑定。如果两者还是混就把这两类的loss权重调高或者合并成一类非白壳有瑕蛋再训练保业务精度。数据集的标签是别人打的边界标准未必是你的业务标准动手前先定标准。4.3 钙沉积蛋几乎学不出来现象训练结束后各类别AP表里calcium的AP只有0.2其它四类都在0.85以上钙沉积蛋单独拉低整体表现。原因钙沉积蛋在615张图里可能只有30到40张类别严重不平衡。YOLO的loss是所有类别框loss求和少数类贡献的梯度被大类淹没了。加上钙沉积斑块在图像里对比度低模型更难提取特征。解决最简单的办法是复制钙沉积蛋的样本做复制粘贴增强但复制时不要只贴同一颗蛋要随机缩放、旋转后贴到不同背景上否则只是重复记忆。第二个办法是用v8的class_weight参数给少数类加权先试1.5到2倍观察各类AP是否拉平。要是还不行就回到采集层面补拍30张钙沉积蛋比调30轮参数都管用这是最直接的后悔药。4.4 615张图训到一半就过拟合现象训练损失持续下降验证损失在第30个epoch开始反弹mAP50在验证集上忽高忽低保存的best.pt反而是某个偶然高点的结果。原因epochs太长且mosaic增强过度。YOLO默认开启mosaic增强把四张图拼成一张小数据集上这会人为制造大量带伪影的训练样本模型在训练集上很拟合验证集上却抖动剧烈。解决把mosaic关掉或者只在训练前半段用。在Ultralytics里设mosaic0.0可以关掉。615张图用100个epoch、patience20通常够损失曲线如果出现验证loss持续升高、训练loss继续下降就是过拟合信号直接点早停不要等300个epoch跑完。另外数据增强要保守不要同时开旋转、透视、mixup、mosaic那一套在COCO上有效在615张鸡蛋图上只会让模型学坏。4.5 导出的模型在工业相机上卡顿现象训练时把imgsz设成1280导出后又用FP32在CPU上推理单帧耗时几百毫秒。工业相机的连续分拣对帧率很敏感单帧超过100ms基本没法上线。原因输入分辨率越高推理越慢FP32模型在CPU上更是重量级。鸡蛋检测不需要看到蛋壳上的毛孔imgsz640甚至512都够用。解决先把imgsz降到640或512检测框变小的代价可以接受。导出时用int8量化或直接导出TensorRT engineN卡环境。如果还要再快就把输入分辨率固定成采集相机实际输出分辨率避免做二次缩放。实在不行就换yolov8n的结构615张图也喂不饱yolov8m用小模型反而更匹配数据量推理速度快一截。这一章五条经验本质上都在讲一个道理数据集小的时候模型的误差主要来自标注和训练策略而不是网络结构。先把这几个坑排掉再谈调参能少走很多弯路。5. 把模型送上产线mAP、混淆矩阵、ONNX导出与按大小分级的二次筛选训练完成只是开始产线落地要看指标、看错误分布、看推理速度。这一章讲清楚我怎么验收一个鸡蛋分级模型以及怎么在不重新训练的情况下把检测框扩展成多级分拣。5.1 不看单张图看三类指标mAP50、mAP50-95与各类别AP单张图看得再准也不算数YOLO训练结束会在验证集上输出一张结果表核心是mAP50和mAP50-95。mAP50是IoU阈值0.5时的平均精度适合评估框大概对不对mAP50-95是0.5到0.95每隔0.05算一个均值越苛刻对框的贴合度越敏感。鸡蛋分级不需要像自动驾驶那样毫米级定位mAP50达到0.92以上就可以接受mAP50-95低一点没关系但各类别AP之间的差距要小。用Ultralytics自带的方法单独跑一次验证可以批量拿到每个类别的APyolo detect val \ modelegg_runs/exp_baseline/weights/best.pt \ dataegg_data.yaml \ splittest \ imgsz640 \ conf0.001conf0.001是为了在验证时看到所有预测避免阈值筛选掩盖低分样本。输出的results.csv里每一行是一个类别的precision、recall、mAP50我一般先看recall最低的类别因为漏检在现场比误检更致命。如果recall低的同时precision高说明阈值设太严可以适当降conf如果两者都低就要回到训练数据找原因了。5.2 混淆矩阵会说话标注错误和模型误判怎么区分训练目录下会自动生成confusion_matrix.png横轴是真实类别纵轴是预测类别对角线越亮越好。我在鸡蛋项目上看到最常见的是dirty一列多出一块亮色到brown排查时先拿几十张预测图人工看发现是标注人员把轻度脏污蛋标成了棕色蛋。混淆矩阵反映的往往不是模型缺陷而是标注一致性问题。处理方式有两种一种是回改标签把那种轻微污渍的样本重新归类加进训练集另一种是调整业务逻辑把dirty和brown当成同一大类只在上游输出一个颜色属性真正分级靠下游的灰度值或纹理特征。第二种做法在产线上更实用因为传送带上没有时间去纠结这枚蛋算脏还是算棕。混淆矩阵里如果background那一列也很亮说明误检来自蛋托或传送带纹理这时候要回看标注框是不是把背景包进了框里。5.3 导出ONNX/Engine不同部署端的精度与速度取舍训练得到的.pt文件只能在PyTorch环境里跑产线上常见的是ONNX Runtime或TensorRT。导出命令很简单yolo export \ modelegg_runs/exp_baseline/weights/best.pt \ formatonnx \ imgsz640 \ opset12 \ dynamicFalse yolo export \ modelegg_runs/exp_baseline/weights/best.pt \ formatengine \ imgsz640 \ halfTrueONNX适合CPU或移动端部署dynamicFalse会把输入尺寸固定成640×640推理速度更快如果你的相机输出分辨率固定建议直接固定尺寸。engine格式只能在N卡上用导出时会做TensorRT优化通常比ONNX快两到三倍halfTrue用的是FP16显存占用减半。导出后用onnxruntime写个最小推理脚本确认输出shape是[1, 5, 8400]之类再对接相机SDK。别忘记导出的模型输入归一化方式和训练时保持一致YOLO默认除以255很多产线对接翻车就翻在预处理不一致。5.4 鸡蛋按大小分级用检测框面积做S/M/L二次筛选鸡蛋品质除了表面干净程度还有大小分级。业务上通常按重量分级但图像里可以用检测框像素面积做粗分传送带位置固定、镜头高度固定的情况下框面积和实际尺寸是线性关系。训练好的模型已经给出每颗蛋的框直接统计即可。import numpy as np def size_level(w, h, area_thresholds(12000, 16000, 20000)): area w * h # 阈值需要根据你的相机距离实测标定 if area area_thresholds[0]: return S if area area_thresholds[1]: return M if area area_thresholds[2]: return L return XL results model.predict(sourceegg_data/images/test, conf0.25, iou0.5) for r in results: for box in r.boxes.xyxy.cpu().numpy(): x1, y1, x2, y2 box level size_level(x2 - x1, y2 - y1) print(f鸡蛋分级结果: {level})这个二次筛选不需要重新训练模型只把检测框面积映射到业务等级。注意同一颗蛋在不同帧里的面积会有几像素抖动分拣气缸每次触发的时间点不确定所以要加一个按最近N帧取中位数的滑动窗口避免气缸被抖动触发。阈值先用三种已知大小的鸡蛋实测标定不要用训练集里的平均框面积代替。如果发现面积和重量非线性比如蛋型偏长可以改用框的宽高比做辅助判据但那样通常已经超出目标检测范畴更适合用分割模型。6. 给鸡蛋模型的后悔药冻结测试集、三次重复实验、保守增强与验收基线这一章写给所有准备把鸡蛋项目做成正式交付的人。615张图像带标签意味着你有且只有一把子弹模型调参的每一步都在消耗验证集的可靠性。我的后悔药不是某个神奇参数而是一套让实验结果可信的工作习惯正好适合这种小数据量项目。第一颗后悔药是冻结测试集。从划分数据那一刻开始test目录就要锁死任何调参、改标注、加增强都不允许拿着test集反复试。常见错误是训练过程中觉得mAP低就去测试集里找失败样本加进训练集再跑一轮。这么做的结果是测试集被污染最终的数字永远比现场好看。正确做法是训练集随便调整验证集只用来早停测试集只在上线前跑一次跑完记录数值之后所有改动都跟这个基线比。第二颗后悔药是三次重复实验取中位数。小数据集训练结果有随机性同样的命令跑三次mAP可能有2到3个点的波动。单跑一次就下结论这个增强有效很可能只是这次种子撞上了。我一般会把随机种子分别设成0、42、2024跑三次对比时看中位数不是最大值。第三颗后悔药是增强要保守。很多人拿到615张图第一反应是疯狂做数据增强增加样本量。但对鸡蛋这种目标本身外观变化不大的场景过强的mosaic、mixup反而让模型学到拼接边缘的伪影。我最终保留的是轻度旋转±10度、轻微缩放、饱和度扰动关掉mosaic。增强的目的是让模型对光照和角度鲁棒不是造出像脏蛋但实际不脏的合成样本。验收时我还坚持一个盲测习惯不去看训练曲线有多漂亮而是把模型输出的错误样本打印成一叠照片让不懂深度学习的分拣工人打勾判断这颗蛋能不能上市。他们的判断就是最终验收基线。把模型当成黑匣子只看它是否解决业务问题。希望这个615张带标签的鸡蛋品质分级数据集的跑通过程能帮你在YOLO算法和真实质检线之间少踩几个坑也希望帮到你。本文还有配套的精品资源点击获取
返回列表