做了一个Serverless的仿discuz验证码识别器
在 Cloudflare Worker 中部署,纯原生 JavaScript 手写实现 2D 卷积、池化以及图像协议解码,最终将 AI 识别任务压缩到了极致的 ~ 400KB(FP32) 和 ~ 100KB(INT8),且做到 0 依赖运行。可以识别 类discuz 的 BMP、PNG、GIF 的简单验证码(过于复杂的码识别能力很差)。
以子之矛,陷子之盾
以子之矛,陷子之盾,何如?
干扰线条
随机倾斜
波纹扭曲
噪点发散
鲜艳彩色
尺寸形变
立体阴影
等待生成...
请先设置参数并生成验证码,然后点击识别测试效果。
核心特性
- 微型模型:基于 MobileNetV3-Small 魔改,加入定制化 1D 序列融合头(OCR Sequence Head),来解决字符粘连与扭曲。
- QAT INT8 量化:使用 PyTorch QNNPACK 引擎进行量化感知训练 (Quantization-Aware Training),算子融合后导出纯净
.bin数据,体积 ~ 100KB。 - 手写图像解码引擎:
- BMP: 这个没啥说的。
- GIF: 手写 LZW 解码器,并自动抽取延迟最长的一帧。
- PNG: Web Crypto API 的
DecompressionStream替代 Zlib,纯手写查表逆滤波(Sub, Up, Average, Paeth)。
- 原生 V8 推理引擎:零第三方库,使用
Float32Array纯手搓含有 Padding、Stride 和分组卷积(Depthwise)的算子。
API 调用方式
向你的 Worker 发送一个带有图片二进制 Body 的 POST 请求,即可瞬间获得识别结果。
使用 cURL 测试:
1 | curl -X POST https://uncaptcha.psu.monster/?precision=fp32 \ |
响应示例:
1 | B2X9 |
性能基准 (Benchmarks)
- 模型体积: ~100 KB (原生 INT8)
- 内存占用 (Cold Start): < 10 MB (包含张量池初始化)
- 推理耗时 (纯 JS 卷积): ~15 - 30 毫秒 (视 Cloudflare 节点 CPU 性能而定)
- 准确率 (Accuracy): 72% ~ 85% (FP32); 30% ~ 70% (INT8)
后日谈
本来模型容量就小,FP32都勉勉强强,就没必要量化了,本来刚好够的拟合任务,一量化之后精度直接跌破天际,微调也不管太多用。后来尝试了带着QAT训练才勉勉强强能够识别了。
做了一个Serverless的仿discuz验证码识别器