共计 5190 个字符,预计需要花费 13 分钟才能阅读完成。
提醒:本文最后更新于2025-07-07 14:39,文中所关联的信息可能已发生改变,请知悉!
提到图片 OCR 识别,一般可能都会想到著名的 tesseract-ocr。
在 Node.js 程序中处理如验证码识别一类的文本或物体识别时,需要以 Node.js API 的方式调用。一般来说有三种可实现该需求的方式:包装本地安装的 OCR 应用程序(如 tesseract-ocr)以提供 Node.js 调用接口、通过 http 请求方式调用第三方在线服务以及使用支持 node.js 的第三方依赖库(如 tesseract.js)。
包装本地 OCR 应用程序 API
这种方案要求首先在本地机器安装并配置要包装的 OCR 应用。然后使用 node.js child_process
模块的 exec、spawn
等方法调用 OCR 应用,并将执行后的结果处理后返回。
npm 上能找到的大多为基于 tesseract-ocr
实现的包装,主要区别在于包装后的 API 易用性。相关实现参考:
- https://github.com/tesseract-ocr/tesseract
- https://github.com/nicolaspearson/node.ts.ocr
使用第三方在线服务 API
BAT 都提供有相关的在线服务 API,这些在线 API 的用法一般也都比较简单,少量的调用基本都是免费的。另外一些在线打码平台也会提供相关收费 API 服务。下面以百度智能云为例作简单示例介绍。
使用百度账号登陆百度 AI 智能云平台,并新建一个应用,然后进入应用管理可得到 APPId、key、和 secret。
百度智能云控制台:https://console.bce.baidu.com/ai/#/ai/ocr/overview/index
百度智能云平台提供了相当多的人工智能相关的 API 开放服务。以下为 node.js 调用百度智能云 OCR API 实现图片文本识别的一个示例:
// 需先安装其 SDK 包: npm -i badidu-aip-sdk | |
// const AipOcrClient = require('baidu-aip-sdk').ocr; | |
const AipOcrClient = require('baidu-aip-sdk/AipOcr'); | |
const fs = require('fs'); | |
const APP_ID = '14406xxx'; | |
const API_KEY = 'Fz7XXXXXXXXXXX'; | |
const SECRET_KEY = 'XEXXXXXXXXXXXXXX'; | |
const client = new AipOcrClient(APP_ID, API_KEY, SECRET_KEY); | |
const ocrTextTest = async () => { | |
const options = { detect_direction: true }; | |
// 识别本地图片 | |
const image = fs.readFileSync('./donate_wx.png').toString('base64'); | |
let result = client.generalBasic(image, options); | |
console.log(result.words_result); | |
// 识别在线图片 | |
const result = await client.generalBasicUrl('https://lzw.me/wp-content/uploads/2017/02/donate_wx.png'); | |
console.log(result.words_result); | |
} | |
ocrTextTest(); |
使用 tesseract.js
库实现 OCR 识别
tesseract.js 本质上也是基于 tesseract-ocr
的封装,但其不同的是它借助 emscripten
将 C++ 开发的 tesseract-ocr
编译为 WebAssembly
实现能力支持,现代浏览器均支持 WebAssembly
,故其也可直接在浏览器中应用。
以下对使用 tesseract.js
实现 OCR 文本识别作简要介绍。
安装 tesseract.js
依赖
npm i tesseract.js | |
# or | |
yarn add tesseract.js |
下载训练数据
tesseract.js
默认从其网站下载训练数据,但由于训练数据包比较大,可能需要比较久的时间。我们可以先使用迅雷等工具将其下载下来,然后通过 langPath
参数指定训练数据的位置。
下载地址示例: https://tessdata.projectnaptha.com/4.0.0_fast/chi_sim.traineddata.gz
下载其他语言类型的训练数据,只需将示例地址中的 chi_sim
改为要下载的语言标识即可。
当然你也可以从其默认训练数据的仓库下载(可能会因 git 拉取太久而失败),所有默认支持的的语言也都可以从这里知晓。
默认训练数据仓库地址为:https://github.com/naptha/tessdata
基于 tesseract.js
的图片文本识别示例
const Tesseract = require('tesseract.js'); | |
const path = require('path'); | |
const worker = Tesseract.createWorker({ | |
logger: m => console.log(m), | |
errorHandler: err => console.log('[error:]', err), | |
// 使用离线训练数据 | |
langPath: path.resolve(__dirname, './tessdata/4.0.0_best'), | |
}); | |
const ocrTest = async () => { | |
await worker.load(); | |
await worker.loadLanguage('chi_sim'); | |
await worker.initialize('chi_sim'); | |
await worker.setParameters({ | |
// 验证码只为数字的情况下,设定白名单 | |
// tessedit_char_whitelist: '0123456789', | |
tessedit_pageseg_mode: tessedit_pageseg_mode: Tesseract.PSM.AUTO, | |
}); | |
// const image = require('fs').readFileSync('./donate_wx.png'); | |
const image = 'https://lzw.me/wp-content/uploads/2017/02/donate_wx.png'; | |
const { data: { text } } = await worker.recognize(image); | |
console.log(text); | |
await worker.terminate(); | |
}); | |
ocrTest(); |
以上示例为对文本对识别。
自行训练自定义数据
默认支持的训练数据相对比较弱,对于文字比较清晰的图片来说一般没有问题,但对于存在干扰的验证码这种需求来说,则需要通过自行训练来提升准确率。
tesseract.js
使用的训练数据只是将 tesseract-ocr
gzip 压缩了一下而已,训练自定义的数据需要安装 tesseract-ocr
以及其训练数据相关工具。
具体的方法可参考官方相关仓库和文档:
- 安装 tesseract-OCR:https://github.com/tesseract-ocr/tessdoc/blob/master/Installation.md
- https://github.com/tesseract-ocr/tesstrain
- https://github.com/tesseract-ocr/tessdoc/blob/master/Compiling.md
另外也有一些可参考的教程:
- https://zhuanlan.zhihu.com/p/103714876
- https://github.com/kekxv/TesseractTrain
- https://www.bbsmax.com/A/6pdDb7pDJw/
- https://www.bbsmax.com/A/8Bz8KNOkdx/
- https://www.ershicimi.com/p/9bf5ec129082ac6800b1cb6f56c6f71c
- https://blog.csdn.net/sylsjane/article/details/83751297
- https://blog.csdn.net/holmofy/article/details/80867243
- https://blog.csdn.net/makesibushuohua/article/details/52058310
获取用于训练的图片
以验证码为例,下面为获取一定数量的验证码作为训练集。由于训练的图片只能为 png 格式,使用了 sharp 库将下载得到的图片转换为 png 格式。sharp 安装过程中需要从 GitHub 仓库下载二进制资源,可能会因为无法下载而安装失败,我们执行如下命令设置从淘宝镜像下载相关资源:
npm config set sharp_binary_host "https://npm.taobao.org/mirrors/sharp" | |
npm config set sharp_libvips_binary_host "https://npm.taobao.org/mirrors/sharp-libvips" |
代码示例:
import fs from 'fs'; | |
import http from 'http'; | |
import https from 'https'; | |
import sharp from 'sharp'; | |
const downloadImage = (imageUrl: string): Promise<buffer> => { | |
return new Promise((resolve, reject) => { | |
(imageUrl.startsWith('https') ? https : http).get(imageUrl, (res) => { | |
const chunks: Buffer[] = []; | |
res.on('data', (chunk) => chunks.push(chunk)); | |
res.on('end', (error: Error) => { | |
if (error) return reject(error); | |
const size = chunks.map(d => d.length).reduce((val, total) => val + total, 0); | |
resolve(Buffer.concat(chunks, size)); | |
}); | |
}); | |
}); | |
}; | |
const getCodeImgUrl = () => `https://lzw.me/getcaptcha?theme=light&_pc=${Date.now()}`; | |
export const saveImages = async (total = 100, nameBase = 10000, baseDir = './images/captcha/') => { | |
if (!fs.existsSync(baseDir)) fs.mkdirSync(baseDir, { recursive: true }); | |
console.log('等待下载的图片数量:', total); | |
await downloadImage(getCodeImgUrl()).then(buf => { | |
return sharp(buf).png().toFile(path.resolve(baseDir, `${nameBase++}.png`)); | |
}); | |
await new Promise(rs => setTimeout(() => rs(null), Math.ceil(Math.random() * 700 + 300))); | |
if (--total) await saveImages(total, nameBase, baseDir); | |
}; | |
saveImages(10, 100, './images/captcha_1/'); |
然后可以人肉识别,将验证码图片重命名为其对应的验证码值,以便用于后续的训练,有重名的可以加上后缀如 -1
。
除了 之外,还有 opencv:
- https://www.npmjs.com/package/opencv
- https://www.npmjs.com/package/opencv-wasm
相关参考
- https://github.com/tesseract-ocr/tesseract
- https://github.com/naptha/tesseract.js/
- https://github.com/emscripten-core/emscripten
- https://github.com/UB-Mannheim/tesseract/wiki
- https://www.npmjs.com/package/captcha-cv-ocr