cv_resnet18_ocr-detection训练集怎么准备?ICDAR格式详解
OCR文字检测模型的训练效果,八成取决于数据——不是模型多深、参数多大,而是你喂给它的数据够不够“懂行”。cv_resnet18_ocr-detection 这个轻量但实用的检测模型,由科哥基于ResNet-18主干网络构建,专为中文场景优化,在服务器资源有限、需快速落地的中小项目中表现稳定。它不追求SOTA榜单排名,但胜在部署简单、推理快、微调门槛低。而这一切的前提,是你能准备好一份结构清晰、标注规范、即插即用的训练集。
很多人卡在第一步:训练集到底怎么组织?文件放哪?txt里怎么写?为什么模型报错说“找不到gt”或“坐标解析失败”?其实问题往往不出在代码,而出在数据格式的“隐形约定”上。本文不讲模型原理,不堆公式,就聚焦一个最实在的问题:如何亲手搭出一份能让 cv_resnet18_ocr-detection 顺利读取、正确训练的 ICDAR 格式数据集。从零开始,手把手带你把一张图、一行字,变成模型能理解的“语言”。
1. 为什么是ICDAR格式?不是JSON,也不是YOLO?
先说结论:这不是技术偏见,而是工程妥协后的最优解。
ICDAR(International Conference on Document Analysis and Recognition)作为OCR领域最权威的评测组织,其2015年发布的文本检测数据集(ICDAR2015 Incidental Scene Text)已成为行业事实标准。它的标注方式——用8个数字定义一个四边形文本框——天然适配自然场景中倾斜、弯曲、透视变形的文字,比矩形框(如YOLO的xywh)更精准,又比复杂多边形(如COCO的segmentation)更轻量易用。
cv_resnet18_ocr-detection 的训练脚本直接兼容ICDAR2015格式,意味着你无需额外写转换器、不需改一行代码,只要目录结构对、txt内容对,就能开跑。相比之下:
- JSON格式虽灵活,但需自定义解析逻辑,容易因字段名、嵌套层级出错;
- YOLO格式(txt每行5个数)只支持水平矩形,对倾斜招牌、旋转票据几乎无效;
- COCO格式过于重型,对单任务OCR属于“杀鸡用牛刀”,且加载慢。
所以,选ICDAR,不是因为它最先进,而是因为它最省心、最可靠、最不容易踩坑。你的精力,应该花在拍好图、标准写对上,而不是和数据加载器死磕。
2. ICDAR2015格式核心:一张图,一个txt,八数字,一串字
ICDAR2015的标注精髓,就藏在这一行文本里:
x1,y1,x2,y2,x3,y3,x4,y4,文本内容别被8个数字吓到,它只是按顺时针(或逆时针)顺序,把你用鼠标框出来的文本区域四个顶点的坐标,原封不动记下来。我们拆开看:
2.1 坐标怎么数?从左上角开始,顺时针画圈
想象你正用画图工具框选一段文字。起笔点(第一个点)通常是左上角顶点,然后依次是右上角→右下角→左下角。这四个点连起来,就是一个紧贴文字边缘的四边形。
举个真实例子:
一张发票图片中,“金额:¥1,234.56”这几个字被框选,标注文件1.txt内容如下:
124,87,392,89,390,125,122,123,金额:¥1,234.56对应关系:
(124,87)→ 左上角(文字起始位置)(392,89)→ 右上角(文字结束位置上方)(390,125)→ 右下角(文字结束位置下方)(122,123)→ 左下角(文字起始位置下方)
关键提醒:坐标必须是整数,单位是像素;顺序必须严格,不能颠倒;逗号后不能有空格;文本内容可以含中文、英文、数字、符号,但不能换行。
2.2 多行文字?那就多写几行
一张图里有10行字?没问题。1.txt里就写10行,每行一个四边形+文本:
45,132,287,135,285,178,43,175,客户名称:北京智创科技有限公司 48,192,290,195,288,238,46,235,地址:朝阳区建国路8号SOHO现代城A座 ...避坑指南:
- 如果某行文字被遮挡、模糊到无法识别,宁可不标,也不要乱填。模型会学“假知识”;
- 空格、制表符、全角/半角混用会导致解析失败,建议用VS Code打开txt,开启“显示空白字符”功能检查;
- 文本内容里如果本身含逗号(如“苹果,香蕉”),目前版本不支持转义,建议改用顿号或空格替代。
3. 数据集目录结构:四层铁律,少一层都报错
格式对了,目录乱了照样训练失败。cv_resnet18_ocr-detection 要求数据集必须严格遵循以下结构(注意大小写和斜杠方向):
custom_data/ ├── train_list.txt # 必须存在,训练集清单 ├── train_images/ # 必须存在,存放所有训练图 │ ├── 1.jpg │ ├── 2.png │ └── 3.bmp ├── train_gts/ # 必须存在,存放所有训练标注 │ ├── 1.txt │ ├── 2.txt │ └── 3.txt ├── test_list.txt # 必须存在,测试集清单(可为空) ├── test_images/ # 必须存在,测试图片目录 │ └── 4.jpg └── test_gts/ # 必须存在,测试标注目录 └── 4.txt3.1 四个“必须存在”的目录,缺一不可
即使你只有训练数据,test_images/和test_gts/也得建空文件夹;即使测试集为空,test_list.txt也得存在(可为空文件)。这是训练脚本硬性校验逻辑,跳不过。
3.2 列表文件:路径是相对的,不是绝对的
train_list.txt不是写/root/custom_data/train_images/1.jpg,而是写相对于custom_data/目录的相对路径:
train_images/1.jpg train_gts/1.txt train_images/2.png train_gts/2.txt train_images/3.bmp train_gts/3.txt每行两个字段,用空格分隔,不是制表符,不是逗号。第一列是图片路径,第二列是对应标注txt路径。路径里不能有中文(避免编码问题),推荐全英文+数字命名。
实操技巧:
在Linux终端进入custom_data/目录,用这条命令自动生成train_list.txt:for img in train_images/*; do base=$(basename "$img" | sed 's/\.[^.]*$//'); echo "$img train_gts/${base}.txt"; done > train_list.txt它会自动匹配同名jpg/png/bmp与txt,省去手动敲100行。
4. 从零开始:三步搭建你的第一份训练集
现在,把前面所有规则串起来,动手做一份最小可用数据集。不需要100张图,3张就够验证流程。
4.1 第一步:准备3张图,命名规范
找3张带文字的清晰图片(截图、拍照、扫描件均可),重命名为1.jpg,2.jpg,3.jpg,放进train_images/文件夹。确保:
- 分辨率不低于640×480(太小的图,文字像素不足,模型学不到特征);
- 文字区域占画面1/5以上(避免“大海捞针”式训练);
- 避免纯黑底白字(部分预处理会失效),优先选白底黑字或灰度图。
4.2 第二步:手写3个txt,严格按格式
用记事本或VS Code,新建1.txt,2.txt,3.txt,放进train_gts/。内容示例(以1.txt为例):
85,142,423,145,421,188,83,185,订单编号:ORD20260105001 92,210,430,213,428,256,90,253,下单时间:2026-01-05 14:30:22 105,278,267,281,265,324,103,321,收货人:张伟验证方法:用Python快速检查格式是否合法:
with open("train_gts/1.txt", "r", encoding="utf-8") as f: for i, line in enumerate(f, 1): parts = line.strip().split(",") if len(parts) != 9: print(f"第{i}行错误:应有9个字段,实际{len(parts)}个") try: coords = list(map(int, parts[:8])) except ValueError: print(f"第{i}行错误:前8个字段必须为整数")
4.3 第三步:生成列表文件,启动训练
在custom_data/目录下,创建train_list.txt,内容为:
train_images/1.jpg train_gts/1.txt train_images/2.jpg train_gts/2.txt train_images/3.jpg train_gts/3.txt再建空的test_list.txt,以及空的test_images/和test_gts/文件夹。
回到WebUI的“训练微调”页,输入路径/root/custom_data,点击“开始训练”。如果看到日志里滚动出现Epoch 1/5,loss: 0.421...,恭喜,你的数据集已成功激活!
5. 高阶技巧:让数据集更“聪明”,不止于能跑
数据集合格只是起点。想让模型在你的业务场景中真正好用,还得加点“调料”。
5.1 数据增强:不是加图,是加“变化”
cv_resnet18_ocr-detection 内置了基础增强(随机裁剪、色彩抖动),但针对中文场景,建议手动补充:
- 字体多样性:收集不同字体(微软雅黑、思源黑体、宋体)的合成文本图,避免模型只认某一种字形;
- 背景复杂化:把文字P到办公桌、工厂流水线、手机屏幕等背景上,提升抗干扰能力;
- 噪声模拟:用OpenCV给图加高斯噪声、运动模糊,模拟手机拍摄抖动。
低成本方案:用Python脚本批量生成(示例):
from PIL import Image, ImageDraw, ImageFont import numpy as np import cv2 # 生成一张带文字的合成图 img = Image.new('RGB', (800, 600), color='white') draw = ImageDraw.Draw(img) font = ImageFont.truetype("simhei.ttf", 32) # 中文字体 draw.text((100, 100), "测试文字:OCR很强大!", fill='black', font=font) # 加点噪声 img_np = np.array(img) img_noisy = cv2.randn(img_np, 0, 10) # 高斯噪声 Image.fromarray(img_noisy).save("synth_1.jpg")
5.2 难例挖掘:专治“总漏检”的顽疾
训练几轮后,用验证集跑一遍,找出模型总漏掉的图。把这些图单独拎出来,人工重新精标:
- 检查是否漏标了小字号、浅灰色文字;
- 把原本标成一个框的长段落,拆成多个短框(如地址拆为“省”、“市”、“区”、“路”);
- 对模糊文字,放大后标,哪怕坐标稍不准,也比不标强。
这些“难例”组成的子集,加入训练集后,准确率提升往往比加100张普通图还明显。
6. 常见报错与秒级修复方案
训练启动失败?90%是数据集问题。这里整理高频报错及对应解法:
| 报错信息(日志片段) | 根本原因 | 30秒修复方案 |
|---|---|---|
FileNotFoundError: [Errno 2] No such file or directory: 'train_images/1.jpg' | train_list.txt里写的路径和实际文件名不一致 | 进入train_images/目录,执行ls看真实文件名,修正train_list.txt |
ValueError: could not convert string to float: 'abc' | txt某行前8个字段含非数字字符(如中文逗号、空格) | 用VS Code打开对应txt,开启“显示所有字符”,删掉隐藏符号 |
IndexError: list index out of range | txt某行字段数≠9(常见于最后一行空行) | 删除txt文件末尾所有空行,保存 |
AssertionError: image size mismatch | 图片宽高比极端(如100×2000),超出模型预设范围 | 用convert -resize 1200x800^ -gravity center -extent 1200x800 1.jpg统一缩放 |
终极排查口诀:
一看路径(list文件)、二看文件(图片和txt是否存在)、三看内容(txt每行9字段、前8个是整数)、四看编码(txt用UTF-8无BOM保存)。
7. 总结:数据是模型的土壤,格式是土壤的pH值
cv_resnet18_ocr-detection 不是一个需要你精通PyTorch才能驾驭的庞然大物。它的价值,恰恰在于把复杂的OCR检测,封装成一个“数据驱动”的黑盒:你提供符合ICDAR规范的图片与标注,它就还你一个能干活的模型。而这份规范,不是束缚,而是护栏——它确保你投入的时间,不会浪费在无意义的调试上。
记住三个动作:
严格按8坐标+文本写txt,用顺时针顺序,整数,无空格;
死守四层目录结构,train_images/、train_gts/、train_list.txt一个都不能少;
用最小集(3张图)先跑通,验证流程,再逐步扩充。
当你第一次看到自己标的数据,让模型成功框出“发票金额”四个字时,那种“我造出来了”的踏实感,远胜于读十篇论文。OCR落地,从来不是玄学,它就藏在你新建的那个txt文件里。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。