ARTICLE DETAIL

资讯详情

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

YOLO/VOC/COCO数据集格式转换与坐标系对齐实战指南

YOLO/VOC/COCO数据集格式转换与坐标系对齐实战指南 1. 这不是教科书是我在三个大项目里踩坑踩出来的数据集流水线你手上有一堆手机拍的工地照片、无人机扫的农田视频、或者产线上高速流转的零件特写——但它们还不能喂给模型。真正卡住90%新手的从来不是YOLO的损失函数怎么调也不是TensorRT怎么加速而是第一口饭——数据集——根本喂不进去。我带过七支视觉团队从智能巡检到农业识别最常听到的求助不是“loss不下降”而是“标注完导出YOLO格式训练报错no labels found”、“COCO JSON里category_id对不上”、“VOC转YOLO后bbox全偏移”。这些错误背后没有玄学只有三件事没做对原始图像的元信息一致性、标注逻辑与任务目标的咬合度、格式转换时坐标系的隐式假设。这整套流程我把它拆成四个不可跳过的硬核环节收集不是拍照存文件夹标注不是框框画框VOC/COCO/YOLO不是三种并列格式而是一套坐标系统标签体系文件组织规范的组合拳。比如YOLO要求归一化坐标但很多人直接把VOC的像素坐标除以宽高就交差却忘了VOC的bbox是[xmin, ymin, xmax, ymax]而YOLO要的是[center_x, center_y, width, height]——中间差了一个(xmax-xmin)/2的偏移计算。再比如COCO的category_id必须从1开始连续编号但你用LabelImg导出VOC后手动改XMLID乱序了转COCO时索引直接越界。这些坑我都在产线部署前夜通宵填过。本文不讲理论推导只给你一条能直接跑通的流水线从手机相册里拖出500张图开始到生成可直接扔进YOLOv8 train.py的datasets目录为止每一步都标清楚为什么这么干、不这么干会炸在哪一行日志里。适合刚拿到甲方需求文档的算法工程师、正在准备毕业设计的研究生、以及被老板催着“下周就要看到检测效果”的嵌入式工程师。2. 数据集制作全流程为什么必须分四步走而不是“找个工具一键转换”2.1 收集阶段图像质量、场景覆盖与元信息控制的三角平衡收集不是体力活是数据资产的第一道风控闸门。我见过太多团队花两周拍3000张图结果发现87%的图片在同一个光照角度下拍摄模型一上真实产线就漏检——因为训练集里根本没有逆光、侧光、强阴影场景。真正的收集策略必须同时满足三个硬约束光照多样性按时间分段采集早/中/晚而非单纯增加数量。例如农业病害检测晨露未干、正午强光、傍晚低色温下的叶片反光特性差异极大单靠数据增强无法模拟这种物理级变化。视角与尺度覆盖用“距离×角度”矩阵规划采集。比如工业缺陷检测需设定近距10cm、中距50cm、远距2m三个基准距离每个距离再覆盖正视、斜45°、俯视三个角度形成9种基础组合。实测表明少于6种组合时小目标召回率下降超40%。元信息强制记录每张图必须附带EXIF中的DateTimeOriginal、Make相机品牌、Model型号、FocalLengthIn35mmFilm等效焦距。这些看似无关的信息在后续分析误检样本时至关重要——曾有个案例所有误检都集中在某款iPhone 12拍摄的图片上追溯发现其广角镜头畸变校正算法与训练集主流相机不一致最终通过添加对应畸变模拟层解决。提示禁止使用截图或压缩后的网络图片。我处理过一个OCR项目客户提供的“现场照片”实为微信转发的JPG二次压缩导致文字边缘模糊即使标注再精准模型也学不会清晰笔画特征。原始采集必须用RAW或高质量JPEG且保留完整EXIF。工具链选择上我放弃一切“智能采集APP”坚持用ADB命令批量抓取安卓设备相册adb shell content query --uri content://media/external/images/media --projection _id:display_name:data_type:date_added --where date_added 1672531200配合Python脚本自动提取GPS坐标和时间戳生成CSV元数据表。原因很简单APP会自动裁剪、滤镜、重编码而命令行直取原始文件路径确保像素零失真。对于无人机数据则用DJI SDK导出带经纬度、高度、云台俯仰角的CSV与每帧画面时间戳对齐——这些信息后期做地理围栏或尺度自适应时就是救命稻草。2.2 标注阶段标签体系设计比框选操作重要十倍标注员画框的速度永远快不过算法工程师重构标签体系的时间。去年帮一家电力公司做绝缘子裂纹检测他们最初用“裂纹/正常”二分类标注完2000张训练发现模型把所有反光区域都判为裂纹。问题不在标注不准而在标签定义没穿透物理本质裂纹是亚毫米级线性缺陷而反光是宏观光学现象二者应属不同维度。我们立刻重构为三级标签体系Level 1状态正常/异常Level 2异常类型裂纹/污秽/锈蚀/形变Level 3裂纹子类纵向/横向/网状/起皮这个调整让mAP提升12.3%但代价是返工重标1500张图。所以标注启动前必须完成三件事制定《标注歧义判定手册》明确边界案例的处理规则。例如“鸟停在电线上”是否标注手册规定鸟体与电线接触面积30%像素才标否则视为背景干扰。这条规则避免了标注员主观判断导致的标签噪声。设计最小可分辨单元MRU根据部署场景确定标注粒度。同样是“车辆检测”交通卡口需标注到车牌级别MRU10px而园区安防只需区分车型MRU50px。我们曾因MRU设错导致模型在4K视频里能检出轿车却漏掉远处的自行车——因为标注时把自行车当“小目标”合并到“其他”类里。强制实施交叉验证机制每100张图设5张“黄金标准图”由算法工程师亲自标注随机插入标注队列。标注员完成批次后系统自动比对IoU低于0.85的批次全部返工。这套机制使标注一致性从72%提升至96%。工具选型上LabelImg仍是VOC流程的基石但必须打补丁修改labelImg/libs/shape.py在__init__中强制self.label self.label.strip().upper()避免“car”和“Car”被当不同类别用labelImg/plugins/auto_label.py接入YOLO预训练模型做半自动标注但仅作为初筛人工必须逐帧修正——自动标注对遮挡、小目标、模糊区域的漏标率高达38%直接采用等于给模型喂毒。2.3 VOC格式不是XML文件堆砌而是坐标系与层级关系的显式声明VOCPASCAL Visual Object Classes格式常被误解为“一堆XML文件”其实它是一套严格的坐标系契约所有bbox坐标基于图像左上角原点单位为像素且必须满足xmin xmax、ymin ymax。但真正致命的陷阱藏在细节里图像尺寸一致性VOC要求所有size标签中的width和height必须与实际图像像素尺寸完全一致。我遇到过最诡异的bug标注工具导出的XML里width写成1920但实际图像是1920×1080的PNG而height却填了1080.0带小数点——PyTorch DataLoader读取时因类型转换失败直接崩溃。解决方案是用OpenCV校验cv2.imread(img_path).shape[:2]得到的(height, width)必须与XML中数值完全匹配。类别ID隐式绑定VOC本身不定义类别ID它依赖ImageSets/Main/train.txt中文件名与Annotations/下XML的严格一一对应。一旦文件名含空格或中文Linux服务器读取时路径解析失败训练时出现“image not found”错误。我们强制规定所有文件名仅允许小写字母、数字、下划线且.jpg扩展名统一为小写。分割掩码的坑VOC支持segmented标签但多数工具导出为空值。若需实例分割必须手动生成SegmentationObject和SegmentationClass两个PNG掩码图其中SegmentationClass的像素值对应name在pascal_voc_classes.txt中的行号从0开始。曾有个项目因掩码图用RGB模式保存模型读取时把(255,0,0)当类别255而非类别1训练完全失效。实操中我构建了一个VOC校验流水线# 检查XML结构合法性 find Annotations/ -name *.xml | xargs -I {} xmllint --noout {} 2/dev/null || echo Invalid XML detected # 校验图像尺寸匹配 python -c import xml.etree.ElementTree as ET, cv2, os for xml in os.listdir(Annotations): tree ET.parse(fAnnotations/{xml}) root tree.getroot() width int(root.find(size/width).text) height int(root.find(size/height).text) img_path fJPEGImages/{xml.replace(\.xml\, \.jpg\)} if os.path.exists(img_path): h, w cv2.imread(img_path).shape[:2] if w ! width or h ! height: print(fMismatch: {xml} expects {width}x{height}, got {w}x{h}) 这段脚本能在5分钟内扫清整个VOC数据集的结构性错误比人工抽查高效百倍。2.4 COCO格式JSON不是万能容器是对象关系与统计约束的精密表达COCOCommon Objects in Context格式的核心价值不在JSON语法而在其对象关系建模能力一张图可含多个对象每个对象有独立bbox、segmentation、keypoints且所有类别通过categories数组全局索引。但新手常犯的致命错误是把VOC XML机械转成COCO JSON忽略三个关键约束category_id必须从1开始连续编号COCO规范明文规定categories[i].id i1。若你的VOC有“person”、“car”、“dog”三类但XML中name顺序是car/person/dog直接映射会导致car.id1、person.id2、dog.id3而模型加载时默认person.id1结果所有行人被识别为汽车。解决方案是构建映射字典{person:1, car:2, dog:3}遍历所有XML强制重编号。image_id与annotation_id的全局唯一性COCO要求所有images[]的id字段在整个数据集中唯一且annotations[]的image_id必须存在于images[]中。常见错误是分批次生成JSON时各批次image_id都从1开始合并后ID冲突。我们采用时间戳哈希image_id int(hashlib.md5(img_filename.encode()).hexdigest()[:8], 16) % 1000000确保百万级图像ID不重复。segmentation格式的双重校验COCO支持RLE和polygon两种掩码格式。Polygon必须是[[x1,y1,x2,y2,...]]的浮点数列表且首尾坐标必须闭合即x1x_last and y1y_last。曾有个项目因标注工具导出polygon未闭合OpenCVcv2.fillPoly填充时崩溃。我们在转换脚本中加入闭合检查def close_polygon(poly): if len(poly) 4 and poly[0] ! poly[-1]: poly.append(poly[0]) return poly更隐蔽的坑在area字段COCO要求area必须等于mask实际像素面积而非bbox面积。若用bbox[2]*bbox[3]填充area评估时AP计算会严重失真。正确做法是用cv2.contourArea计算polygon面积或对RLE解码后用np.sum(mask)。2.5 YOLO格式归一化不是数学游戏是部署端推理引擎的物理约束YOLO格式.txt文件表面简单实则暗藏部署级约束。它的核心是归一化坐标系与文件组织强耦合每个txt文件名必须与同名jpg严格对应且内容为class_id center_x center_y width height全部0~1范围。但“归一化”二字常被曲解center_x/center_y的计算陷阱正确公式是(xmin xmax) / (2 * img_width)而非(xmax - xmin) / (2 * img_width)。后者算出来是半宽不是中心横坐标。这个错误导致模型学习到错误的anchor偏移训练loss震荡剧烈。width/height的物理意义width (xmax - xmin) / img_widthheight (ymax - ymin) / img_height。注意分母必须用各自方向的图像尺寸——若图像旋转90°宽高互换但很多脚本仍用原图宽高计算导致bbox严重拉伸。多目标文件的行序无关性YOLO不要求txt中行序与图像中目标出现顺序一致但必须保证同一张图的所有目标都在一个txt里。曾有个项目因脚本bug把单图多目标拆到多个txt训练时只读第一个文件其余目标彻底丢失。我们开发了一个YOLO校验器重点监控三类错误txt文件缺失find labels/ -name *.txt | sed s/\.txt$// | sort txt_list.txt; find images/ -name *.jpg | sed s/\.jpg$// | sort img_list.txt; comm -23 img_list.txt txt_list.txt坐标越界awk {if($20||$21||$30||$31||$40||$41||$50||$51) print FILENAME} labels/*.txt类别ID越界awk {if($10||$1num_classes) print FILENAME,$1} labels/*.txtnum_classes需提前配置这套校验在YOLOv5/v8迁移中拦截了92%的格式错误避免了训练数小时后才发现数据问题的灾难。3. 四格式互转不是代码搬运是坐标系、索引体系、文件协议的三重映射3.1 VOC转YOLO从像素坐标到归一化坐标的物理对齐VOC转YOLO看似简单实则是图像坐标系到模型输入空间的首次物理对齐。关键步骤如下读取VOC XML获取原始bboxtree ET.parse(xml_path) root tree.getroot() size root.find(size) img_w int(size.find(width).text) img_h int(size.find(height).text) for obj in root.findall(object): bbox obj.find(bndbox) xmin int(bbox.find(xmin).text) ymin int(bbox.find(ymin).text) xmax int(bbox.find(xmax).text) ymax int(bbox.find(ymax).text)坐标转换此处必须手算不可调库center_x (xmin xmax) / (2 * img_w)center_y (ymin ymax) / (2 * img_h)width (xmax - xmin) / img_wheight (ymax - ymin) / img_h注意OpenCV读图的shape返回(height, width)而PIL返回(width, height)。若混用img_w/img_h颠倒会导致bbox整体旋转90°。我们统一用cv2.imread().shape并在脚本开头加断言assert img.shape[0] img_h and img.shape[1] img_w。类别映射与文件写入# 构建类别字典必须与train.yaml中names顺序一致 class_dict {person: 0, car: 1, dog: 2} with open(flabels/{xml_name.replace(.xml, .txt)}, w) as f: for obj in objects: cls_id class_dict[obj[name]] f.write(f{cls_id} {center_x:.6f} {center_y:.6f} {width:.6f} {height:.6f}\n)实操心得YOLOv8要求txt文件必须存在即使图像无目标也要创建空txt。我们用touch labels/xxx.txt初始化所有文件再逐个填充避免训练时报错“no labels found”。3.2 VOC转COCO从单图单类到全局对象关系的升维重构VOC转COCO的本质是将分散的XML文件升维为全局对象关系图。核心挑战在于categories、images、annotations三大数组的协同构建categories数组构建categories [] class_names sorted(set(all_class_names)) # 强制排序确保ID连续 for i, name in enumerate(class_names): categories.append({ id: i1, # COCO要求从1开始 name: name, supercategory: none })images数组构建关键images [] for img_file in image_files: img cv2.imread(fJPEGImages/{img_file}) h, w img.shape[:2] images.append({ id: get_unique_image_id(img_file), # 时间戳哈希 file_name: img_file, width: w, height: h, date_captured: datetime.now().isoformat(), license: 1 })annotations数组构建最易出错annotations [] ann_id 1 # 全局唯一 for xml_file in xml_files: tree ET.parse(fAnnotations/{xml_file}) root tree.getroot() img_id get_unique_image_id(xml_file.replace(.xml, .jpg)) for obj in root.findall(object): bbox obj.find(bndbox) xmin int(bbox.find(xmin).text) ymin int(bbox.find(ymin).text) xmax int(bbox.find(xmax).text) ymax int(bbox.find(ymax).text) # COCO bbox格式[xmin, ymin, width, height] coco_bbox [xmin, ymin, xmax-xmin, ymax-ymin] # 计算area必须用mask面积此处用bbox近似 area (xmax-xmin) * (ymax-ymin) annotations.append({ id: ann_id, image_id: img_id, category_id: class_dict[obj.find(name).text], bbox: coco_bbox, area: area, iscrowd: 0 }) ann_id 1提示COCO的iscrowd0表示单个对象1表示crowd区域如人群。若VOC中用difficult标签标记难例应转为COCO的ignore字段需修改JSON schema而非简单丢弃。3.3 COCO转YOLO从全局ID到本地ID的索引坍缩COCO转YOLO是对象关系图向单图平面坐标的坍缩过程难点在于category_id的映射一致性读取COCO JSON并构建映射with open(coco.json) as f: coco json.load(f) # 构建COCO category_id到YOLO class_id的映射 coco_to_yolo {} for i, cat in enumerate(coco[categories]): coco_to_yolo[cat[id]] i # COCO id→YOLO index0-based按image_id分组annotationsfrom collections import defaultdict img_anns defaultdict(list) for ann in coco[annotations]: img_anns[ann[image_id]].append(ann)逐图转换关键坐标归一化for img in coco[images]: img_id img[id] img_w, img_h img[width], img[height] img_name img[file_name] txt_path flabels/{img_name.replace(.jpg, .txt)} with open(txt_path, w) as f: for ann in img_anns[img_id]: # COCO bbox: [xmin, ymin, width, height] xmin, ymin, w, h ann[bbox] # 转YOLO格式 center_x (xmin w/2) / img_w center_y (ymin h/2) / img_h norm_w w / img_w norm_h h / img_h yolo_cls_id coco_to_yolo[ann[category_id]] f.write(f{yolo_cls_id} {center_x:.6f} {center_y:.6f} {norm_w:.6f} {norm_h:.6f}\n)实操避坑COCO JSON中images[]可能包含未标注的图像如test set这些图像在annotations[]中无对应项。脚本必须用defaultdict(list)而非anns_by_img[img_id]直接索引否则KeyError中断。3.4 YOLO转VOC从归一化坐标到像素坐标的逆向工程YOLO转VOC是模型输出空间向物理图像空间的逆向映射需严格遵循YOLO的归一化定义读取YOLO txt并获取图像尺寸img_path fimages/{txt_file.replace(.txt, .jpg)} img cv2.imread(img_path) img_h, img_w img.shape[:2]坐标逆变换注意必须用原始图像尺寸with open(flabels/{txt_file}) as f: lines f.readlines() for line in lines: parts line.strip().split() cls_id int(parts[0]) center_x float(parts[1]) center_y float(parts[2]) width float(parts[3]) height float(parts[4]) # 逆变换pixel normalized * img_size xmin max(0, int((center_x - width/2) * img_w)) ymin max(0, int((center_y - height/2) * img_h)) xmax min(img_w, int((center_x width/2) * img_w)) ymax min(img_h, int((center_y height/2) * img_h))注意max(0, ...)和min(img_w, ...)防止归一化坐标越界导致负值或超图幅这是YOLO训练时常见的坐标扰动所致。生成VOC XML模板# 使用xml.etree.ElementTree构建标准VOC结构 root ET.Element(annotation) ET.SubElement(root, folder).text JPEGImages ET.SubElement(root, filename).text img_name ET.SubElement(root, path).text fJPEGImages/{img_name} source ET.SubElement(root, source) ET.SubElement(source, database).text Unknown size ET.SubElement(root, size) ET.SubElement(size, width).text str(img_w) ET.SubElement(size, height).text str(img_h) ET.SubElement(size, depth).text 3 ET.SubElement(root, segmented).text 0 # 添加object节点...3.5 COCO转VOC全局关系到单图XML的降维打击COCO转VOC是对象关系图向单图XML的降维过程需重建VOC的层级结构构建image_id到文件名的映射img_dict {img[id]: img[file_name] for img in coco[images]}按image_id分组annotationsfrom collections import defaultdict img_anns defaultdict(list) for ann in coco[annotations]: img_anns[ann[image_id]].append(ann)逐图生成XMLfor img_id, img_name in img_dict.items(): img cv2.imread(fimages/{img_name}) h, w img.shape[:2] root ET.Element(annotation) # ... 填充VOC基础结构 ... for ann in img_anns[img_id]: obj ET.SubElement(root, object) ET.SubElement(obj, name).text coco[categories][ann[category_id]-1][name] # COCO id从1开始 ET.SubElement(obj, pose).text Unspecified ET.SubElement(obj, truncated).text 0 ET.SubElement(obj, difficult).text 0 bndbox ET.SubElement(obj, bndbox) # COCO bbox: [xmin, ymin, width, height] xmin, ymin, w_box, h_box ann[bbox] ET.SubElement(bndbox, xmin).text str(int(xmin)) ET.SubElement(bndbox, ymin).text str(int(ymin)) ET.SubElement(bndbox, xmax).text str(int(xmin w_box)) ET.SubElement(bndbox, ymax).text str(int(ymin h_box)) # 写入XML文件 tree ET.ElementTree(root) tree.write(fAnnotations/{img_name.replace(.jpg, .xml)}, encodingutf-8, xml_declarationTrue)4. 实战问题排查那些让训练崩盘的隐藏雷区与我的排雷手册4.1 “No labels found”错误不是路径错了是文件协议没对齐这个报错90%源于文件命名协议断裂。YOLO训练脚本如ultralytics的train.py默认寻找images/train/xxx.jpg对应的labels/train/xxx.txt。但实际中常见断裂点扩展名大小写不一致图像为IMG_001.JPG而脚本按.jpg查找IMG_001.txt结果找不到。解决方案统一用find images/ -iname *.jpg | xargs -I {} mv {} {}.tmp rename s/\.tmp$// images/*.tmp批量转小写。路径层级错位VOC结构是JPEGImages/xxx.jpgAnnotations/xxx.xml而YOLO要求images/xxx.jpglabels/xxx.txt。若直接复制VOC文件夹未重命名目录脚本在images/下找不到jpg。我们用符号链接解决ln -s VOCdevkit/VOC2007/JPEGImages images。空标签文件缺失YOLO要求每张图都有对应txt哪怕无目标。用for img in images/*.jpg; do base$(basename $img .jpg); touch labels/$base.txt; done初始化。提示在训练前运行python -c from ultralytics.data.utils import check_det_dataset; check_det_dataset(data.yaml)它会扫描所有路径并报告缺失文件比报错后再排查快10倍。4.2 mAP为0或极低坐标系污染导致的特征学习失效当训练loss下降但mAP卡在0大概率是坐标系污染——模型学到的bbox偏移与真实物理位置完全脱钩。典型症状验证集上所有预测框集中在图像中心区域loss曲线平滑下降但precision/recall始终为0可视化预测结果时框与目标完全不重叠。根因分析表现象可能原因排查命令解决方案所有预测框宽度≈0.5width归一化时用了img_h而非img_whead -n 1 labels/xxx.txt看width值分布检查转换脚本中/ img_w是否误写为/ img_h框整体偏右下center_x/center_y计算未加max(0,min(1,))截断awk {print $2,$3} labels/*.txtsort -n小目标全漏检VOC转YOLO时未处理xminxmax的退化bboxgrep -r 0\.000000 0\.000000 labels/过滤掉xmax-xmin5的bbox实操案例某次农业项目中mAP始终为0.02。用cv2.imshow可视化YOLO标签将txt坐标转回像素画框发现所有框都比实际目标大3倍——追查发现转换脚本中width (xmax-xmin) / img_h把高度当宽度用了。修复后mAP飙升至0.81。4.3 类别ID错乱不是标注错了是索引体系没同步类别ID错乱表现为模型把A类识别为B类且混淆矩阵显示高置信度。根源在于训练yaml、标签文件、预训练权重三者ID映射不一致YOLOv8默认80类若你只有3类但用yolov8n.pt微调权重中names是COCO的80类而你的train.yaml中names: [a,b,c]模型会把第1类权重person强行加载到你的a类上。解决方案必须用--resume参数从头训练或修改ultralytics/nn/tasks.py中DetectionModel.__init__强制加载时跳过类别层# 在load_state_dict前添加 for k in list(state_dict.keys()): if k.startswith(model.22.) or k.startswith(model.23.): # 检测头权重 state_dict.pop(k)更稳妥的做法是用官方脚本导出适配权重yolo detect train datadata.yaml modelyolov8n.pt epochs100 resumeFalse # 训练1个epoch后中断此时权重已适配你的类别数4.4 格式转换后图像损坏元数据丢失引发的像素级灾难用PIL或OpenCV批量处理图像时常见EXIF元数据丢失导致后续分析失效。例如无人机图像含GPS信息转换后变成纯RGB图地理定位功能彻底报废。PIL保存时保留EXIFfrom PIL import Image img Image.open(input.jpg) exif img.info.get(exif) img.save(output.jpg, exifexif) # 关键传入exif参数OpenCV保存时注入EXIFOpenCV不支持EXIF需用piexif库import piexif img cv2.imread(input.jpg) # 保存为JPEG cv2.imwrite(temp.jpg, img) # 注入原始EXIF exif_dict piexif.load(input.jpg) piexif.insert(piexif.dump(exif_dict), temp.jpg)实测对比未保留EXIF的图像在GIS平台中显示为(0,0)坐标保留后精确到小数点后6位。4.5 多格式共存时的版本冲突一个数据集三种格式如何安全切换大型项目常需同时维护VOC/COCO/YOLO三套格式如VOC用于传统算法对比COCO用于Mask R-CNNYOLO用于边缘部署。手动同步极易出错我们采用硬链接Git LFS方案建立主格式仓库以YOLO为事实源因其结构最简所有图像存images/标签存labels/。用硬链接生成其他格式# VOC结构 mkdir -p VOCdevkit/VOC2007/JPEGImages VOCdevkit/VOC2007/Annotations ln -f images/*.jpg VOCdevkit/VOC2007/JPEGImages/ # 用脚本生成Annotations/XML非硬链接因内容不同 python voc_gen.py --yolo-dir labels/ --voc-dir VOCdevkit/VOC2007/Annotations/Git LFS管理大文件git lfs install git lfs track *.jpg git lfs track *.png git add .gitattributes这样修改YOLO标签后运行python sync_all.py即可一键更新VOC/COCO避免人工同步遗漏。5. 我的终极工作流从手机相册到可训练数据集的15分钟自动化流水线最后分享我压箱底的自动化脚本它把整个流程压缩到15分钟内#!/bin/bash # data_pipeline.sh # 输入手机导出的DCIM文件夹 # 输出可直接喂给YOLOv8的
返回列表