首页 / 资讯中心 / 文章详情

用PPOCRLabel做OCR数据标注:从半自动标注到训练集生成

用PPOCRLabel做OCR数据标注:从半自动标注到训练集生成 ★ FEATURED ARTICLE
做OCR项目真正劝退人的往往不是模型选型而是标注。之前做个票据识别的小项目整批图片里有表格线、印章、倾斜文字和低对比度字迹一开始用通用标注工具拖矩形框、手敲文本一个小时只能出二十来张图眼睛全是黢黑。后来换成PPOCRLabel先用模型自动把检测框和识别结果跑一遍人工再修正和确认同一批数据直接缩到三分之一的工作量。这篇文章我就把这套流程完整写下来怎么装上、怎么启动、怎么把一张图从打开到导出标注以及格式和训练集怎么对接最后还有我自己踩过的几个坑给正在做OCR数据准备的人一份可以直接照着操作的参考。1. 标注是OCR项目里最容易被低估的环节1.1 公开数据集和真实业务数据的错位很多人一开始做OCR习惯直接拿公开数据集训练比如各种打印体、标准排版、街景文字之类的评测集。这类数据确实干净文字区域工整、背景简单、方向一致。但放到实际项目里情况马上不一样票据上有红章压着汉字快递面单上字体小而且排列紧密屏幕截图里还有深色底纹铭牌照片拍出来是斜的再加上反光、污渍、贴纸。你在公开模型上看到“精度很高”换到真实场景就崩掉就是因为训练数据和你业务数据分布不一样。这时候唯一的出路就是拿一批真实图片做域内标注让模型知道你的场景长什么样。标注这件事在整个OCR流程里其实占了相当大比重不只是“画个框”那么简单检测框怎么画、文本怎么转写、难例怎么处理都会直接影响后面的训练效果。而我为什么选PPOCRLabel而不是那些更通用的标注工具下一节说清楚。1.2 PPOCRLabel在同类工具里的生态位市面上能用的标注工具不少常见的是LabelImg和Labelme还有商业平台。我拿自己实际用过的感受对比一下工具支持框类型自动检测识别联动导出是否贴合OCR训练LabelImg水平矩形无无需要自己转换Labelme多边形/矩形无无通用JSON格式要二次处理PPOCRLabel四边形四点框有有直接导出PaddleOCR训练常用格式LabelImg拖框很快但只有轴对齐矩形遇到倾斜文字就没法标Labelme能画多边形但画完还得自己写脚本转成OCR训练格式而且没有模型辅助效率低。PPOCRLabel是PaddleOCR生态里的标注工具最大的区别是它直接把检测模型和识别模型接进了标注流程图片打开它可以先框出一组候选文本区域再对每个框给出预测文本人工只需要在候选结果上做删减、修改和确认。这不止是省了画框的力气连键盘输入也省掉一大截。我用的版本是PaddleOCR仓库里自带的那套它可以导出后面训练直接能用的数据集结构。商业标注平台我也试过几个流程确实完善但自定义字段和格式导出有时候还被平台限制而且涉及数据安全很多项目的图片根本不方便传到云端。PPOCRLabel本地运行离线工作这点对所有有保密要求的业务都非常友好。1.3 半自动标注的现实收益半自动标注到底省多少我觉得不能只看“省了多少分钟”得看整条流水线。假设一张图里有六个需要标注的文本区域全手动标注要做的事情是画六个框、输入六段文本、检查六个框是否漏掉、保存。每一步都有人工操作一张图两分钟很正常。用PPOCRLabel以后正常清晰图片上模型自动检测基本能覆盖九成以上区域人工做的事变成把漏掉的框补上把歪的角点拖正把自动识别出来但错的文本改掉再把多余的误检框删掉。熟练以后一张图三十到五十秒能完成遇到质量更差的图片会慢一些。而且当模型在标注过程中反复接收人工修正结果我往往会每隔一段时间重新生成一次检测模型效果会继续变好标注速度会进一步上升。这个正循环才是它真正值得用的地方。2. 环境准备阶段我最想提前告诉你的三件事2.1 安装步骤和版本选择安装PPOCRLabel之前先确认机器上有没有Python环境。个人经验是尽量用conda建一个干净的环境避免和系统自带的Python互相污染。我一般这么建conda create -n paddle python3.9 -y conda activate paddle pip install paddlepaddle -i https://pypi.tuna.tsinghua.edu.cn/simple git clone https://github.com/PaddlePaddle/PaddleOCR.git cd PaddleOCR pip install -r requirements.txt cd PPOCRLabel python PPOCRLabel.py --lang ch这里有个容易被忽略的地方paddlepaddle是CPU版本如果你的机器有NVIDIA显卡想标注大图更流畅应该装GPU版比如paddlepaddle-gpu。PPOCRLabel的自动检测和识别都要跑模型CPU也能跑但大图多的时候明显吃力GPU能让体验提升一个档次。版本选择上我的建议是不要盲目追最新先看你目标训练生态的PaddleOCR版本。仓库不同分支可能对应不同版本启动脚本的参数也会有细微变化。之前看到有人拿新版的预训练模型放到旧版工具里用结果检测框出不来其实是模型结构不匹配不是代码问题。如果你只想标注数据不研究新特性选择和你训练计划一致的分支最省心。2.2 模型文件从哪里来PPOCRLabel第一次启动时会用到一个检测模型和一个识别模型默认会根据--lang ch参数决定下载中文模型。模型文件会放在用户目录的.paddleocr文件夹下面具体路径根据版本不同略有差异。如果你的网络环境不太稳定模型下载可能失败程序会一直卡在“下载模型”的界面。这时候别干等直接手动把对应模型文件下载好放到它期望的目录下再启动。我常用的做法是先让它启动一次然后从日志里看它具体去哪个路径找模型再把模型压缩包解压到那个路径下面重新启动程序。需要注意模型文件名和目录层级都不能随意改动否则程序识别不出来。2.3 启动失败最常见的几种情况我帮朋友看过的启动问题基本集中在下面几个症状常见原因解决办法启动后界面一闪而过缺少系统图形库安装libGL相关依赖后再试报No module named skimagerequirements没装全在PaddleOCR目录下重新装依赖窗口打开但加载图片就报错路径里有中文或特殊空格把工程目录改成纯英文路径自动检测按钮没有反应模型没有下载成功检查.paddleocr目录下的模型是否完整检测结果全是空白框检测模型和工具版本不匹配换成对应版本的模型文件这些看起来都是小问题但每一个都能让人折腾半天。最稳妥的做法是严格按照仓库文档的依赖安装不要跳过任何一条。尤其是只用pip install paddleocr而不clone仓库的同学后面启动PPOCRLabel经常缺这缺那我实际用下来还是clone源码最完整。3. 第一次完整标注流程从打开图片到导出标注3.1 图片目录的准备启动PPOCRLabel后左侧是图片列表右侧是两个面板一个放检测框候选列表另一个放识别文本输入。第一次使用建议先把图片整理到一个干净的文件夹里图片命名最好规则化比如001.jpg、002.jpg不要用特别长的中文名也不要混合存放不同来源的图片。图片格式方面JPG和PNG是最稳的只要读取没问题基本都可以。要注意的是图片尺寸如果单张图超过四五千万像素加载和模型推理都会很慢建议先对超大图做切片处理标注完成后再把切片的标注坐标换算回原图。这一步很多人会忽略结果标注到一半程序卡死前功尽弃。3.2 自动检测和人工框选怎么配合图片打开以后最省事的操作是先点自动检测。工具会用检测模型把当前图片里看起来像是文字的区域标出来然后把结果列在右侧列表里。正常情况下票据、单据这类版式相对固定的图片检测框命中率很高。自动检测不可能完全可靠我的习惯是把它当作“初稿”然后人工逐条检查。如果发现漏检的区域用手动框选补上如果发现误检的区域比如把印章、条形码、背景纹理框进去了直接删掉。框选的时候尽量贴着文字边缘不要留大片空白也不要切到文字中间这在后面训练质量里是硬指标。手动绘制框的时候PPOCRLabel用的是四点四边形不是简单的水平矩形。也就是说你可以沿着倾斜文字的方向点出四个角点框跟着文字走而不是等图片旋转之后再画。这一点非常重要因为实际场景里大量文本是倾斜的用轴对齐矩形会圈进很多干扰像素。3.3 识别文本用模型还是手输框确定以后右侧要填这段框对应的文本内容。PPOCRLabel可以和识别模型联动自动把框里的文字识别出来填到对应的文本框里。此时人工要做的是检查识别结果有没有错字、漏字和多余字符。我见过很多人偷懒自动识别出来就不看了结果训练文本里全是错别字和多余空格模型精度一路狂跌。正确做法是哪怕自动识别看起来很好也要对一遍。遇到模糊、低对比度、生僻字、特殊编号就直接手动输入。手动输入时注意不要带额外的左右空格标点符号按图片实际内容保留看不清的字符宁可标注成难例也不要硬编造一个字符进去。3.4 快捷键的正确打开方式PPOCRLabel的快捷键在不同版本之间会有变化所以我不会给你写一串死键位。你要做的是打开软件后看一眼“帮助”菜单或者界面上悬停提示先搞清楚当前版本里“创建框、删除框、切换下一张、确认标签”这些动作分别绑在哪些按键上。我自己的使用习惯是把最高频的几个动作固定成肌肉记忆新建框、删除误检框、保存当前标注、切到下一张。这四个动作一天要重复几百次如果每次都点鼠标菜单效率会低很多。同样重要的是小心误触我曾经连续按错键删掉了已经标注好的框后来养成了每标注完几张就立刻保存一次的习惯。4. 决定训练效果的标注质量规范4.1 文本框怎么画才算规范标注规范这件事比工具本身更容易被忽略但它的影响非常直接。检测框画得是否规范决定了模型在检测阶段能不能把文字区域和背景分开文本转录是否准确决定了识别模型能不能学到正确的字符序列。我订过一套自己的标注规矩核心原则只有三条框住文字主体不要框大背景一个语义完整的文本区域不要拆成多个框一行文字有轻微弯曲时用四个角点尽量贴合文字走向。举个例子发票上“金额”两个字如果你只框“金额”这两个汉字那没问题因为这是独立语义但如果一行文字是“发票号码12345678”最合理的做法是整个框住这一行而不是把“发票号码”和“12345678”拆成两个框。拆框会让模型把局部字符组合当成固定样本训练出来的识别结果反而不稳定。4.2 方向、特殊结构到底怎么处理倾斜是OCR标注里最常遇到的情况。PPOCRLabel支持画四点斜框所以不用提前旋转图片但你要保证框内的文本在训练数据里是“可读方向”的。什么意思就是框里那一串字的阅读顺序应该和人眼看到的阅读顺序一致不能左一个右一个乱排。多行文本的问题要特别小心。如果一个文本框里包含两行文字我的建议是拆成两个检测框每行一个每个框单独转录。因为现在主流OCR识别链路里检测和识别模型基本按“行”来理解文本你把多行塞进一个框识别模型很容易把它当成一整段连续字符来学效果一般不好。遇到印章压字、文字被污渍覆盖、或者文本只有一半的情况我建议不要强行输入完整文本而是标记成难例。PPOCRLabel的导出格式里保留了difficult字段把这类样本标出来训练时可以对这些难例做特殊处理提升模型在复杂场景下的鲁棒性。4.3 空转录和错转录是最大的隐性雷区标注数据里最隐蔽的问题不是框画歪了而是有些框的转录文本是空的或者文本里混入了不可见字符。空转录常见于自动检测后漏掉了识别环节你在检查框的时候没注意到右侧文本框是空的就保存了不可见字符则常见于文本在中间环节被复制粘贴过混入了制表符、换行符和全角空格。我写了一个最简单的校验脚本在导出后扫描一遍数据把所有“有框但没有转录文本”的样本找出来这个动作已经救过我很多次。脚本核心思路就是逐行读取标注文件解析出每个框和转录文本如果发现转录为空就打印出对应的图片路径提醒复查。import json from pathlib import Path label_file Path(Label.txt) bad_items [] for line in label_file.read_text(encodingutf-8).splitlines(): parts line.split(\t, 1) if len(parts) 2: bad_items.append((line, 缺少标注内容)) continue image_path, content parts[0], parts[1] try: boxes json.loads(content) except Exception: bad_items.append((image_path, JSON解析失败)) continue for box in boxes: text box.get(transcription, ) if not text.strip(): bad_items.append((image_path, 空转录)) print(f发现 {len(bad_items)} 个可疑样本) for item in bad_items[:30]: print(item)每次导出前跑一遍这个脚本能省掉大量返工时间。文本里如果出现肉眼都看不出来的不可见字符后续训练时报错或字表对不上排查成本非常高。5. 导出文件的底层格式与训练管线对接5.1 一次导出会得到什么标注工作完成以后点击导出工具会在你图片目录下生成一套训练用的数据文件。不同版本导出细节略有差异但我用到的版本会生成这样几个东西Label.txt、一个crop_img目录以及Rec_gt.txt。Label.txt是检测任务的标注文件里面维护了图片路径和对应的检测框信息crop_img目录保存的是每个检测框对应裁剪出来的小图Rec_gt.txt则是识别任务需要的标注文件每条包含一张裁剪图片和它对应的文本内容。这套结构基本就是PaddleOCR训练前需要的输入雏形。5.2 检测训练格式怎么对上PaddleOCR的检测训练通常需要每张图片对应一个或多个检测框框用四个点的坐标表示再加上转录文本。PPOCRLabel导出的Label.txt内容大概长这样images/001.jpg [{transcription: 金额, points: [[56, 88], [210, 88], [210, 118], [56, 118]], difficult: false}]在PaddleOCR训练配置里路径一般指到类似train_data/det_label.txt这样的文件对应关系就是前面是图片相对路径后面是检测框数组的JSON。只要你把导出结果按训练配置的路径管理好检测阶段数据就能直接用。这里有一点要提醒points里的四个坐标顺序要保持一致建议按左上、右上、右下、左下的顺序。坐标顺序乱掉以后训练时数据增强里的随机旋转会出问题模型会学到错误的框走向。5.3 识别训练格式怎么对上识别训练需要的是另一种形态的数据裁剪出来的小图和这段小图上的文字。PPOCRLabel导出时会把每个检测框对应的小图裁剪到crop_img目录裁剪图和文本之间的对应关系写在Rec_gt.txt里类似这样crop_img/001_0.jpg 金额 crop_img/001_1.jpg 发票号码12345678在PaddleOCR识别训练里你通常还需要准备一个字符集合文件也就是字典。把标注数据里出现的所有字符收集起来去重一行一个字符顺序和训练配置里指定的一致。如果字符集不完整训练时对应字符就会变成“未定义”损失直接波动。5.4 训练集和验证集划分的一条硬规矩数据集划分最忌讳的是按裁剪图划分。不能把同一张原图裁剪出的多个小图一部分放进训练集、一部分放进验证集这会造成严重的数据泄漏模型验证分数虚高。正确做法是先把原图按比例划分成训练集和验证集再让每个集合各自对应自己的检测标注和识别标注。我常用的比例是九比一如果数据量大八比二也可以但至少保证验证集里有足够多的不同原图类型。划分完之后把Label.txt和Rec_gt.txt对应拆成train和val两份再交给训练脚本。这个步骤虽然简单却是最容易让人忽略的坑。6. 我踩过的坑希望你不再踩6.1 自动检测把印章误判成文字票据类图片里红色印章和文字叠在一起是最常见的也是自动检测最容易出问题的。印章的文字会和正文交叉重叠模型会把印章边缘、发票专用章那几个字一起框出来或者把正文和印章文字混在同一个框里。这种场景下我的经验是不要完全依赖自动检测的框手动重新框一遍更靠谱。框选时只框完整可读的正文印章里模糊、重叠、残缺的文字不要硬转录如果一段文字确实被印章严重遮挡鉴于是难例保留difficult标记。最终模型反而能在检测阶段学会忽略这些干扰框。6.2 用Excel改标注文本导致JSON解析失败有一次我图省事导出Label.txt后用Excel批量替换了一批错字保存后再回去跑训练结果程序一直报错。原因是Excel把文本里的英文引号、逗号、花括号都自动做了替换还把false变成了False纯文本JSON格式直接被破坏掉了。从那以后我再也不用办公软件碰标注文件所有文本替换都改成专门的小脚本用Python处理编码强制UTF-8格式不会变。6.3 长图标注到一半进度全丢我踩过最痛的一次坑是标注一批高分辨率长图一张图里密密麻麻排了二三十个小框。标到一半软件直接卡死重开以后发现标注结果没有保存全。后来我调整了策略高分辨率大图先切成若干小块再标注切块后的图片最大边长控制在像素范围内既保证模型推理不卡也避免单张图片标注文件过大导致保存失败。切完的标注坐标要记得按切片偏移量换算回原图坐标换算脚本很简单但换算出的坐标才是训练真正需要的值。6.4 多人协作时文件管理混乱如果是团队标注最忌讳的是多人同时在同一个目录下操作互相覆盖标注结果。我的做法是把原图按人名或批次分目录每个人认领独立目录标注完成后统一合并。合并之前跑一遍校验脚本检查有没有重复图片、空转录、JSON解析失败这三类问题。合并完的最终文件再按上一节的方式切分训练集和验证集这样即使某一个目录出问题也能快速定位回对应批次的标注文件。在我实际标注数据和模型迭代的过程中PPOCRLabel真正解决的问题是把“人工逐字录入”和“模型自动预测”这两个环节自然地接在一起。越是图片质量差、业务场景杂的项目你对标注格式和标注规范的控制越要细。建议第一次用的时候先拿二十张图完整走一遍从打开图片到导出数据的流程确认每个字段的含义之后再批量铺开。这个前期投资在后续训练排障的时候一定会加倍赚回来。
阅读完成 · 觉得有帮助?
咨询建站