鸿蒙端侧OCR实战:Core Vision Kit离线文字识别
鸿蒙端侧OCR实战:Core Vision Kit离线文字识别
需求与选型
移动端要做文字识别(OCR),第一反应往往是接云端 API。但在实际项目里,端侧方案越来越值得优先考虑,尤其这三个场景:图片涉及证件、票据等敏感信息,不能出设备;弱网或离线环境(巡检、仓储)必须可用;调用量大、按次计费的云 API 成本压不住。
两条路线对比:
| 维度 | 云端 OCR API | 端侧(Core Vision Kit) |
|---|---|---|
| 网络依赖 | 必须 | 无,离线可用 |
| 隐私 | 图片上传到服务端 | 数据不出设备 |
| 成本 | 按次计费 | 免费 |
| 延迟 | 网络往返,几百 ms 起 | 端侧推理,通常百 ms 级 |
| 模型能力 | 强,场景丰富 | 印刷体为主,手写/艺术字是边界 |
鸿蒙侧的端选方案是 Core Vision Kit 的 textRecognition:模型跑在设备上,支持简体中文、繁体中文、英文、日文、韩文的印刷体识别,无需申请任何权限(OCR 本身不涉及敏感权限),Stage 模型下即可直接调用。本文用"选图 → 识别 → 取词"这个小工具,把完整链路走一遍。
调用范式:三步拿到识别结果
import { textRecognition } from '@kit.CoreVisionKit';
import { image } from '@kit.ImageKit';
let visionInfo: textRecognition.VisionInfo = { pixelMap: pixelMap };
let result: textRecognition.TextRecognitionResult =
await textRecognition.recognizeText(visionInfo);
范式极简:构造 VisionInfo(包一个 PixelMap)→ 调 recognizeText → 解析结果。但有几个约束要先交代清楚,都是实际会踩的点:
- 输入只认
PixelMap,格式必须RGBA_8888。相册、相机、资源文件解出的 PixelMap 默认就是这个格式,一般不用手动转;从网络拿 JPEG/PNG 解码后同样成立。 - 图片建议不超过 4096×4096。超大图先缩放,速度和精度都更稳。
- 可以传第二个参数
TextRecognitionConfiguration,目前只有一个开关isDirectionDetectionSupported(默认true)。如果图片方向已知,关掉它能省一次方向检测,提速明显:
let config: textRecognition.TextRecognitionConfiguration = {
isDirectionDetectionSupported: false // 方向已知时跳过检测
};
let result = await textRecognition.recognizeText(visionInfo, config);
结果解析:块/行/字三级树 + 坐标
TextRecognitionResult 是一棵从粗到细的三级树:blocks(文本块)→ lines(文本行)→ words(单词)。每层都同时给文本内容和 cornerPoints 边界框坐标(顺时针四点,第一个点是左上角)。
// 只要全文:拼接块的文本即可
const fullText = result.blocks.map(b => b.value).join('\n');
// 要行级/字级信息(取词、框选、高亮)时下钻
for (const block of result.blocks) {
for (const line of block.lines) {
console.info(`行文本: ${line.value}`); // 行内容
console.info(`行坐标: ${JSON.stringify(line.cornerPoints)}`);
for (const word of line.words) {
// word.value / word.cornerPoints:单词级内容和坐标
}
}
}
cornerPoints 是整套 API 里最值钱的部分——它意味着不仅能拿到"图里写了什么",还能拿到"写在哪里"。点击取词、划选翻译、区域高亮、票据字段定位,全都建立在坐标之上。
完整实现:选图取词工具
下面是一个可以直接跑的页面:相册选图 → 转 PixelMap → 识别 → 展示全文,错误路径全部兜住。
import { textRecognition } from '@kit.CoreVisionKit';
import { image } from '@kit.ImageKit';
import { fileIo } from '@kit.CoreFileKit';
import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { BusinessError } from '@kit.BasicServicesKit';
@Entry
@Component
struct OcrPage {
@State resultText: string = '';
@State loading: boolean = false;
async pickAndRecognize(): Promise<void> {
const picker = new photoAccessHelper.PhotoViewPicker();
const res = await picker.select({
MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE,
maxSelectNumber: 1
});
const uri = res.photoUris[0];
if (!uri) return;
this.loading = true;
try {
// 1. URI → PixelMap
const file = await fileIo.open(uri, fileIo.OpenMode.READ_ONLY);
const source = image.createImageSource(file.fd);
const pixelMap = await source.createPixelMap();
// 2. 端侧识别
const visionInfo: textRecognition.VisionInfo = { pixelMap };
const result = await textRecognition.recognizeText(visionInfo);
// 3. 解析结果
this.resultText = result.blocks.map(b => b.value).join('\n');
if (!this.resultText) {
this.resultText = '未识别到文字,请换一张更清晰的图片';
}
pixelMap.release();
source.release();
} catch (err) {
const e = err as BusinessError;
this.resultText = `识别失败(code=${e.code}),请重试`;
} finally {
this.loading = false;
}
}
build() {
Column({ space: 16 }) {
Button('选择图片并识别')
.onClick(() => this.pickAndRecognize())
if (this.loading) {
LoadingProgress().width(40).height(40)
} else {
Scroll() {
Text(this.resultText)
.fontSize(16)
.copyOption(CopyOptions.InApp) // 识别结果可直接长按复制
}
.layoutWeight(1)
.padding(16)
}
}
.width('100%')
.height('100%')
.padding(16)
}
}
两个工程细节:loading 态让识别期间 UI 有明确反馈(端侧推理虽快,大图也要几百 ms);pixelMap 和 ImageSource 用完即 release(),列表页反复识别的场景漏释放会持续涨内存。
踩坑与调优
错误码要逐个兜。recognizeText 的 Promise 里会抛业务错误,实际遇到最多的是这几个:
200识别超时——大图或后台负载时偶发,提示重试即可;401参数校验失败——九成是 PixelMap 无效或已 release;1001400001运行失败——可重试一次;1001400002服务异常——引导重启应用。
识别效果差的排查顺序。端侧模型对"清晰、正对、背景简单"的印刷体效果最好,效果差时按这个顺序查:
- 图片是否过小或过模糊(先看分辨率,低于几十像素高的文本行基本没戏);
- 文字是否倾斜严重——方向检测只管 90°/180° 级别的旋转,不管小角度纠偏;
- 背景是否杂乱、文字是否被遮挡。
手写体和艺术字是能力边界,需要这类识别时再考虑云端方案,端侧别硬扛。
小结
Core Vision Kit 的 textRecognition 用极低的集成成本换来了免费、离线、隐私安全的端侧 OCR:一次 Promise 调用,拿到带坐标的三级文本树。它适合印刷体识别的主流场景(票据、名片、截图取词、无网录入),调用范式也是 Core Vision Kit 全家族端侧 AI 能力(人脸检测、卡证识别等)的通用模板,学会这一个,其余能力照葫芦画瓢即可。
更多推荐



所有评论(0)