千呼万唤,Snipaste 这款截图贴图软件终于支持 OCR 功能。OCR 可以识别图片上的文字,跟截图软件一起工作再合适不过了。在更新日志引用的这个 issue 下,我看到 Coxxs 提供了一个改进的 OCR 组件。原来对于 Windows,Snipaste 默认的系统内置选项会调用旧版的微软组件,准确率低、识别率慢。然而我使用以后觉得新版也差强人意,尝试看看能不急集成微信 PC 版的 OCR。
答案是可以。Coxxs 的项目实际利用了 Snipaste 的第二种方式:Tesseract 对接。从 Snipaste 界面可以看出其命令行参数默认是 stdin stdout。我实际下载了 Tesseract 使用,速度不快,结果有很多空格,差点意思。但是重要的是可以用帮助命令看出参数含义,结论是 Snipaste 将图片传给标准输入 stdin,OCR 文本结果传给标准输出 stdout。那么我只要写个程序在中间调用微信 OCR 就好了。
开发过程
一般来说这里面最棘手的过程是调用微信 OCR。但我就是有印象有人开发过,所以才有了对接到 Snipaste 的想法。这个项目是 swigger/wechat-ocr,同时支持微信 PC 版 3.x 和 4.x 的版本。官方提供 C++、Python、Java、C# 接口。
那么该选择什么样的技术栈做这个中间程序呢?我第一反应想到的是 aardio。我自己写 Windows 下的小的程序经常用,印象中 aardio 跟类 C 接口的互操作性也很好。但我决定还是不趟这浑水。我工作主要语言是 Java,但是写这种小东西带个运行时也太重。最终我选择有过少许开发经验的 golang,编译方便,制品体积小,也能操作 C 的接口。但我还是有点畏难,问了 AI 大模型似乎有点繁琐,好在前述项目有人写了 go 版本的 fanchenggang/wechat-ocr-go。
开发中稍微别扭的地方是需要将图片存为文件。前述 wechat-ocr 项目只接受路径作为参数,不支持文件内容。据说 Windows 下也有命名管道之类的东西可以用,但我决定从简,将从标准输入读到的图片保存到临时目录,程序运行结束或报错时删除。
为了排查问题,将调试和报错信息也输出。但是这里不能输出到 stdout。稍微看了 Coxxs/sp-oneocr,应该是输出到标准错误 stderr,即使只是调试信息。那我也这样做。
该怎么调试呢?我真没想到原来 Windows 的 cmd 也有管道。(不要问我为什么不用 PowerShell。)跟 Linux 类似,用竖线 | 操作符即可。读取文件内容用 type。即:
chcp 65001
type "C:\your\image.png" | "C:\your\wechat-ocr-snipaste\wechat-ocr-snipaste.exe" stdin stdout其中第一句是为了让命令行提示符正确显示 UTF-8 编码。实测 Snipaste 就是需要 UTF-8 输出。
如果长期运行的话,可以后台常驻,接收到 Snipaste 请求时通过通信机制传递给运行着的实例,这样不需要重复加载 DLL 之类的。但是现在这样用一次退一次的速度就不错。后台常驻的收益可能不明显,还可能不稳定。
开源仓库:https://github.com/shansing/wechat-ocr-snipaste
使用方法
注意目前只有专业版的 Snipaste 才有 OCR 支持。另外需要确保操作系统是 64 位 x86 的 Windows。实测不支持 Arm64。
首先去 Releases 页面下载我编译好的 wechat-ocr-snipaste.exe,或者自行编译。建议放到一个单独的文件夹。
确保微信 PC 版安装好。需要复制 wxocr.dll(旧版微信)或者 wechatocr.exe(4.x 版微信)的全路径,包含文件名,我们把这个参数叫作 ocrBin。找到微信本体的安装路径,通常带版本号,在我这里是 mmmojo_64.dll 所在的目录,把这个参数叫作 wechatDir。这两个参数后面会用到。
ocrBin参数示例:
- C:\Users\name\AppData\Roaming\Tencent\WeChat\XPlugin\Plugins\WeChatOCR\7061\extracted\WeChatOCR.exe
- C:\Users\name\AppData\Roaming\Tencent\xwechat\XPlugin\Plugins\WeChatOcr\8075\extracted\wxocr.dll
wechatDir参数示例:
- C:\Program Files\Tencent\WeChat[3.9.8.25]
- C:\Program Files\Tencent\Weixin\4.1.5.30
也很推荐把这里的 extracted 目录复制出来,跟 wechat-ocr-snipaste.exe 放在一起,重命名为 ocrBin;将版本号文件夹复制放在一起命名为 wechat。这样稍后可以用上俩参数的默认值,不必显式指明。复制出来也可以减少微信抽风风控的风险。
接着下载 wcocr.dll。可以从 swigger/wechat-ocr 或 fanchenggang/wechat-ocr-go 得到。跟 wechat-ocr-snipaste.exe 放到一起。
现在我们的目录结构是这样的:

接下来配置 Snipaste。右击托盘图片进入“首选项”,选择“输出”-“文字识别”。选择 OCR 引擎为 Tesseract,将可执行文件更改为选择 wechat-ocr-snipaste.exe。参数填写 -ocrBin "..." -wechatDir "...",其中 ... 替换成上述两个参数实际的值,因为引号的缘故目录不要最后加反斜线 \;如果遵循我上面推荐做法使用默认值,那么这里参数保持为空即可,如图:

然后截图使用测试一番。正常的话结果会复制到剪贴板。
第一次使用如果不成功,可以用上一节的命令行排查一下,查看报错信息。有问题可以下面留言。
这里之所以需要自行下载这么多文件,是因为如作者说“打包他人软件是侵犯知识产权的违法行为”,所见略同。而我觉得封装 API 好像也涉及逆向有点可疑,所以这个 dll 也请你们自己下载啦。
实测效果不错。速度快,准略率又高。跟系统内置(哪怕高版本)相比抗干扰能力也强,比如不太受屏幕水印影响。