使用opencv4nodejs预处理图片 优化Tesseract小数字识别
问题描述
我正尝试预处理一张图片,随后用Tesseract识别图片右侧的数字,代码如下:
const COORDINATES = { MORE_INFO_LABELS: { x: 740, y: 165, w: 112, h: 326, }, }; const worker = await createWorker("eng", OEM.TESSERACT_LSTM_COMBINED); await worker.setParameters({ tessedit_char_whitelist: "0123456789", tessedit_pageseg_mode: PSM.SINGLE_LINE, }); const moreInfoScreenshot = await cv.imdecodeAsync( await fs.readFile("test.png"), cv.IMREAD_GRAYSCALE ); const binaryImage = moreInfoScreenshot.adaptiveThreshold( 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY_INV, 11, 2 ); const moreInfoScreenshotPNG = await cv.imencodeAsync(".png", binaryImage); await cv.imwriteAsync("test-fmt.png", binaryImage); function coordinatesToRectangle(coordinates) { return { top: coordinates.y, left: coordinates.x, width: coordinates.w, height: coordinates.h, }; } const { data: { text: moreInfoText }, } = await options.worker.recognize(moreInfoScreenshotPNG, { rectangle: coordinatesToRectangle(COORDINATES.MORE_INFO_LABELS), });
处理后的图片中,Tesseract无法识别其中的较小数字,输出文本为:moreInfoText: '100408218\n18870369\n26783840937\n3330133360\n215735\n',请问如何确保这些小数字被正确识别?
优化方案
1. 调整图像预处理逻辑
- 放大目标区域:小数字尺寸不足是识别失效的核心原因,先对裁剪后的区域进行放大处理,使用
cv.resize设置fx/fy为2-3倍,选择cv.INTER_CUBIC插值方式保留细节,再执行二值化。 - 优化二值化参数:当前自适应阈值的块大小
11对小数字过于粗糙,尝试将块大小改为5或7,常数项调整为1,让小数字的边缘更锐利,减少模糊。 - 添加降噪操作:用
cv.morphologyEx执行开运算(cv.MORPH_OPEN),消除二值化后残留的噪点,避免干扰Tesseract的字符检测。
2. 调整Tesseract参数
- 修改页面分割模式:替换
PSM.SINGLE_LINE为PSM.SPARSE_TEXT,该模式适合识别分散的多行文本,能更好地捕捉小尺寸数字块。 - 更新字符白名单:将
tessedit_char_whitelist设为"0123456789\n",加入换行符帮助Tesseract正确分割行。 - 使用数字专用模型:加载Tesseract针对数字优化的训练模型,或自定义训练小尺寸数字的识别模型,提升对小数字的识别精度。
3. 优化区域分割策略
- 拆分识别区域:不要一次性识别整个右侧区域,而是为每行数字单独设置坐标,逐个区域识别,避免大区域内大小数字互相干扰。
- 校验坐标准确性:检查
COORDINATES.MORE_INFO_LABELS的坐标是否完全覆盖所有数字行,尤其是小数字的位置,确保没有偏移或遗漏。
4. 后处理校验
结合业务场景对识别结果进行长度校验,比如已知每行数字的大致长度范围,若输出长度不符则重新识别对应区域,补全遗漏的小数字。
内容的提问来源于stack exchange,提问作者user22257111
相关产品推荐
相关产品推荐

