Rust 使用 tesseract 识别验证码
近期需要将验证码识别功能集成到一个 Rust 项目中,验证码图片大概这样:
观察
首先观察图片,发现前景文字和背景图片颜色深度差别较大,可以对图片进行二值化处理。使用 Photoshop 可以看到,转为灰度图像后,在 0 ~ 255 内,前景和背景大约以 130 为界。使用 “天若OCR” 截图、识别了若干张图片,在较大截图区域的情况下,识别率可以达到 100%,说明这个验证码不复杂。由于在线 API 有数量等限制,最终将目光锁定在了 tesseract 上。
tesseract 预训练好的 trained-data(eng)大概能达到 50% 左右的识别率,但在细节上(如字母 S
与数字 5
)错误率较高。训练过程不多说,请同学帮忙用约 300 张验证码图片,训练了一个模型。准确率大约 85%,由于嫌麻烦,没有进一步框图训练了。
初次尝试
我的环境是:Windows 10,CLion 2020.2 + Rust 1.46(2020-08-24)。
Rust 下有关于 tesseract 库的封装,tesseract、tesseract-sys 和 leptess(tesseract 和 leptonica 结合),我这里使用 tesseract 库。
找一张使用 Photoshop 处理过的图片,先测试一下:
1 | fn main() { |
可能存在的问题
因为依赖 leptonica-sys
和 tesseract-sys
只是对应 C/C++ 库的封装,所以我们需要对应的 C/C++ 库。如若未安装,可能报这样的错误:
1 | /* 省略 */ |
Linux
这里注意,Linux 下解决这个问题好像很简单,只需要
1 | apt install libleptonica-dev libtesseract-dev clang |
再次 cargo build
即可。
Windows 下
可以看到,leptonica-sys
依赖了 vcpkg
,且缺少 x64-windows-static-md
。可以去 Github 仓库先下载一个 vcpkg。可以参考 《官方快速安装指南》。注意,仓库只提供了源码,你需要保证电脑中有 Visual Studio C++ 的那一套编译工具。
然后在命令行中:
1 | vcpkg install leptonica:x64-windows-static-md |
具体参数视报错自行决定,再次编译即可。
至此问题基本解决,输出:
1 | Warning: Invalid resolution 0 dpi. Using 70 instead. |
完善
很明显,我们需要完善一下这个程序,用 Rust 来做二值化的操作。
引入 image
、imageproc
和 tesseract
库:
1 | [dependencies] |
首先打开图片:
1 | let image = image::open("31.jpg").unwrap(); |
imageproc
库有一个 threshold
函数,原型为:
1 | pub fn threshold(image: &GrayImage, thresh: u8) -> GrayImage |
所以需要先将读入的 RGB 图像转换为灰度图像。
1 | let image_luma = image.into_luma(); |
再调用 tesseract::ocr_from_frame
函数即可:
1 | let dimension = image_luma.dimensions(); |
这里面,容易理解的是,bytes_per_pixel
是位深度 / 8
,也就是每个像素所占的字节数,但是 bytes_per_line
不知道为何需要输入,可能有些图片格式比较特殊吧。该参数按字面意思是每行像素所占的字节数,然而没有找到有关文档和描述,后来翻了下源码,发现自己并没有理解错,却在这里花费了不少时间。
完整的程序:
1 | use imageproc::contrast::threshold; |
结语
断断续续地搞了好多天,vcpkg
、tesseract
也都没有用过,就这么边琢磨着、折腾着,弄完了。
谨以此文,庆祝一下国庆,感谢一下自己。