SpaceX 夹住火箭的那一刻:暴力美学背后的精确算法

SpaceX 夹住火箭的那一刻,我盯着屏幕,脑子里想的不是航天,是我桌上那堆堆成山的纸质单据。那种暴力又精确的机械臂,跟我用 Python 脚本暴力处理几千张发票的 PDF 扫描件,本质上是同一种焦虑:时间就是金钱,而我的时间正在被这些破纸片按秒计价地消耗掉。

客户扔过来一个压缩包,解压出来三千多张扫描件,有发票、有收据、有手写的送货单,歪的、斜的、光线暗的、盖章糊成一团的。要求是两天内把关键字段(日期、金额、供应商名称、税号)全提出来,结构化扔进数据库。这不是人力能干的活,招实习生手动录?成本和时间都炸了。只能上 OCR,但通用的云端 API 贵得离谱,而且这种批量、涉及敏感财务数据的活儿,根本不敢往外网传。只能硬着头皮搞本地部署的开源方案。

最开始试了 Tesseract,默认模型上去,识别率惨不忍睹,尤其是那些低质量扫描件和手写体,简直像在猜谜。时间压力下,人容易走极端,我当时就想,是不是得自己从头训练一个模型?但冷静下来算算,数据标注、训练周期、GPU 成本,两天?两个月都搞不定。这不是技术炫技,这是生存问题。必须基于现有引擎做快速调优,走“暴力穷举+规则清洗”的野路子。

第一步是预处理暴力化。写了个批处理脚本,对每张图依次走:自适应二值化(对付光照不均)、高斯模糊去噪点、然后尝试多种形态学操作(开运算、闭运算)来断开粘连字符或填补空洞。这步没有银弹参数,我直接写了个循环,用几组不同的核尺寸和迭代次数去处理同一批样本图,肉眼对比选出效果最好的一组。这很“糙”,但快,两小时搞定参数摸索。

第二步是切割和识别策略调整。Tesseract 对整页复杂布局的解析很弱。我放弃让它自己分析段落,转而用 OpenCV 找轮廓,根据先验知识(比如发票号码通常在右上角,金额表格在下方)做区域ROI裁剪,把整图拆成一个个小任务块,再分别扔给 Tesseract。同时,启用多进程。对,就是最土的那种 `multiprocessing.Pool`,把三千张图列表切分,扔到 8 个进程里并行跑预处理和识别。CPU 瞬间飙到 100%,风扇狂转,但处理时间从预估的线性 10 小时压缩到了 2 小时。这就是最直接的“时间金钱”换算:用计算资源换人力时间。

最耗神的第三步是后处理规则引擎。识别出来的文本是杂乱的,包含大量错误。我根据财务单据的固定范式,写了一大堆正则表达式和字典查找。比如,日期格式无非就那几种 “2023/03/20”, “2023-03-20”,用正则匹配并统一格式化。金额字段,就找“¥”、“¥”、“小写:”这些关键词后面的数字串,再检查小数点位置。供应商名称,维护一个常见供应商名称的列表做模糊匹配(用 `fuzzywuzzy` 库,设置一个相似度阈值)。这里没有机器学习,全是“if-else”和规则,但有效。每一条规则,都是之前被坑过、赔过钱后总结出来的血泪教训。

搞到凌晨,脚本终于能稳定跑了,识别率从最初的不到 60% 提到了 85% 以上。剩下的 15% 疑难杂症,脚本会把原图和识别结果高亮标注出来,打包成一个待复核文件,人工介入。从“全部人工”到“人工只处理例外”,效率提升了十倍不止。

看着终端里滚动的处理日志,听着机箱风扇的轰鸣,我突然觉得,我这个小破脚本和 SpaceX 的回收算法,内核是相通的。都是在极端约束(时间/成本/物理极限)下,把一堆不确定的、混乱的输入(模糊图像/高速下坠的火箭),通过一层层粗暴但有效的预处理、并行计算、和基于强领域知识的规则过滤,最终输出一个稳定、可用的结果。它不优雅,甚至充满了补丁和硬编码,但它能在 deadline 之前把钱挣了。这就是工程现实里的“暴力美学”,美感不在于代码多简洁,而在于它在泥潭里挣扎时,那股子能把事办成的、精确的狠劲。

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