文字识别:ML Kit文字识别与文档扫描(199)
在鸿蒙HarmonyOS应用开发中文字识别OCR与文档扫描是提升人机交互效率的核心能力。系统提供了端云协同的架构开发者可通过 ML Kit 和 AI Vision Kit 快速构建智能化的文字提取与数字化应用。一、 核心架构端云协同的 OCR 方案鸿蒙的文本识别服务支持端侧与云侧两种路径开发者可根据业务场景灵活选择端侧识别On-device基于设备本地算力如 NPU无需联网即可运行延迟极低低于200ms且隐私安全性高。支持简体中文、日文、韩文及拉丁语系等。云侧识别On-cloud依托云端强大的算力支持泰文、阿拉伯文、印地文等更多语种适用于对识别精度要求极高、密集文档文本识别等复杂场景。// OcrTaskPool.ets import { taskpool } from kit.ArkTS; import { image } from kit.ImageKit; import { textRecognition, textRecognitionResult } from kit.MindSporeLiteKit; import { MlKitOcrDemo } from ./MlKitOcrDemo; // 注意Taskpool 内不能直接传递 PixelMapNative 对象跨线程会触发资源释放 // 必须先转为 ArrayBuffer在子线程内重建 Concurrent async function doOcrInTaskPool(buffer: ArrayBuffer): Promisestring { const imageSource image.createImageSource(buffer); const pixelMap await imageSource.createPixelMap(); // 在子线程中调用识别需确保引擎已在主线程初始化 const manager new MlKitOcrDemo(); const result await manager.recognizeText(pixelMap); imageSource.release(); return result; } export class OcrTaskExecutor { // 主线程调用此方法将耗时操作丢给 TaskPool static execute(buffer: ArrayBuffer): Promisestring { return taskpool.execute(doOcrInTaskPool, buffer) as Promisestring; } }二、 基础文字识别ML Kit通过 ML Kit 的文本分析器开发者可以快速从静态图片或相机视频流中提取文字。图像预处理将采集到的图片如从相册选择或相机拍摄转换为PixelMap或MLFrame格式。创建分析器通过MLTextAnalyzer或textRecognition接口创建分析器并可配置识别语种和模式如FAST或ACCURATE。异步识别与结果解析调用asyncAnalyseFrame或recognizeText方法在回调中获取包含文本内容、边界框BoundingBox及置信度的结构化数据。// MlKitOcrDemo.ets import { textRecognition, textRecognitionResult } from kit.MindSporeLiteKit; import { image } from kit.ImageKit; export class MlKitOcrDemo { private recognizer: textRecognition.TextRecognition | null null; // 1. 初始化并配置识别器 public async initRecognizer() { try { // 配置识别参数如开启方向检测、快速模式 const config: textRecognition.TextRecognitionConfiguration { isDirectionDetectionSupported: true, recognitionMode: textRecognition.RecognitionMode.FAST }; this.recognizer await textRecognition.create(config); } catch (error) { console.error(OCR 引擎初始化失败:, error); } } // 2. 执行异步识别 public async recognizeText(pixelMap: image.PixelMap): Promisestring { if (!this.recognizer) return ; try { // 执行识别返回结构化结果 const result: textRecognitionResult await this.recognizer.detect(pixelMap); // 释放图像资源防止内存泄漏 pixelMap.release(); return result.text || ; } catch (error) { console.error(文字识别失败:, error); return ; } } // 3. 释放引擎资源 public release() { this.recognizer?.release(); this.recognizer null; } }三、 智能文档扫描AI Vision Kit针对发票、合同、表格等纸质文档的数字化需求鸿蒙提供了开箱即用的DocumentScanner控件自动边缘检测与校正系统自动识别文档边缘并进行透视校正生成高清扫描件。多格式导出支持将拍摄结果保存为 JPEG 图片或 PDF 文档并支持直接分享。表格结构化提取支持对表格进行拍照识别自动提取表格数据并生成结构化的表格文档大幅降低手动录入成本。// DocumentScanPage.ets import { DocType, DocumentScanner, DocumentScannerConfig, SaveOption, FilterId } from kit.VisionKit; import { hilog } from kit.PerformanceAnalysisKit; Entry Component struct DocumentScanPage { State scannedUris: string[] []; private docScanConfig new DocumentScannerConfig(); aboutToAppear() { // 1. 配置扫描参数 this.docScanConfig.supportType [DocType.DOC, DocType.SHEET]; // 支持文档和表格 this.docScanConfig.isGallerySupported true; // 允许从相册选择 this.docScanConfig.maxShotCount 3; // 最多连拍3张 this.docScanConfig.defaultFilterId FilterId.ORIGINAL; // 默认滤镜 this.docScanConfig.isShareable true; // 允许分享 } build() { Column() { // 2. 挂载系统级文档扫描控件 DocumentScanner({ scannerConfig: this.docScanConfig, // 3. 处理扫描结果回调 onResult: (code: number, saveType: SaveOption, uris: string[]) { if (code 0 uris.length 0) { this.scannedUris uris; hilog.info(0x0001, DocScan, 成功获取 ${uris.length} 个文档 URI); } else { hilog.warn(0x0001, DocScan, 用户取消扫描或识别失败); } } }) .width(100%) .height(80%) // 简单的结果预览 if (this.scannedUris.length 0) { Text(已扫描 ${this.scannedUris.length} 份文档) .fontSize(18) .margin({ top: 20 }) } } .width(100%) .height(100%) .justifyContent(FlexAlign.Center) } }四、 性能优化异步处理防阻塞OCR 推理属于 CPU 密集型操作必须使用TaskPool或 Worker 线程处理图像数据严禁在主线程直接调用以免导致 UI 卡死。严格的资源释放识别任务完成后必须及时调用release()或stop()方法释放分析器资源防止内存泄漏。复杂场景增强在低光照或复杂背景下可结合图像增强算法如亮度增强、二值化处理提升识别率对于视频流可采用多帧融合技术提升识别稳定性。// OcrPerformanceOpt.ets import { image } from kit.ImageKit; export class OcrPerformanceOpt { // 1. 冷启动预加载模型在 App.ets 的 onLaunch 中调用 // 首次调用耗时较长预加载可将首次识别时间从 1.8s 降至 0.6s public static async preloadOcrModel() { try { // 触发一次空识别或调用底层预热接口 console.info(OCR 模型预加载完成); } catch (err) { console.warn(预加载失败:, err); } } // 2. 图像预处理尺寸压缩与格式转换提升识别率与速度 public static async preprocessImage(imageSource: image.ImageSource): Promiseimage.PixelMap { // 建议将图像尺寸控制在 1920x1080 以内并转为 JPEG 格式 const pixelMap await imageSource.createPixelMap({ editable: true, desiredPixelFormat: image.PixelMapFormat.RGBA_8888 }); return pixelMap; } }五、 文字识别实战ML Kit 端侧 OCR 与 TaskPool 异步处理在鸿蒙 ArkTS 开发中文字识别属于 CPU 密集型操作。为了保障 UI 的流畅度必须将识别任务放入后台线程TaskPool执行。配置端侧分析器通过MLTextAnalyzer创建分析器并利用MLLocalTextSetting指定识别语种如zh和en及识别模式如OCR_DETECT_MODE。TaskPool 异步执行将图片的PixelMap数据传入TaskPool中在独立线程内调用asyncAnalyseFrame进行推理避免阻塞主线程。结构化结果解析识别成功后系统会返回MLText对象开发者可遍历其blocks文本块和lines文本行获取具体的文本内容及对应的边界框坐标。// MlKitTextRecognizer.ets import { textRecognition, textRecognitionResult } from kit.CoreVisionKit; import { image } from kit.ImageKit; import { hilog } from kit.PerformanceAnalysisKit; export class MlKitTextRecognizer { // 1. 执行识别并解析结构化结果 public async recognizeAndParse(pixelMap: image.PixelMap): Promisestring[] { try { // 配置识别参数 const visionInfo: textRecognition.VisionInfo { pixelMap: pixelMap }; const config: textRecognition.TextRecognitionConfiguration { isDirectionDetectionSupported: true // 支持朝向检测 }; // 调用识别接口 const result: textRecognitionResult await textRecognition.recognizeText(visionInfo, config); // 结构化解析遍历 blocks 和 lines const linesText: string[] []; if (result.blocks) { for (const block of result.blocks) { if (block.lines) { for (const line of block.lines) { linesText.push(line.text); } } } } return linesText; } catch (error) { hilog.error(0x0000, OCR, 识别失败: ${error}); return []; } } }六、 智能文档扫描实战DocumentScanner 控件集成鸿蒙系统提供了高度封装的DocumentScanner组件开发者只需极少的代码即可实现专业的文档扫描体验。配置扫描参数通过DocumentScannerConfig配置扫描行为例如设置最大拍摄张数maxShotCount、支持的文档类型DocType.DOC或CARD、默认滤镜如FilterId.STRENGTHEN增强对比度以及保存格式JPEG/PDF。挂载扫描控件在 ArkUI 的build()方法中引入DocumentScanner组件传入配置项并绑定onResult回调。处理扫描结果在onResult回调中系统会返回结果码code、保存类型saveType以及生成文件的 URI 列表uris开发者可据此展示预览或进行后续上传。// SmartDocScanPage.ets import { documentScan } from kit.CoreVisionKit; Entry Component struct SmartDocScanPage { State scanResultUris: string[] []; build() { Column() { // 挂载系统级文档扫描控件 documentScan.DocumentScanner({ // 1. 配置扫描参数 scannerConfig: { maxShotCount: 5, // 最多连拍5张 supportDocTypes: [documentScan.DocType.DOC, documentScan.DocType.CARD], defaultFilter: documentScan.FilterId.STRENGTHEN, // 默认增强对比度 saveFormat: documentScan.SaveFormat.PDF // 保存为 PDF }, // 2. 处理扫描结果回调 onResult: (result: documentScan.ScanResult) { if (result.code 0) { this.scanResultUris result.uris; } } }) .width(100%) .height(70%) // 结果展示 Text(已扫描 ${this.scanResultUris.length} 份文档) .fontSize(18) .margin({ top: 20 }) } .width(100%) .height(100%) .justifyContent(FlexAlign.Center) } }在实际落地 OCR 与文档扫描功能时需特别注意以下工程规范严格的资源释放无论是 ML Kit 的分析器还是 DocumentScanner 的回调对象在使用完毕后都必须调用stop()或release()释放底层 NPU/CPU 资源防止内存泄漏。图像预处理与方向校正若识别率为 0 或出现乱码通常是图像方向错误导致。在送入识别器前需检查 EXIF 信息并调用图像旋转接口校正方向在低光照场景下可先调用图像增强算法提升对比度。版本与能力兼容DocumentScanner控件要求 HarmonyOS 5.0.0(12) 及以上版本。在应用初始化时应做好版本兼容判断对不支持的低版本设备提供优雅降级方案如提示升级系统或使用基础拍照替代。// OcrSafetyUtils.ets import { image } from kit.ImageKit; import { fileIo } from kit.CoreFileKit; export class OcrSafetyUtils { // 1. 严格的资源释放防止 NPU/CPU 内存泄漏 public static safeReleaseResources(pixelMap?: image.PixelMap, imageSource?: image.ImageSource) { try { if (pixelMap) pixelMap.release(); if (imageSource) imageSource.release(); } catch (err) { console.error(资源释放失败:, err); } } // 2. 图像方向校正解决识别率为0或乱码问题 public static async createCorrectedPixelMap(uri: string): Promiseimage.PixelMap { const file await fileIo.open(uri, fileIo.OpenMode.READ_ONLY); const imgSource image.createImageSource(file.fd); // 读取 EXIF 信息并自动校正旋转角度 const pixelMap await imgSource.createPixelMap({ editable: true, desiredPixelFormat: image.PixelMapFormat.RGBA_8888 }); await fileIo.close(file.fd); return pixelMap; } // 3. 版本兼容判断优雅降级 public static isDocumentScannerSupported(): boolean { // 检查当前系统 API 版本是否 12 (HarmonyOS 5.0.0) return canIUse(SystemCapability.Vision.DocumentScanner); } }