四月总结:体重没变,但认知架构被彻底推倒了

四月总结,体重没变,但认知架构被彻底推倒了。上个月还在跟教练死磕体脂率,这个月直接掉进 OCR 的坑里,爬出来的时候发现脑子里那套“产品经理画原型、技术团队搞实现”的老架构,碎了一地。

客户扔过来一麻袋纸质单据,有手写的送货单、机打的发票、盖了红章的验收单,要求一周内全部数字化,还要能按字段检索。团队?早解散了。外包?预算为零。这活儿搁两年前,我肯定头皮发麻,要么硬着头皮招人手工录,要么跟客户扯皮加钱。现在没退路,只能自己上。第一反应是找现成的商业 OCR API,试了一圈,贵,而且对五花八门的非标单据识别率感人,尤其是那些沾了油污、折了角、字迹潦草的,API 返回的 JSON 跟天书一样。

逼上梁山,只能啃开源。PaddleOCR 是首选,文档全,社区活。但“开箱即用”是个美好的谎言。直接 pip install 跑 demo,对标准印刷体还行,一上真实单据,准确率立马崩盘。问题出在预处理和后期调参上,没人会告诉你这些。

先说图像预处理。单据扫描进来不是白纸黑字,背景可能有格子、有彩色 logo、有深浅不一的水印。直接扔给 OCR 引擎,它光辨认哪些是噪声、哪些是文字就够呛。我花了三天时间跟 OpenCV 死磕,试了灰度化、二值化(全局阈值、局部自适应阈值)、降噪(高斯滤波、中值滤波)。发现关键不是用多高级的算法,而是针对单据类型做定制。比如发票背景浅,用全局阈值就能切得很干净;但手写送货单纸张发黄,局部自适应阈值配合形态学操作(开运算)去除小噪点,效果才好。这里有个坑,二值化阈值调得太激进,容易把笔画细的手写字给“吃”掉,识别出来就缺笔少画。

然后是 PaddleOCR 本身的调优。它默认的检测模型(DB)和识别模型(CRNN+CTC)是通用模型。我的单据文字密度高、排版紧凑,默认参数容易把相邻两行文字检测成一个框。得调 detect 的 box_thresh 和 unclip_ratio,控制文本框的膨胀程度,让它们既能包住文字又不至于粘连。更麻烦的是识别字典。默认中英文混合字典,但我的单据里大量是产品型号(比如“GY-3A 型控制器”)、客户简称(“沪申机电”),这些词不在字典里,识别出来就是形近字。没办法,只能自己收集这批单据的高频词,生成自定义字典,硬塞给识别模型。虽然增加了匹配负担,但准确率从 70% 拉到了 90% 以上。

最后是后处理。OCR 识别出来是一行行文本,但单据是结构化的,比如“日期:2022/03/15”需要把“日期”和“2022/03/15”拆成键值对。这里用规则引擎比上 NLP 更直接。用正则表达式匹配固定关键词,再根据相对坐标位置(OCR 引擎会返回每个文本框的坐标)去抓取相邻区域的内容。有些字段位置不固定,就得写简单的启发式规则,比如“金额”后面通常跟着数字和“元”字。

整个过程,我没有写一行真正的业务逻辑代码,全在跟图像像素、模型参数、文本规则搏斗。产品经理的“用户体验”、“商业模式”思维暂时熄火,取而代之的是工程师式的“精度”、“召回率”、“F1值”。身体还是坐在电脑前,但大脑像被格式化了,以前觉得技术是黑箱,调用 API 就行,现在明白真正的黑箱是业务场景到技术方案的映射路径,不开箱折腾,永远拿不到能用的结果。

体重秤上的数字确实没动,但脑子里的脂肪,或者说那种“动动嘴皮子就能成事”的虚胖思维,被这次硬核的 OCR 实操给刮掉了一层。焦虑吗?当然,35 岁了还在跟命令行和错误日志厮混。但也踏实,这套从预处理到后处理的完整 pipeline 打通后,我感觉手里多了一把螺丝刀,以前看不清的机器,现在敢拆开看看了。虽然不知道下一台机器是什么,但至少,不怕了。

© 版权声明
THE END
喜欢就支持一下吧
点赞50 分享