ARTICLE DETAIL

资讯详情

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

手机识别数据集实战:COCO JSON转YOLO与训练避坑指南

手机识别数据集实战:COCO JSON转YOLO与训练避坑指南 简介这份手机识别数据集面向计算机视觉初学者与目标检测开发者用于训练和验证手机目标检测模型解决手机类样本不足、标注格式不统一的问题。资源包共2000个文件以1997张jpg原始图片为主另附3个json标注文件采用coco json格式可直接对接主流检测框架的数据加载流程压缩包整体约82.97MB体积轻便便于快速下载与本地部署。图片命名包含IMG2021系列与mobile-phones、pp等前缀覆盖多种拍摄场景与手机外观适合做数据增强、模型微调与精度对比实验。目前已有725人学习下载可作为课程设计、毕业项目或算法练手的现成数据基础帮助读者省去采集与标注成本把精力集中在模型结构、训练策略与评估指标分析上。1. 手机识别数据集怎么用2628 张原图与 COCO JSON 标注的落地路径做手机检测这类小目标任务最耗时的往往不是调模型而是凑一份标注干净、格式对得上的数据。这份手机识别数据集给的是 2628 张原始图片配套 COCO JSON 格式标注文件名里能看到IMG20211010…这类手机直出命名也有mobile-phones-_jpg.rf.…、pp385_jpg.rf.…这种混合来源说明采集场景比较杂正好覆盖室内桌面、手持、多机同框等真实分布。它适合三类人想快速跑通检测 pipeline 的算法工程师、需要现成标注做课程设计的学生、以及拿它当预训练或蒸馏底料的从业者。COCO JSON 的好处是生态最广主流检测框架基本都能直接吃省掉自己写解析器的功夫。下面按“先看清结构、再动手转换、最后避坑”的顺序拆一遍。2. 先读懂 COCO JSON 结构images、annotations、categories 三张表怎么对拿到一份 COCO 标注别急着往模型里灌。先搞清楚它的字段组织方式后面转换、校验、排错都靠这个底子。COCO 本质是一个大 JSON核心就三个数组images描述每张图的 id、文件名、宽高annotations描述每个框的 bbox、类别 id、所属图片 idcategories描述类别 id 和名称。三者靠 id 互相引用任何一处对不上训练时就是静默丢样本或者框错位。2.1 用 Python 快速体检标注文件第一步永远是先统计别信“标注完整”这种口头承诺。下面这段脚本把类别分布、图片数、框数、异常框一次性打出来。import json from collections import Counter with open(annotations.json, r, encodingutf-8) as f: coco json.load(f) imgs coco[images] anns coco[annotations] cats coco[categories] print(图片数:, len(imgs)) print(标注框数:, len(anns)) print(类别:, {c[id]: c[name] for c in cats}) # 每类框数量 cat_counter Counter(a[category_id] for a in anns) print(每类框数:, cat_counter) # 检查 bbox 是否越界或退化 bad [] for a in anns: x, y, w, h a[bbox] if w 1 or h 1: bad.append((a[id], 尺寸退化, a[bbox])) print(异常框数量:, len(bad))逻辑说明images长度就是实际可用图片数如果明显小于 2628说明有图没进标注或被过滤。cat_counter能看出类别是否严重不均衡手机检测通常只有一到两类若出现十几个类别要警惕混入了无关标注。bbox是[x, y, width, height]格式注意不是[x1,y1,x2,y2]这是 COCO 最容易翻车的地方后面转换会重点讲。参数上w 1 or h 1是我一般用的退化阈值小于这个尺寸的框训练时基本是噪声。2.2 图片 id 与文件名映射要单独存一份COCO 里images的file_name才是真实文件名id只是内部编号。很多框架读图时按file_name找但有些转换脚本会误用id拼路径结果全部读不到图。稳妥做法是先导出一份映射表。import os img_dir images mapping {img[id]: img[file_name] for img in imgs} missing [fn for fn in mapping.values() if not os.path.exists(os.path.join(img_dir, fn))] print(缺失图片数:, len(missing)) print(前 5 个缺失:, missing[:5])这段的作用是把“标注里有、磁盘上没有”的图揪出来。常见原因是文件名里的.rf.哈希段在拷贝时被截断或者大小写不一致。missing为空才说明数据齐整否则训练时 DataLoader 会直接抛异常或者跳过白白浪费 epoch。2.3 类别 id 不连续是正常现象COCO 的category_id不要求从 0 连续很多标注工具会留空号。但 YOLO 这类框架要求类别从 0 开始连续编号所以转换时必须重建映射不能直接把category_id当类别索引用。这一点在下一章转换时会具体处理。3. 转成 YOLO 格式从 COCO bbox 到归一化中心点坐标大部分人要的不是 COCO 本身而是把它喂给 YOLO 系列。COCO 的bbox是左上角加宽高YOLO 要的是归一化的中心点加宽高两者差一次坐标变换和一次除以图像尺寸。这一步写错框会整体偏移而且偏移量随图片尺寸变化肉眼很难第一时间发现。3.1 转换脚本与目录组织先约定目录结构转换脚本按这个结构读写后面训练配置直接复用。dataset/ images/ # 2628 张原图 annotations.json # COCO 标注 labels/ # 转换后输出的 YOLO txt data.yaml # 训练配置转换脚本如下import json, os with open(annotations.json, r, encodingutf-8) as f: coco json.load(f) # 重建连续类别映射 cats sorted(coco[categories], keylambda c: c[id]) cat_id2idx {c[id]: i for i, c in enumerate(cats)} names [c[name] for c in cats] img_info {img[id]: img for img in coco[images]} os.makedirs(labels, exist_okTrue) # 按图片聚合标注 from collections import defaultdict per_img defaultdict(list) for a in coco[annotations]: per_img[a[image_id]].append(a) for img_id, anns in per_img.items(): info img_info[img_id] W, H info[width], info[height] lines [] for a in anns: x, y, w, h a[bbox] cx (x w / 2) / W cy (y h / 2) / H nw w / W nh h / H # 裁剪到 [0,1]防止越界框 cx, cy min(max(cx, 0), 1), min(max(cy, 0), 1) nw, nh min(nw, 1), min(nh, 1) cls cat_id2idx[a[category_id]] lines.append(f{cls} {cx:.6f} {cy:.6f} {nw:.6f} {nh:.6f}) stem os.path.splitext(info[file_name])[0] with open(flabels/{stem}.txt, w) as f: f.write(\n.join(lines)) print(类别顺序:, names)逻辑说明cat_id2idx把原始不连续的category_id压成 0 起始的连续索引这是 YOLO 的硬要求。cx (x w/2)/W是中心点归一化nw w/W是宽归一化顺序不能反。裁剪到[0,1]是为了兜住少量越界标注否则 YOLO 训练时会报坐标非法。输出文件名用原图 stem保证图片和标签同名这是 YOLO 找标签的默认规则。3.2 data.yaml 怎么写转换完还要一份配置文件告诉框架去哪找图和类别名。path: ./dataset train: images val: images nc: 1 names: [mobile phone]nc是类别数要和names长度一致。这里train和val都指向images只是先跑通正式训练要按比例切分常见做法是 8:2切分时注意同一场景的连拍图别跨集否则验证指标会虚高。names的顺序必须和转换脚本里names一致错一位整个类别就乱了。3.3 转换后必须做一次回读校验转完别直接开训写个回读脚本把 YOLO txt 反算回像素坐标和原 COCO 对比误差应该在 1 像素内。import json with open(annotations.json) as f: coco json.load(f) img_info {i[id]: i for i in coco[images]} max_err 0 for a in coco[annotations]: info img_info[a[image_id]] W, H info[width], info[height] stem info[file_name].rsplit(., 1)[0] with open(flabels/{stem}.txt) as f: lines f.readlines() # 简化只校验第一个框实际可按顺序匹配 cls, cx, cy, nw, nh lines[0].split() px (float(cx) - float(nw) / 2) * W py (float(cy) - float(nh) / 2) * H err abs(px - a[bbox][0]) abs(py - a[bbox][1]) max_err max(max_err, err) print(最大回算误差(像素):, max_err)误差超过 1 像素基本就是归一化用错了尺寸或者把宽高当成了右下角坐标。这一步花两分钟能省掉后面几小时的排查。4. 训练前避坑标注、尺寸与划分里的五个常见问题数据看着干净一训就崩问题多半出在下面这几处。每条按现象、原因、解决写都是实际踩过的。4.1 现象loss 正常下降但框全部偏左上原因COCO 的bbox是[x, y, w, h]有人误当成[x1, y1, x2, y2]转换时直接拿后两位当宽高导致中心点算错。解决转换前打印前几条bbox确认第三、四个值明显小于图像宽高若接近图像尺寸就是坐标对而非宽高。4.2 现象训练报 “invalid label” 或坐标大于 1原因原标注里有越界框或者图片实际尺寸和images里记录的width/height不一致。解决转换时做[0,1]裁剪同时用 PIL 重新读一遍真实尺寸和 JSON 里的对比不一致就以真实尺寸为准重算。4.3 现象验证集 mAP 高得离谱实际推理一塌糊涂原因连拍图被随机切分同一场景的相似帧同时进了训练和验证等于变相泄漏。解决按文件名前缀或采集批次分组切分同一组只进一个集合。这份数据里IMG20211009…明显是同一批连拍切分时要整组处理。4.4 现象某类框数远少于其他类模型几乎不预测原因类别不均衡手机检测里若混入了“手机壳”“屏幕”等细分类小类会被压制。解决先看第 2 章脚本打出的cat_counter若确实不均衡合并细分类或对小类做重采样别硬训。4.5 现象文件名里的.rf.哈希导致路径匹配失败原因部分框架按文件名前缀匹配图片和标签.rf.后面的哈希段让 stem 变长若标签生成时截断规则不一致就对不上。解决统一用os.path.splitext取 stem图片和标签用同一套规则别手工截字符串。5. 进阶用这份数据做小目标增强与标注质量抽检跑通 baseline 之后真正拉开差距的是两件事小目标召回和标注质量。手机在画面里往往只占几十像素直接训容易漏。我一般会先做一次标注质量抽检再做针对性增强。抽检的做法是把标注框画回原图随机抽 30 张拼成网格看。下面这段用 PIL 画框不依赖任何可视化库。from PIL import Image, ImageDraw import json, random with open(annotations.json) as f: coco json.load(f) img_info {i[id]: i for i in coco[images]} from collections import defaultdict per_img defaultdict(list) for a in coco[annotations]: per_img[a[image_id]].append(a) samples random.sample(list(per_img.keys()), 30) for i, img_id in enumerate(samples): info img_info[img_id] im Image.open(fimages/{info[file_name]}).convert(RGB) d ImageDraw.Draw(im) for a in per_img[img_id]: x, y, w, h a[bbox] d.rectangle([x, y, x w, y h], outlinered, width2) im.save(fcheck_{i}.jpg)逻辑说明rectangle用的是[x1,y1,x2,y2]所以要把xw、yh算出来这里正好和转换时的公式互为验证。抽检重点看三类问题框是否只框了屏幕没框机身、多机同框时是否漏标、遮挡严重的机器是否被标成了整框。发现系统性偏差就回去修标注别指望模型自己学出来。增强方面小目标优先用 mosaic 和随机缩放但缩放别低于原图短边的 0.5 倍否则手机直接糊成色块。另外这份数据来源杂白平衡和曝光差异大HSV 抖动可以开大一点hsv_h0.02、hsv_s0.7、hsv_v0.4是我常用的起点。验证时单独统计小目标面积小于 32×32的召回别只看整体 mAP整体指标会被大框拉高掩盖小目标的真实表现。从那以后我每次拿到新数据集都强制先跑一遍第 2 章的体检脚本和第 3 章的回读校验再动手训。这两步加起来不到五分钟却能挡掉后面大半的玄学问题。希望帮到你。本文还有配套的精品资源点击获取
返回列表