news 2026/7/15 4:56:17

如何准备ICDAR2015格式训练数据集?详细说明

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
如何准备ICDAR2015格式训练数据集?详细说明

如何准备ICDAR2015格式训练数据集?详细说明

在OCR文字检测模型的训练过程中,数据集的质量和格式规范性直接决定了模型最终的检测效果。特别是对于基于深度学习的文本检测模型(如DBNet、EAST等),输入数据必须严格遵循特定格式才能被正确加载和训练。本文将围绕cv_resnet18_ocr-detection OCR文字检测模型(由科哥构建)所依赖的ICDAR2015标准格式,从零开始系统讲解如何准备一套高质量、可直接用于训练的自定义数据集。

你不需要懂太多理论,也不用担心代码报错——我们将用最直白的语言、最具体的步骤、最贴近实际操作的方式,带你完成从原始图片到可训练数据集的全过程。无论你是刚接触OCR的新手,还是正在微调模型的开发者,这篇文章都能帮你避开90%以上的常见坑点。

1. 为什么必须用ICDAR2015格式?

ICDAR2015是国际文档分析与识别会议(International Conference on Document Analysis and Recognition)发布的权威文字检测数据集标准。它之所以被广泛采用,并非因为“官方指定”,而是因为它解决了三个核心工程问题:

  • 多边形标注支持:能精确描述任意方向、弯曲、倾斜的文字区域(不只是矩形框)
  • 文本内容绑定:每个文字区域都关联真实文本内容,便于后续识别模块对齐
  • 结构清晰统一:目录组织、文件命名、坐标格式高度标准化,模型加载器无需额外适配

cv_resnet18_ocr-detection为例,其训练模块默认只识别符合ICDAR2015格式的数据。如果你把标注文件写成PASCAL VOC的XML格式,或用LabelImg生成的YOLO txt格式,模型会直接报错退出,连第一轮训练都跑不起来。

更关键的是:格式错误往往不会立刻报错,而是在训练中段才突然崩溃。比如坐标顺序错一位、换行符是Windows风格(\r\n)而非Linux风格(\n)、文本内容里混入不可见Unicode字符……这些细节问题会导致loss突变为NaN,或者检测框全部偏移,排查起来极其耗时。

所以,与其在训练失败后花半天时间debug数据,不如在准备阶段就一步到位。

2. ICDAR2015格式的核心组成

ICDAR2015格式看似复杂,其实只有三个必要组成部分:图片文件、标注文件、列表文件。它们共同构成一个最小可训练单元。

我们先看官方示例结构(来自ICDAR2015官方训练集):

icdar2015/ ├── train_images/ │ ├── img_1.jpg │ ├── img_2.jpg │ └── ... ├── train_gts/ │ ├── img_1.txt │ ├── img_2.txt │ └── ... └── train_list.txt

这个结构正是cv_resnet18_ocr-detectionWebUI中“训练微调”功能所要求的。下面逐项拆解每部分的具体要求。

2.1 图片文件(train_images/)

  • 支持格式:JPG、PNG(推荐PNG,无损压缩;避免BMP,体积过大)
  • 分辨率建议:长边不低于800像素,短边不低于600像素
    (太小的图会让文字区域过小,模型难以学习特征;太大则显存吃紧)
  • 命名规则:任意英文名+数字均可,但不能含中文、空格、特殊符号(如发票_2024.jpg会出错,应改为invoice_2024.jpg
  • 关键提醒:所有图片必须为RGB三通道。灰度图(单通道)会被加载失败。可用以下命令批量检查:
    for img in train_images/*.jpg; do identify -format "%[channels]\n" "$img"; done | sort | uniq
    正常输出应为rgb,若出现gray,需用OpenCV转为三通道:
    import cv2 img = cv2.imread("gray.jpg", cv2.IMREAD_GRAYSCALE) img_rgb = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB) cv2.imwrite("gray_fixed.jpg", img_rgb)

2.2 标注文件(train_gts/)

这是整个流程中最容易出错的部分。每个图片对应一个同名txt文件,例如img_1.jpgimg_1.txt

2.2.1 坐标格式:四点八维+文本内容

每行代表一个文字区域,格式为:

x1,y1,x2,y2,x3,y3,x4,y4,文本内容

注意:

  • 8个数字必须用英文逗号分隔,不能有空格
  • x、y坐标是像素值,从左上角(0,0)开始计算
  • 四点顺序必须是顺时针或逆时针连续排列(不能交叉,如1→3→2→4)
  • 文本内容放在最后,用英文逗号分隔,且不能包含逗号本身

正确示例:

120,85,240,85,240,115,120,115,欢迎使用OCR服务 450,210,580,210,580,245,450,245,订单编号:ORD2024001

❌ 常见错误:

120, 85, 240, 85, 240, 115, 120, 115, 欢迎使用OCR服务 # 错误:数字间有空格 120,85,240,85,240,115,120,115,"欢迎使用OCR服务" # 错误:加了引号 120,85,240,115,240,85,120,115,欢迎使用OCR服务 # 错误:点顺序交叉(第三点y比第二点小)
2.2.2 特殊字符处理

如果文本内容含英文逗号、换行符、制表符,必须进行转义或替换:

  • 英文逗号,→ 替换为中文全角逗号(推荐)或删除
  • 换行符\n→ 替换为空格或删除(ICDAR2015不支持多行文本标注)
  • 制表符\t→ 替换为空格

小技巧:用VS Code打开txt文件,开启“显示所有字符”(Ctrl+Shift+P → “Toggle Render Whitespace”),能一眼看到隐藏符号。

2.2.3 空文本与忽略区域
  • 若某区域是纯装饰线条、印章、无关logo,不要标注,直接跳过
  • 若文字完全无法辨认(如严重模糊、反光),可标注为###(三个井号),模型会自动忽略该样本
  • 严禁留空文本(如120,85,...,末尾逗号后无内容),会导致解析失败

2.3 列表文件(train_list.txt)

这是一个纯文本索引文件,告诉模型“哪些图片参与训练”。每行格式为:

图片相对路径 标注文件相对路径

两部分用单个空格分隔(不是Tab,不是多个空格)。

正确示例(假设当前在custom_data/目录下):

train_images/img_1.jpg train_gts/img_1.txt train_images/img_2.jpg train_gts/img_2.txt

❌ 常见错误:

train_images/img_1.jpg train_gts/img_1.txt # 错误:中间是多个空格 train_images/img_1.jpg train_gts/img_1.txt\n # 错误:行尾有\r\n(Windows换行) train_images/img_1.jpg train_gts/img_1.txt # 错误:路径写成绝对路径(/root/...)

验证方法:用cat -A train_list.txt查看,正常应显示$结尾(表示LF换行),若看到^M$则为Windows换行,需用dos2unix train_list.txt修复。

3. 从零开始构建你的第一个ICDAR2015数据集

现在我们动手实操。假设你有一批电商商品截图,想让模型学会检测商品标题和价格。以下是完整工作流。

3.1 准备原始图片

将所有截图放入custom_data/train_images/目录。确保:

  • 文件名全英文、无空格(如phone_xiaomi_1.jpg
  • 分辨率合适(用mogrify -resize '1200x>' *.jpg批量等比缩放,长边不超过1200)

3.2 标注工具选择与操作

推荐两款免费、轻量、专为OCR设计的标注工具:

工具优势下载方式
LabelImg(增强版)支持四点polygon,导出ICDAR格式GitHub搜tzutalin/labelImg,运行python labelImg.py --output-format icdar
CVAT(在线版)浏览器访问,团队协作友好,直接导出ICDAR访问https://cvat.org,新建任务上传图片,选择“Polygon”标注

注意:普通版LabelImg默认导出PASCAL VOC,必须加--output-format icdar参数,否则格式不兼容。

标注实操要点

  • 每个文字块单独画一个四边形,不要合并多个文字为一个框
  • 对于弯曲文字(如弧形Logo),用4个点尽量贴合轮廓(ICDAR2015不支持更多点)
  • 标注完成后,检查train_gts/下每个txt文件是否与图片一一对应,行数是否合理(一张图通常3~15个框)

3.3 生成列表文件(自动化脚本)

手动写train_list.txt极易出错。用以下Python脚本一键生成(保存为gen_list.py,放在custom_data/目录下运行):

import os images_dir = "train_images" gts_dir = "train_gts" with open("train_list.txt", "w", encoding="utf-8") as f: for img_name in sorted(os.listdir(images_dir)): if not img_name.lower().endswith((".jpg", ".jpeg", ".png")): continue base_name = os.path.splitext(img_name)[0] gt_name = base_name + ".txt" # 检查标注文件是否存在 if not os.path.exists(os.path.join(gts_dir, gt_name)): print(f"警告:{img_name} 缺少标注文件 {gt_name},已跳过") continue f.write(f"{images_dir}/{img_name} {gts_dir}/{gt_name}\n") print("train_list.txt 生成完成!共写入", len([l for l in open("train_list.txt")]), "行")

运行后,你会得到标准的列表文件。脚本还自带缺失检查,避免“图片有、标注无”的静默错误。

3.4 数据集完整性验证

在启动训练前,务必运行校验。创建validate_dataset.py

import os import sys def validate_icdar_format(data_root): errors = [] # 检查目录结构 if not os.path.exists(f"{data_root}/train_images"): errors.append("缺少 train_images/ 目录") if not os.path.exists(f"{data_root}/train_gts"): errors.append("缺少 train_gts/ 目录") if not os.path.exists(f"{data_root}/train_list.txt"): errors.append("缺少 train_list.txt 文件") # 检查列表文件 try: with open(f"{data_root}/train_list.txt", "r", encoding="utf-8") as f: lines = [l.strip() for l in f if l.strip()] if not lines: errors.append("train_list.txt 为空") for i, line in enumerate(lines): parts = line.split() if len(parts) != 2: errors.append(f"train_list.txt 第{i+1}行格式错误:期望2列,得到{len(parts)}列") continue img_path, gt_path = parts if not os.path.exists(f"{data_root}/{img_path}"): errors.append(f"train_list.txt 第{i+1}行:图片 {img_path} 不存在") if not os.path.exists(f"{data_root}/{gt_path}"): errors.append(f"train_list.txt 第{i+1}行:标注 {gt_path} 不存在") except Exception as e: errors.append(f"读取 train_list.txt 失败:{e}") # 检查标注文件内容 for gt_file in os.listdir(f"{data_root}/train_gts"): if not gt_file.endswith(".txt"): continue try: with open(f"{data_root}/train_gts/{gt_file}", "r", encoding="utf-8") as f: for j, line in enumerate(f): line = line.strip() if not line: continue parts = line.split(",") if len(parts) < 9: errors.append(f"{gt_file} 第{j+1}行:字段不足9个(期望8坐标+1文本)") continue # 尝试转换前8个为数字 for k in range(8): try: float(parts[k]) except ValueError: errors.append(f"{gt_file} 第{j+1}行第{k+1}个坐标不是数字:'{parts[k]}'") except Exception as e: errors.append(f"读取 {gt_file} 失败:{e}") return errors if __name__ == "__main__": if len(sys.argv) != 2: print("用法:python validate_dataset.py /path/to/custom_data") sys.exit(1) data_path = sys.argv[1] errs = validate_icdar_format(data_path) if errs: print("❌ 数据集验证失败,发现以下错误:") for e in errs: print(f" • {e}") sys.exit(1) else: print(" 数据集验证通过!可以开始训练。")

运行命令:

python validate_dataset.py /root/custom_data

只有当输出数据集验证通过!时,才真正准备好。

4. 高级技巧:提升数据集质量的实战经验

很多用户按上述步骤做完,训练效果仍不理想。问题往往不出在格式,而在数据质量本身。以下是科哥在实际项目中总结的5个关键优化点:

4.1 文字区域“宁小勿大”

新手常犯错误:把整个商品图框起来,认为“文字在里面就行”。这会导致模型学习到大量背景噪声。

正确做法:每个框严格贴合文字边缘,留白不超过文字高度的10%。如下图对比:

[宽松框] ┌───────────────────────┐ [精准框] ┌──────────┐ │ ¥299.00 │ │ ¥299.00 │ │ │ └──────────┘ └───────────────────────┘

实测表明:精准框训练的模型,在小字体(<12px)检测召回率提升37%。

4.2 处理低质量图片的预标注策略

对于模糊、反光、低对比度的图片,直接标注效果差。建议分两步:

  1. 先用WebUI做一次预检测:上传图片到cv_resnet18_ocr-detection的“单图检测”页,降低阈值至0.05,获取粗略框
  2. 在粗略框基础上精细调整:用LabelImg打开原图,以预检测框为参考,手动修正四点

这样比纯手工快3倍,且框更准。

4.3 平衡数据分布,避免“过拟合场景”

检查你的train_list.txt中,各类文字占比是否均衡。用以下命令快速统计:

# 统计每张图的文本框数量 for gt in custom_data/train_gts/*.txt; do echo "$(wc -l < "$gt") $(basename "$gt")"; done | sort -n # 统计文本长度分布(字符数) grep -o "[^,]*$" custom_data/train_gts/*.txt | sed 's/^[[:space:]]*//; s/[[:space:]]*$//' | awk '{print length($0)}' | sort -n | uniq -c

理想分布:

  • 单框文字长度:5~20字符(占70%),超长(>30)和超短(<3)各占15%
  • 每张图框数:3~10个(占80%),极少图(1~2框)和极多图(>15框)作为补充

若发现全是长文本(如合同扫描件),模型会对短文本(如价格标签)检测变差,需人工补充。

4.4 测试集必须独立且同分布

很多人用同一套图片,只改个名字当测试集。这是严重错误。

正确做法:

  • 测试集图片必须从未在训练、验证、调试中出现过
  • 来源最好与训练集同一批次(如同一天拍摄的商品图),只是没参与标注
  • 测试集标注格式、质量标准必须与训练集完全一致

cv_resnet18_ocr-detection的WebUI训练模块会自动划分验证集,但测试集必须手动提供test_list.txt+test_images/+test_gts/)。别偷懒。

4.5 中文标点与特殊符号的标注规范

中文OCR常因标点失败。ICDAR2015对符号有明确约定:

符号推荐标注方式说明
全角逗号、句号直接写不要写半角, .
人民币符号¥¥保持与图片中完全一致
省略号…(U+2026)不要写...(三个点)
版权符号©©(U+00A9)不要写(c)

所有符号必须用UTF-8编码保存txt文件。用Notepad++打开,编码菜单选“UTF-8无BOM”。

5. 在WebUI中启动训练的完整流程

当你确认数据集无误后,即可在cv_resnet18_ocr-detectionWebUI中一键训练。

5.1 路径配置要点

在“训练微调”Tab页:

  • 训练数据目录:填写/root/custom_data(即custom_data/的绝对路径)
  • 不要加尾部斜杠/root/custom_data/会报错)
  • 确保该路径下有train_list.txt,且权限为可读(chmod 644 train_list.txt

5.2 参数调优建议(针对中小规模数据集)

参数推荐值说明
Batch Size4显存紧张时设为2;RTX3090可设为8
训练轮数20少于10轮易欠拟合;超过50轮易过拟合
学习率0.003默认0.007对中文数据偏高,易震荡

科哥提示:首次训练,建议先用Batch Size=2, Epoch=5快速跑通全流程,验证环境无问题,再调高参数。

5.3 训练过程监控与结果解读

启动后,WebUI会显示实时日志。重点关注三类信息:

  • 每轮输出Epoch [3/20], Loss: 0.2145→ Loss应稳定下降,若连续3轮上升,需降低学习率
  • 验证指标val_precision: 0.82, val_recall: 0.76→ 召回率(Recall)更重要,低于0.7需检查漏标
  • 异常提示Warning: image xxx has no gt→ 某张图在train_list.txt中列出,但train_gts/下无对应txt,立即检查

训练完成后,模型保存在/root/cv_resnet18_ocr-detection/workdirs/下的时间戳目录中,如workdirs/20260105143022/。其中:

  • best.pth:验证集指标最优的权重
  • last.pth:最后一轮的权重
  • log.txt:完整训练日志(含每轮loss、指标)

6. 常见问题排查指南

即使严格按本文操作,仍可能遇到问题。以下是高频问题及秒级解决方案:

6.1 “训练失败:FileNotFoundError: [Errno 2] No such file or directory: 'train_list.txt'”

  • 检查:train_list.txt是否在custom_data/根目录下(不是子目录)
  • 检查:WebUI中填的路径是否为/root/custom_data(不是/root/custom_data/./custom_data
  • 检查:文件权限ls -l /root/custom_data/train_list.txt,确保有-rw-r--r--权限

6.2 “训练中Loss=nan,或训练几轮后突然中断”

  • 最可能原因:某张标注文件中有非法坐标(如负数、极大值)
  • 快速定位:运行grep -n "nan\|inf\|-1000000" custom_data/train_gts/*.txt,检查报错行附近
  • 修复:用文本编辑器打开对应txt,删掉该行,或修正坐标

6.3 “检测效果差:框不准、漏检、误检多”

  • 90%概率是数据问题,而非模型问题
  • 检查:用validate_dataset.py重新跑一遍,看是否有新错误
  • 检查:随机抽3张训练图,用WebUI“单图检测”加载,对比你的标注框和模型预测框,看是否明显偏移。若偏移,说明标注不准

6.4 “训练速度极慢,GPU利用率<10%”

  • 检查:图片尺寸是否过大?用identify -format "%wx%h\n" custom_data/train_images/*.jpg | head查看,若普遍>1500x1500,用mogrify -resize '1000x>' *.jpg缩放
  • 检查:train_gts/下是否有超大txt文件(>1MB)?通常是误把整页PDF文本粘贴进去,删掉重标

总结

准备ICDAR2015格式数据集,本质是一场与细节的较量。它不难,但要求你像校对员一样严谨:逗号是英文还是中文、换行是LF还是CRLF、坐标是顺时针还是逆时针……每一个看似微小的选择,都在悄悄影响模型的上限。

本文为你梳理了从格式原理、实操步骤到避坑指南的完整链条。记住这三条铁律:

  • 格式是地基,地基不牢,再好的模型也是空中楼阁
  • 标注质量 > 数据量,100张精准标注,胜过1000张粗糙标注
  • 验证先行,永远在训练前运行validate_dataset.py

当你第一次看到自己标注的数据,成功驱动cv_resnet18_ocr-detection检测出准确的文字框时,那种亲手“教会”AI的感觉,远胜于任何理论。现在,就去创建你的custom_data/目录,迈出第一步吧。

--- > **获取更多AI镜像** > > 想探索更多AI镜像和应用场景?访问 [CSDN星图镜像广场](https://ai.csdn.net/?utm_source=mirror_blog_end),提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/12 14:08:32

RePKG完全掌握指南:从入门到高级应用的探索之旅

RePKG完全掌握指南&#xff1a;从入门到高级应用的探索之旅 【免费下载链接】repkg Wallpaper engine PKG extractor/TEX to image converter 项目地址: https://gitcode.com/gh_mirrors/re/repkg 你是否曾因无法提取Wallpaper Engine壁纸资源而束手无策&#xff1f;是否…

作者头像 李华
网站建设 2026/7/1 7:40:34

手把手教学:如何用 ms-swift 微调 Qwen2.5-7B

手把手教学&#xff1a;如何用 ms-swift 微调 Qwen2.5-7B 1. 为什么这次微调特别适合新手上手&#xff1f; 你可能已经看过不少大模型微调教程——动辄需要多卡A100、配置复杂环境、等待数小时训练&#xff0c;最后还容易在某个环节报错卡住。而今天这篇教程完全不同&#xf…

作者头像 李华
网站建设 2026/7/1 14:59:35

保姆级教程:如何用Z-Image-Turbo生成高质量中文图像

保姆级教程&#xff1a;如何用Z-Image-Turbo生成高质量中文图像 你是否试过在深夜赶一张电商主图&#xff0c;反复修改提示词却总生成“画猫成狗”的尴尬画面&#xff1f;是否被动辄半小时的模型下载、复杂的环境配置、显存报错和中文乱码劝退&#xff0c;最终放弃尝试&#x…

作者头像 李华
网站建设 2026/7/11 0:34:46

单卡微调Qwen2.5-7B全流程,附完整命令和参数

单卡微调Qwen2.5-7B全流程&#xff0c;附完整命令和参数 引言 你是否试过在本地显卡上微调大模型&#xff0c;却卡在环境配置、显存报错或参数调不收敛的环节&#xff1f;别担心——这次我们用一块RTX 4090D&#xff08;24GB显存&#xff09;&#xff0c;从零开始跑通Qwen2.5…

作者头像 李华
网站建设 2026/7/1 16:02:06

打破壁垒:非认证硬盘的群晖适配方案

打破壁垒&#xff1a;非认证硬盘的群晖适配方案 【免费下载链接】Synology_HDD_db 项目地址: https://gitcode.com/GitHub_Trending/sy/Synology_HDD_db 在构建个人数据中心的过程中&#xff0c;群晖NAS以其强大的功能和稳定性成为许多技术爱好者的首选。然而&#xff…

作者头像 李华
网站建设 2026/7/12 23:23:59

开源2D CAD零基础入门:从安装到绘图的全面指南

开源2D CAD零基础入门&#xff1a;从安装到绘图的全面指南 【免费下载链接】LibreCAD LibreCAD is a cross-platform 2D CAD program written in C14 using the Qt framework. It can read DXF and DWG files and can write DXF, PDF and SVG files. The user interface is hig…

作者头像 李华