我与Agent共创的wxocr文字识别服务

wxocr: Vibe Coding with Claude Code

以下内容包含AIGC

一年多以前在 V2EX 看到帖子,有网友把 Linux 版微信的离线 OCR 引擎提取出来,做成了可以 API 调用的服务,这个 OCR 引擎可以输出每个文本块的top bottom left right text rate(置信度)属性。当时我用 Copilot 搓了一个网页,在图片上叠加色块来对比查看 OCR 识别结果,验证了识别率确实不错。

一年后,Claude Code 成为开发人员的标配,我不太会写 Python,但我能描述清楚自己要什么,能测出哪里有问题,能把现象说明白。于是花了一天半的时间,和 Claude 一起把这个想法做成了一个完整的项目:支持图片和 PDF 的 OCR 识别、Web 界面可视化对比、人工修订 OCR 结果、一键嵌入生成可检索的 PDF,还有水印去除、图片纠偏等功能。

开发过程:真实的 Vibe Coding

整个项目经历 76 轮对话,从第一句“帮我分析当前项目是否可以从 Python 迁移到 Node.js”开始。我一开始想用 Node.js 写,因为更熟悉,但调研了一圈发现 PDF 处理、图像操作在 Python 生态里成熟太多,最后还是妥协了。

开发流程基本是这样的:我用小作文描述需求 → Claude 给计划、定待办清单、写代码 → 我本地或线上测试 → 发现问题、描述现象 → Claude 修复 → 循环。听起来很顺利,但实际上每个环节都有坑。

坑一:PDF 文本层嵌入的中文渲染

最难的部分是把 OCR 识别的文本“不可见地”嵌入到 PDF 里。技术上用的是 PyMuPDF,在原始图片上叠加透明文本块,这样生成的 PDF 看起来还是影印版,但可以圈选复制、可以搜索。

第一版嵌入后,我圈选文字一看:

1
2
■■■ ■■2026/7/29 06:30■■
■■■■■■■■■■■AI■■

中文全是方块乱码。Claude 判断是字体问题,改了字体,重新嵌入,中文出来了,但标点符号又变成了圆点。

逗号句号变成了 ·,我把这些现象描述给 Claude,它发现是字体切换逻辑有问题 —— 非中文字符用的是 helvetica,中文用的是 china-s,但中文标点符号被错误地归到了非中文字体,所以渲染不出来。

修复后又发现另一个问题:非中文字符之间被插入了空格,2026/7/29 变成了 2 0 2 6 / 7 / 2 9。这次是因为 PyMuPDF 的文本插入逻辑会自动分段,每个字符都被当成独立的文本块,间距就拉开了。最后改成按语言连续性分段 —— 中文字符连续的部分一起插入,非中文连续的部分一起插入,这个问题才算解决。

坑二:PDF 的坐标缩放问题

图片嵌入文本块的坐标是准的,但 PDF 嵌入后文本块全都向右下角偏移了一大截。我测试了几次发现规律:偏移量看起来是 2 倍关系 —— OCR 返回的坐标是 (100, 100),但实际文本块出现在 (200, 200) 的位置。

告诉 Claude 这个现象后,它意识到问题:PDF 渲染时用的是 2 倍分辨率(scale=2),但嵌入文本块时用的是 OCR 原始坐标,没有做缩放转换。加了一行 x /= scale, y /= scale,问题解决。

坑三:Claude 意外地吹了个牛

在项目快完成时,我让 Claude 帮我写 README 文档。它很积极地在显著位置写了:“支持水印去除、图片纠偏等增强功能”。

我当时愣了一下 —— 水印去除和纠偏确实实现了,但只作用在 OCR 前的预处理阶段,帮助提升识别率。最终生成的 PDF 里,水印还是在的,并没有真的“去除”。这个描述有点夸大了。

我跟 Claude 说:“这个描述有点误导,实际上水印并没有从最终产物里消失。”然后问它:“如果真要做到’去除水印并嵌入’,难度有多大?”

Claude 给了个方案:既然预处理时已经生成了去除水印后的干净图片,那就把这些干净图片作为嵌入的底图,再叠加文本块,不就行了?对于图片输入这很容易,对于 PDF 输入稍微复杂点,需要把每页都渲染成图片、去水印、嵌入文本、重新组装成 PDF。

听起来可行。我说:“那就做吧,别让 README 成为虚假宣传。”

于是又花了一个小时,实现了 apply_preprocessing 参数 —— 当用户在接口或前端勾选“移除水印”时,最终文本嵌入产物里的水印真的会消失,只留下干净的图像和可搜索的文本层。测试后效果很好,自述文档的描述终于名副其实了。

这个过程挺有意思的:AI 有时候会过度承诺,或者理解偏差导致描述不准确。你可以选择纠正它,也可以选择把这个承诺实现出来。后者更累,但产品会因此变得更完整。

项目亮点

最终这个项目的核心特性是三个:

1. 人工可订正

OCR 识别率再高也有错误。影印版 PDF 里的模糊字符、扫歪的表格、水印干扰的文本,识别总会出问题。wxocr 提供了完整的 Web 界面,可以对照原图逐行修订识别内容,逻辑删除不需要的文本块(比如页眉页脚),然后一键嵌入订正后的文本生成 PDF。

ocrmypdf 也能嵌入文本层,但不提供人工干预的环节 —— 识别错了就是错了,直接嵌入。wxocr 假设你不会盲目信任 AI 的识别结果,而是需要一个可控的校验和修订流程。

2. 极低资源消耗

在腾讯云 1C2G5M 轻量云服务器上(没有 GPU),一个 5 页的 PDF 文件,从上传到返回 OCR 结果,总共 10.87 秒。微信 OCR 引擎是为个人电脑设计的,依赖 CPU 的 AVX2 指令集而非 GPU,资源开销几乎可以忽略。

3. 真的去除了水印

如前面说的,这个功能一开始只是 Claude 的“误导性描述”,后来我们把它实现了。当用户勾选“移除水印”和“自动纠偏”时,预处理后的干净图像会成为最终 PDF 的底图,水印真的会消失。

快速开始

Docker 部署:

1
docker run -d -p 5000:5000 --restart unless-stopped icheerme/wxocr:latest

访问⁠⁠ http://localhost:5000⁠⁠,上传图片或PDF,勾选预处理选项,识别后修订结果,最后点击“嵌入并下载PDF”。

注意:wxocr依赖CPU的AVX2指令集。检查方法:

1
2
3
4
5
# Linux
grep avx2 /proc/cpuinfo

# macOS
sysctl -a | grep machdep.cpu.features

如果服务器不支持AVX2,OCR功能无法工作。

技术栈:
后端:Python 3.11 + Flask​
OCR引擎:微信离线OCR(来自Linux版微信)
​PDF处理:PyMuPDF(fitz) + pdf2image​
图像处理:Pillow + OpenCV​
前端:Vue3 UMD(单文件,无构建步骤)​
部署:Docker + Nginx

项目在这里:https://github.com/icheer/wxocr



如果你也在用 AI 协作开发,可能会遇到类似的问题:中文渲染、坐标转换、AI 的过度承诺。这些坑都不是 AI 主动能发现的,需要人去测试、描述、反馈。但只要说清楚了(有时候明确的需求/bug,我甚至指明文件和行号让 AI 去修改),AI 能很快定位并修复。这个过程里,人的价值不在于会不会写代码,而在于知道要什么、能发现问题、会描述清楚。

Buy me a coffee ☕