不想搭后端?一个 JS 库让网页直接完成 OCR 文字识别
不想搭后端一个 JS 库让网页直接完成 OCR 文字识别【免费下载链接】tesseract.jsPure Javascript OCR for more than 100 Languages 项目地址: https://gitcode.com/GitHub_Trending/te/tesseract.js你是否遇到过这样的需求用户上传一张图片网页就能把里面的文字读出来。过去我第一反应是去找 OCR 云服务结果不是要注册账号、申请密钥就是要自己维护一台服务器跑识别服务。直到我遇见了Tesseract.js——这是一个纯 JavaScript 编写的 OCR 引擎把著名的 Tesseract 识别内核通过 WebAssembly 搬进了浏览器。这意味着前端零后端 OCR 方案成为可能不搭服务器、不写接口一个 HTML 文件就能完成图片文字提取。本文记录了我从零到一集成它的完整过程以及一路上踩过的坑。第一步让网页开口读图只差一个 script 标签Tesseract.js 支持通过 CDN 引入也支持 npm 安装。对只想快速验证、或做纯前端页面的朋友来说CDN 是最省事的方式。不过有个细节我一开始没在意一定要写死版本号。script srchttps://cdn.jsdelivr.net/npm/tesseract.js5/dist/tesseract.min.js/script把5锁在这里能避免后续版本升级带来的行为差异。等哪天想升级再手动改版本号并回归测试这比让页面自动追新安全得多。引入之后核心逻辑其实只有三步创建 Worker → 绑定图片 → 识别取字。下面是一个完整的上传即识别示例input typefile idpicker acceptimage/* pre idresult/pre script // 创建识别 Worker语言用英文引擎模式为 LSTM const worker await Tesseract.createWorker(eng, 1, { logger: m console.log(进度 ${(m.progress * 100).toFixed(1)}%${m.status}) }); document.getElementById(picker).addEventListener(change, async (e) { const file e.target.files[0]; if (!file) return; const { data: { text } } await worker.recognize(file); document.getElementById(result).textContent text; }); /script打开页面选一张图片控制台会依次打印加载语言包 → 初始化引擎 → 识别中的进度稍等片刻图片里的文字就被抠出来了。第一次运行会下载语言数据约 2MB之后浏览器会把它缓存进 IndexedDB下次识别就快多了。第二步中英文混合识别改一个参数就行英文识别没问题后我开始处理中文图片。一开始我以为要做什么复杂配置结果只需要把语言代码从eng换成chi_simeng——用加号连接多个语言代码就是混合识别const worker await Tesseract.createWorker(chi_simeng, 1, { logger: m console.log(m) }); const ret await worker.recognize(mixed-language.png); console.log(识别结果:, ret.data.text);Tesseract.js 支持 100 多种语言的识别简体中文chi_sim、繁体chi_tra、日文jpn、韩文kor都在其中。如果你有截图取词类需求比如识别包含中英文混排的公众号文章截图这个组合基本够用。第三步识别不准先试试圈定区域和告诉引擎你只要什么用默认参数跑出来的结果在复杂图片上往往会夹带噪点文字。我的经验是别急着上高级算法先把下面两个手段用起来绝大多数场景都能明显改善。手段一用 rectangle 限定识别区域。比如票据上只有金额那一栏是我需要的其他区域都是干扰那就把识别范围圈出来const { data: { text } } await worker.recognize(imageFile, { rectangle: { left: 0, top: 0, width: 300, height: 200 } });引擎只处理这个矩形内的内容既省时间又避免无关文字混进结果。手段二用 setParameters 收紧识别规则。如果目标内容本身是固定格式比如只含数字的验证码、只含字母的快递单号可以直接告诉引擎你只能输出这些字符await worker.setParameters({ tessedit_pageseg_mode: Tesseract.PSM.SINGLE_LINE, // 整张图只有一行文字时用 tessedit_char_whitelist: 0123456789 // 只允许数字出现 });tessedit_pageseg_mode页面分割模式决定了引擎如何理解版面整页排版用AUTO单行文本用SINGLE_LINE单个单词用SINGLE_WORD。whitelist则相当于给输出上了一道白名单。两者搭配识别速度和准确率都能上一个台阶。第四步批量图片排队太慢让多个 Worker 并行干活单张识别没问题之后我遇到了第二个坎一次性丢进来 10 张图片一张张排队识别慢得让人怀疑人生。后来在官方示例里找到了正解——Scheduler 调度器。它的思路是先建一个 Worker 池建议数量不超过 CPU 核心数再把识别任务丢进队列调度器自动把任务分给空闲的 Worker 并行执行const scheduler Tesseract.createScheduler(); // 预创建 4 个 Worker 并加入池子 for (let i 0; i 4; i) { const w await Tesseract.createWorker(eng, 1, { workerPath: /dist/worker.min.js }); scheduler.addWorker(w); } // 批量提交识别任务 const tasks imageFiles.map(file scheduler.addJob(recognize, file) ); const results await Promise.all(tasks); // 汇总所有识别文本 const allTexts results.map(r r.data.text); await scheduler.terminate(); // 用完统一销毁我在自己机器上实测过单 Worker 顺序处理 10 张图大约要 45 秒换成 4 个 Worker 并行后压到 15 秒左右提速接近三倍。注意每个 Worker 都会占不少内存Worker 数量并非越多越好4 个左右是大多数设备的甜点区。第五步踩坑实录——跨域图片和语言包加载失败跨域图片怎么识别直接拿一张来自其他域名的图片 URL 丢给recognize很可能因为 Canvas 跨域污染直接报错。我采用的兜底方案是先把图片转成 Base64 再喂给引擎。async function toBase64(url) { const resp await fetch(url, { mode: cors }); const blob await resp.blob(); return new Promise((resolve) { const reader new FileReader(); reader.onloadend () resolve(reader.result); reader.readAsDataURL(blob); }); } const dataUrl await toBase64(https://example.com/remote.jpg); const { data: { text } } await worker.recognize(dataUrl);如果远程图片本身没开 CORSfetch也会失败那就只能走代理转发或者让用户先下载再上传。语言包下载超时/失败怎么办公网 CDN 偶尔抽风语言包加载失败时页面会一直卡在初始化。解决办法是把核心文件和语言数据放到自己的服务器上通过路径参数指定const worker await Tesseract.createWorker(eng, 1, { corePath: /static/tesseract-core, // 指向包含 4 个 wasm 内核文件的目录 workerPath: /static/worker.min.js, // Worker 脚本路径 langPath: /static/lang // 语言包目录不要以 / 结尾 });这里要提醒一句corePath一定要指向目录而不是某个具体的.js文件目录里需要放齐tesseract-core.wasm.js、tesseract-core-simd.wasm.js、tesseract-core-lstm.wasm.js和tesseract-core-simd-lstm.wasm.js四个文件让引擎根据用户设备自动挑选最合适的内核否则要么性能大打折扣要么在某些设备上直接跑不起来。语言包则按langPath 语言代码 .traineddata.gz的规则命名存放即可。收尾移动端和长期维护的几个习惯把功能上线后我又做了几处收尾优化也算是对后来者的建议Worker 只建一次别每次识别都重建。官方示例里反复强调Worker 创建、加载语言包的开销远大于识别本身正确的做法是页面加载时预创建之后反复recognize。这是图片文字提取类工具最容易踩的性能坑。移动端先压图再识别。手机相册的照片动辄几 MB识别前先在前端把宽度压到 800px 以内内存占用和耗时都会明显下降还可以顺手设preserve_interword_spaces: 0减少计算量。识别逻辑跑在 Worker 里天然不阻塞 UI。这也是我选它的原因之一识别过程中页面照样能滚动、能点按钮不需要自己折腾多线程。不要识别手写体。Tesseract 的模型是为印刷体设计的手写内容基本识别不出来别在需求阶段就掉进这个坑。第一次使用要留意初始化耗时。首次加载语言包约 2MB如果应用里只有少数用户用 OCR可以考虑等用户点击开始识别后再创建 Worker而不是页面一打开就下载。写在最后回顾整个集成过程Tesseract.js 最打动我的地方是零门槛不用注册云服务、不用维护后端、不写一行服务端代码一个 script 标签加几行调用浏览器自己就能完成 OCR 文字识别。如果你也正在为网页识别图片里的字发愁不妨按本文的路径自己动手试一遍——从 CDN 引入、中英文混合识别到区域圈定、批量并行再到离线兜底这条路我已经替你趟平了。想深入研究的读者可以直接看项目内的docs/目录API 参考、性能优化、常见问题都在里面以及examples/目录下的完整示例代码需要本地部署或定制功能时可以拉取仓库源码https://gitcode.com/GitHub_Trending/te/tesseract.js。动手试试吧你的第一个会读图的网页可能只需要十分钟。【免费下载链接】tesseract.jsPure Javascript OCR for more than 100 Languages 项目地址: https://gitcode.com/GitHub_Trending/te/tesseract.js创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考