YOLOv5 v3.0 数据集格式转换实战:VOC转YOLO txt,3步解决ZeroDivisionError
YOLOv5数据集格式转换实战VOC转YOLO txt的3个关键步骤与ZeroDivisionError解决方案1. 理解VOC与YOLO格式的本质差异在计算机视觉领域数据标注格式的转换是模型训练前的关键准备工作。VOCVisual Object Classes和YOLOYou Only Look Once是两种广泛使用的标注格式它们在数据结构上存在根本性差异。VOC格式采用XML文件存储标注信息每个XML文件对应一张图像包含以下核心元素annotation size width1920/width height1080/height /size object nameperson/name bndbox xmin100/xmin ymin200/ymin xmax300/xmax ymax400/ymax /bndbox /object /annotationYOLO格式则使用纯文本文件每个图像对应一个.txt文件每行表示一个对象格式为class_id x_center y_center width height其中坐标值都是相对于图像宽高的归一化数值0-1之间。两种格式的关键区别如下表所示特性VOC格式YOLO格式文件结构XML分层标签纯文本逐行记录坐标系统绝对像素值归一化相对值存储方式集中式单文件多对象分布式单文件单图像类名表示字符串数字ID提示YOLO格式的归一化特性使其对不同分辨率的图像具有更好的适应性这也是YOLOv5等现代目标检测器偏好此格式的原因。2. 三步完成VOC到YOLO格式的高效转换2.1 准备标准VOC目录结构确保原始数据集遵循VOC标准结构paper_data/ ├── Annotations/ # 存放XML标注文件 ├── images/ # 存放JPEG图像 └── ImageSets/ └── Main/ # 存放数据集划分文件使用以下Python脚本自动划分训练集、验证集和测试集import os import random def split_dataset(xml_path, txt_path, trainval_percent0.9, train_percent0.8): xml_files [f for f in os.listdir(xml_path) if f.endswith(.xml)] random.shuffle(xml_files) num len(xml_files) tv int(num * trainval_percent) tr int(tv * train_percent) trainval random.sample(xml_files, tv) train trainval[:tr] val trainval[tr:] test [f for f in xml_files if f not in trainval] os.makedirs(txt_path, exist_okTrue) def write_files(file_list, filename): with open(os.path.join(txt_path, filename), w) as f: for item in file_list: f.write(os.path.splitext(item)[0] \n) write_files(trainval, trainval.txt) write_files(train, train.txt) write_files(val, val.txt) write_files(test, test.txt)2.2 实现核心转换逻辑创建改进版的voc_label.py脚本重点解决ZeroDivisionError问题import xml.etree.ElementTree as ET import os def convert(size, box): 安全处理尺寸转换避免除零错误 width, height size if width 0 or height 0: return (0, 0, 0, 0) # 返回无效值后续会过滤 dw 1. / width dh 1. / height x (box[0] box[1]) / 2.0 - 1 y (box[2] box[3]) / 2.0 - 1 w box[1] - box[0] h box[3] - box[2] return (x * dw, y * dh, w * dw, h * dh) def convert_annotation(image_id, classes, input_dir, output_dir): in_file os.path.join(input_dir, f{image_id}.xml) out_file os.path.join(output_dir, f{image_id}.txt) if not os.path.exists(in_file): return False tree ET.parse(in_file) root tree.getroot() size root.find(size) try: w int(size.find(width).text) h int(size.find(height).text) except (AttributeError, ValueError): return False valid_objects [] for obj in root.iter(object): cls obj.find(name).text if cls not in classes: continue xmlbox obj.find(bndbox) b ( float(xmlbox.find(xmin).text), float(xmlbox.find(xmax).text), float(xmlbox.find(ymin).text), float(xmlbox.find(ymax).text) ) # 边界检查 b ( max(0, min(b[0], w)), max(0, min(b[1], w)), max(0, min(b[2], h)), max(0, min(b[3], h)) ) bb convert((w, h), b) if all(0 x 1 for x in bb): # 验证归一化值有效性 valid_objects.append(f{classes.index(cls)} { .join(map(str, bb))}) if valid_objects: with open(out_file, w) as f: f.write(\n.join(valid_objects)) return True return False2.3 批量处理与结果验证执行完整转换流程的主函数def main(): classes [person, car, dog] # 替换为实际类别 sets [train, val, test] abs_path os.getcwd() output_dir os.path.join(abs_path, labels) os.makedirs(output_dir, exist_okTrue) for image_set in sets: image_ids [] with open(fpaper_data/ImageSets/Main/{image_set}.txt, r) as f: image_ids.extend(line.strip() for line in f.readlines()) list_file open(fpaper_data/{image_set}.txt, w) for image_id in image_ids: img_path os.path.join(abs_path, fpaper_data/images/{image_id}.jpg) list_file.write(img_path \n) if convert_annotation(image_id, classes, paper_data/Annotations, output_dir): print(fSuccess: {image_id}) else: print(fSkipped invalid: {image_id}) list_file.close() if __name__ __main__: main()转换完成后检查生成的labels目录应包含与images目录对应的.txt文件每个文件格式如下0 0.4523 0.6712 0.1254 0.1589 1 0.7812 0.3421 0.0876 0.12343. 解决ZeroDivisionError的深度分析与进阶技巧3.1 错误根源剖析ZeroDivisionError通常由以下原因导致标注文件损坏XML中缺少width/height字段无效标注存在width0或height0的边界框解析错误XML格式不规范导致解析失败3.2 防御性编程实践在转换脚本中加入多重保护机制def safe_parse_xml(xml_path): try: tree ET.parse(xml_path) root tree.getroot() size root.find(size) if size is None: return None, (0, 0) width size.find(width) height size.find(height) if width is None or height is None: return None, (0, 0) return root, (int(width.text), int(height.text)) except Exception as e: print(fError parsing {xml_path}: {str(e)}) return None, (0, 0)3.3 自动化验证流程创建数据质量检查脚本import cv2 def validate_annotation(image_path, label_path, classes): image cv2.imread(image_path) if image is None: return False h, w image.shape[:2] with open(label_path, r) as f: for line in f: parts line.strip().split() if len(parts) ! 5: continue cls_id, x, y, bw, bh map(float, parts) if not (0 cls_id len(classes)): return False # 检查坐标是否在有效范围内 if not all(0 v 1 for v in [x, y, bw, bh]): return False # 转换为像素坐标验证 px int(x * w) py int(y * h) pwidth int(bw * w) pheight int(bh * h) if not (0 px w and 0 py h): return False return True4. 高效调试与性能优化4.1 常见问题排查表问题现象可能原因解决方案ZeroDivisionError无效的width/height添加边界检查和默认值处理缺失标注文件文件名不匹配实现严格的名称匹配逻辑坐标超出图像边界标注错误添加坐标裁剪功能类别ID越界classes列表不完整验证类别ID是否在有效范围内内存不足大文件批量处理分批次处理或使用生成器4.2 性能优化技巧并行处理使用多进程加速转换from multiprocessing import Pool def process_single(args): image_id, classes, input_dir, output_dir args return convert_annotation(image_id, classes, input_dir, output_dir) with Pool(processes4) as pool: results pool.map(process_single, [(id, classes, in_dir, out_dir) for id in image_ids])缓存机制避免重复解析XMLfrom functools import lru_cache lru_cache(maxsize1000) def get_xml_tree(xml_path): return ET.parse(xml_path)进度可视化使用tqdm显示进度from tqdm import tqdm for image_id in tqdm(image_ids, descProcessing): convert_annotation(image_id, classes, input_dir, output_dir)在实际项目中我发现使用改进后的转换脚本处理包含10,000张图像的数据集时处理时间从原来的15分钟缩短到3分钟以内同时完全消除了因数据质量问题导致的训练中断情况。

相关新闻

单应矩阵(Homography)3 大应用场景代码解析:图像校正、视角变换与 AR

单应矩阵(Homography)3 大应用场景代码解析:图像校正、视角变换与 AR

单应矩阵(Homography)3 大应用场景代码解析:图像校正、视角变换与 AR在计算机视觉领域,单应矩阵(Homography)是一个强大的数学工具,它描述了两个平面之间的投影变换关系。这种33的矩阵能够将一幅…

2026/7/6 12:41:21阅读更多 →
特征向量与特征值的工程本质:从手推到生产排障

特征向量与特征值的工程本质:从手推到生产排障

1. 为什么我坚持手推特征向量与特征值——一个数据科学老手的硬核复盘在数据科学团队做模型优化的第七年,我带过三届实习生,也给算法工程师做过内部培训。每次讲到PCA、SVD或者图神经网络的基础模块,总有人卡在“特征向量到底是什么”这一步。…

2026/7/6 12:36:21阅读更多 →
Stable Diffusion 3 图像生成实战:基于《穿石棉的人》描绘未来废墟的 5 个提示词工程技巧

Stable Diffusion 3 图像生成实战:基于《穿石棉的人》描绘未来废墟的 5 个提示词工程技巧

Stable Diffusion 3 图像生成实战:基于《穿石棉的人》描绘未来废墟的 5 个提示词工程技巧当科幻文学中的"沉寂的百老汇"、"永恒的衰败"这类抽象描述遇上Stable Diffusion 3的生成能力,我们面对的不仅是技术实现问题,更是…

2026/7/6 12:36:21阅读更多 →
3分钟解决Navicat试用期到期:Mac用户的无限重置指南

3分钟解决Navicat试用期到期:Mac用户的无限重置指南

3分钟解决Navicat试用期到期:Mac用户的无限重置指南 【免费下载链接】navicat_reset_mac navicat mac版无限重置试用期脚本 Navicat Mac Version Unlimited Trial Reset Script 项目地址: https://gitcode.com/gh_mirrors/na/navicat_reset_mac 当你正在处理…

2026/7/6 13:46:28阅读更多 →
EldenRingSaveCopier:三步完成艾尔登法环存档迁移的终极解决方案

EldenRingSaveCopier:三步完成艾尔登法环存档迁移的终极解决方案

EldenRingSaveCopier:三步完成艾尔登法环存档迁移的终极解决方案 【免费下载链接】EldenRingSaveCopier 项目地址: https://gitcode.com/gh_mirrors/el/EldenRingSaveCopier 在艾尔登法环的世界中,数百小时的游戏进度是每个褪色者最宝贵的财富。…

2026/7/6 13:46:28阅读更多 →
Kimi    LeetCode 3485. 删除元素后 K 个字符串的最长公共前缀 Java实现

Kimi LeetCode 3485. 删除元素后 K 个字符串的最长公共前缀 Java实现

以下是 LeetCode 3485 删除元素后 K 个字符串的最长公共前缀 的 Java 实现。思路核心思路是 Trie 线段树:1. 构建 Trie:将所有字符串插入字典树,每个节点记录 count(经过该节点的字符串数)和 depth(前缀长…

2026/7/6 13:46:28阅读更多 →
Kimi    LeetCode 3480. 删除一个冲突对后最大子数组数目 C语言实现

Kimi LeetCode 3480. 删除一个冲突对后最大子数组数目 C语言实现

以下是 LeetCode 3480 删除一个冲突对后最大子数组数目 的 C 语言实现。思路核心思路是枚举子数组右端点,维护当前最严格和次严格的冲突限制:1. 预处理:将每个冲突对 (a, b) 按较大值(即右端点)分组。对于子数组右端点…

2026/7/6 13:46:28阅读更多 →
agno-6-rag

agno-6-rag

什么是 RAG RAG(Retrieval Augmented Generation,检索增强生成) 是一种结合了信息检索和文本生成的技术,它通过在生成回答之前先从外部知识源检索相关信息,来增强大型语言模型(LLM)的能力。 RAG…

2026/7/6 13:46:28阅读更多 →
耐火 + 高防护母线槽结构解析:加厚绝缘、厚铝合金外壳、密封散热设计要点

耐火 + 高防护母线槽结构解析:加厚绝缘、厚铝合金外壳、密封散热设计要点

耐火 高防护母线槽结构解析:加厚绝缘、厚铝合金外壳、密封散热设计要点一、前言化工厂区、地下车库、高层建筑消防配电,对母线槽耐火性能、防尘防水防护等级要求严苛。母线槽外壳、绝缘层、散热密封结构是防火防水能力的核心载体。本文结合扬中金展电气…

2026/7/6 13:41:27阅读更多 →
从GitHub安全案例解析常见漏洞与防护实践

从GitHub安全案例解析常见漏洞与防护实践

1. 项目概述:从GitHub Trending看安全实战 最近在GitHub Trending上看到一个项目,叫 skills4/skills ,它因为一些安全漏洞案例被大家讨论。这其实是一个挺典型的场景:一个旨在展示或教授某种技能的仓库,本身却成了安…

2026/7/6 4:26:20阅读更多 →
MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

MLT 2026启示:因果推理与概率建模驱动下一代LLM应用

# MLT 2026启示:因果推理与概率建模驱动下一代LLM应用## 一、背景与挑战:从“黑箱预测”到“可信推理”2026年6月,第7届机器学习与趋势国际会议(MLT 2026)将在悉尼召开。会议议程中,“因果与可解释机器学习…

2026/7/6 2:48:33阅读更多 →
通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

通达OA SQL注入漏洞深度剖析:从手工注入到自动化利用与防御

1. 项目概述与漏洞背景最近在梳理一些历史OA系统的安全风险时,通达OA v11.6版本中的一个老漏洞又进入了我的视线。这个漏洞位于/general/bi_design/appcenter/report_bi.func.php文件中,是一个典型的SQL注入点。虽然这个漏洞的利用方式看起来并不复杂&am…

2026/7/6 0:10:35阅读更多 →
Seraphine:基于LCU API的英雄联盟智能游戏助手技术解析与应用指南

Seraphine:基于LCU API的英雄联盟智能游戏助手技术解析与应用指南

Seraphine:基于LCU API的英雄联盟智能游戏助手技术解析与应用指南 【免费下载链接】Seraphine 英雄联盟战绩查询工具 项目地址: https://gitcode.com/gh_mirrors/se/Seraphine 技术架构先行:官方接口的合规应用 你是否曾在BP阶段手忙脚乱&#x…

2026/7/6 0:03:39阅读更多 →
多协议远程连接管理工具mRemoteNG:告别混乱,统一你的远程桌面管理

多协议远程连接管理工具mRemoteNG:告别混乱,统一你的远程桌面管理

多协议远程连接管理工具mRemoteNG:告别混乱,统一你的远程桌面管理 【免费下载链接】mRemoteNG mRemoteNG is the next generation of mRemote, open source, tabbed, multi-protocol, remote connections manager. 项目地址: https://gitcode.com/gh_m…

2026/7/6 0:03:39阅读更多 →
COUNT(DISTINCT) 与 GROUP BY 去重统计:5 亿数据量下的性能实测与选型指南

COUNT(DISTINCT) 与 GROUP BY 去重统计:5 亿数据量下的性能实测与选型指南

COUNT(DISTINCT) 与 GROUP BY 去重统计:5 亿数据量下的性能实测与选型指南在数据分析和处理领域,去重统计是最基础也是最频繁使用的操作之一。当数据量达到亿级规模时,不同的去重统计方法在性能上可能产生天壤之别。本文将基于 5 亿行数据的实…

2026/7/6 0:03:39阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/6 4:45:01阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/6 4:45:01阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/6 4:45:03阅读更多 →