/**
* ============================================================================
* OCR 模块 - Tesseract.js 封装
* ============================================================================
*
* 本模块封装了 Tesseract.js 的 OCR 功能,提供:
* - 图片验证(格式检查、文件存在性检查)
* - 文字识别(支持多语言)
* - 语言列表查询
*
* Tesseract.js 简介:
* - 纯 JavaScript 实现的 OCR 引擎
* - 基于 Google 的 Tesseract OCR 引擎
* - 支持 100+ 种语言
* - 无需安装额外软件,npm install 即可使用
* - 首次识别某语言时会自动下载对应的语言包(traineddata)
*
* @module ocr
*/
import Tesseract from 'tesseract.js';
import fs from 'fs';
import path from 'path';
// ============================================================================
// 常量定义
// ============================================================================
/**
* 支持的图片格式列表
* Tesseract.js 支持大多数常见图片格式
*/
const SUPPORTED_FORMATS = ['.png', '.jpg', '.jpeg', '.bmp', '.gif', '.webp'];
// ============================================================================
// 工具函数
// ============================================================================
/**
* 验证图片文件是否存在且格式正确
*
* 在执行 OCR 之前进行预检查,避免无效的识别请求:
* 1. 检查文件是否存在
* 2. 检查文件扩展名是否在支持列表中
*
* @param {string} imagePath - 图片的本地绝对路径
* @returns {{ valid: boolean, error?: string }} 验证结果对象
* - valid: true 表示验证通过,false 表示验证失败
* - error: 验证失败时的错误信息
*
* @example
* const result = validateImage('/path/to/image.png');
* if (!result.valid) {
* console.error(result.error);
* }
*/
export function validateImage(imagePath) {
// 检查文件是否存在
// fs.existsSync 是同步方法,对于简单的存在性检查足够高效
if (!fs.existsSync(imagePath)) {
return { valid: false, error: `文件不存在: ${imagePath}` };
}
// 提取文件扩展名并转为小写,确保大小写不敏感的比较
const ext = path.extname(imagePath).toLowerCase();
// 检查扩展名是否在支持列表中
if (!SUPPORTED_FORMATS.includes(ext)) {
return {
valid: false,
error: `不支持的图片格式: ${ext},支持的格式: ${SUPPORTED_FORMATS.join(', ')}`
};
}
// 验证通过
return { valid: true };
}
// ============================================================================
// 核心 OCR 函数
// ============================================================================
/**
* 使用 Tesseract.js 识别图片中的文字
*
* 这是本模块的核心函数,执行实际的 OCR 识别操作。
*
* 工作流程:
* 1. 验证图片文件
* 2. 调用 Tesseract.recognize() 执行识别
* 3. 处理识别结果并返回
*
* 关于语言参数:
* - Tesseract 使用 ISO 639-3 语言代码
* - 多语言识别时用 '+' 连接,如 'chi_sim+eng'
* - 首次使用某语言时会自动下载语言包(约 1-15MB)
*
* 关于置信度(confidence):
* - 范围 0-100,表示识别结果的可信程度
* - 一般 > 80% 认为是较可靠的识别结果
* - 低置信度可能表示图片质量差或包含非文字内容
*
* @param {string} imagePath - 图片的本地绝对路径
* @param {string[]} languages - 识别语言代码数组,默认 ['chi_sim', 'eng']
* @returns {Promise<Object>} 识别结果对象
* - success: boolean - 是否识别成功
* - text: string - 识别出的文字内容(成功时)
* - confidence: number - 识别置信度 0-100(成功时)
* - error: string - 错误信息(失败时)
* - message: string - 附加说明信息
*
* @example
* // 基本用法 - 识别中英文
* const result = await recognizeText('/path/to/image.png');
*
* @example
* // 指定语言 - 只识别日文
* const result = await recognizeText('/path/to/image.png', ['jpn']);
*
* @example
* // 多语言识别
* const result = await recognizeText('/path/to/image.png', ['chi_sim', 'chi_tra', 'eng']);
*/
export async function recognizeText(imagePath, languages = ['chi_sim', 'eng']) {
// 第一步:验证图片
const validation = validateImage(imagePath);
if (!validation.valid) {
return { success: false, error: validation.error };
}
try {
// 第二步:执行 OCR 识别
// Tesseract.recognize() 参数说明:
// - 参数1: 图片路径(也支持 URL、Buffer、Base64)
// - 参数2: 语言代码,多语言用 '+' 连接
// - 参数3: 配置选项对象
const result = await Tesseract.recognize(
imagePath,
languages.join('+'), // 将语言数组转换为 Tesseract 格式,如 'chi_sim+eng'
{
// logger 回调可用于监控识别进度,调试时可取消注释
// logger: m => console.log(m)
//
// 进度信息格式示例:
// { status: 'loading tesseract core', progress: 0.5 }
// { status: 'recognizing text', progress: 0.8 }
}
);
// 第三步:处理识别结果
// result.data 包含完整的识别信息:
// - text: 识别出的全部文字
// - confidence: 整体置信度
// - words: 单词级别的详细信息数组
// - lines: 行级别的详细信息数组
const text = result.data.text.trim(); // 去除首尾空白
const confidence = result.data.confidence;
// 处理空结果的情况
if (!text) {
return {
success: true, // 技术上识别成功,只是没有文字
text: '',
confidence,
message: '图片中未识别到文字内容'
};
}
// 返回成功结果
return {
success: true,
text,
confidence,
message: `识别完成,置信度: ${confidence.toFixed(1)}%`
};
} catch (error) {
// 捕获并返回识别过程中的错误
// 常见错误:
// - 网络问题导致语言包下载失败
// - 图片文件损坏
// - 内存不足(处理超大图片时)
return {
success: false,
error: `OCR 识别失败: ${error.message}`
};
}
}
// ============================================================================
// 语言支持
// ============================================================================
/**
* 获取支持的语言列表
*
* 返回常用语言的代码和名称映射。
* 实际上 Tesseract.js 支持 100+ 种语言,这里只列出最常用的。
*
* 完整语言列表参考:
* https://tesseract-ocr.github.io/tessdoc/Data-Files-in-different-versions.html
*
* @returns {Array<{code: string, name: string}>} 语言列表数组
* - code: Tesseract 语言代码
* - name: 语言中文名称
*
* @example
* const languages = getSupportedLanguages();
* // [{ code: 'chi_sim', name: '简体中文' }, ...]
*/
export function getSupportedLanguages() {
return [
{ code: 'chi_sim', name: '简体中文' }, // Chinese Simplified
{ code: 'chi_tra', name: '繁体中文' }, // Chinese Traditional
{ code: 'eng', name: '英文' }, // English
{ code: 'jpn', name: '日文' }, // Japanese
{ code: 'kor', name: '韩文' }, // Korean
{ code: 'fra', name: '法文' }, // French
{ code: 'deu', name: '德文' }, // German
{ code: 'spa', name: '西班牙文' }, // Spanish
{ code: 'rus', name: '俄文' }, // Russian
{ code: 'ara', name: '阿拉伯文' } // Arabic
];
}