CameraX + MLKit 打造超简单 OCR 方案
消息来源:baojiabao.com 作者: 发布时间:2026-02-14
身份证扫描主要需要用到文字识别技术(OCR)。这类技术方案已经很多了,本文介绍基于 CameraX + MLKit 的实现方式。其中 CameraX 用来实现相机的取景和预览,MLKit 用来进行图片中的文字识别。
1. CameraX 实现相机预览
1.1 CameraX 简介
Android 自 5.0 开始引入了全新的相机框架 Camera2 ,相较于之前的 Camera1 对多摄像头的支持更加友好,功能更加强大,但使用成本也更高。此背景下谷歌发布了 CameraX,它基于 Camera2 封装,大大提高了 API 的易用性。我们可以用很少的代码搭建出面向特定场景的相机应用,OCR 就是一种典型的相机应用场景 。
CameraX 引入 UseCase 的概念完成各种相机能力,UseCase 有利于功能模块的解耦,聚焦特定领域进行功能开发。CameraX 默认提供了几个常用的 UseCase 实现,能够满足大多数场景下的使用
Preview : 提供相机取景和预览
ImageCapture:拍照并保存图片
ImageAnalysis:处理预览帧图片
本文 OCR 场景中将会使用到 Preview 和 ImageAnalysis 这两个 UseCase。Preview 帮助我们实现相机的取景和预览,ImageAnalysis 帮助我们将采集的图片送入 OCR 分析。
接下来让我们使用 CameraX 一步步完成相机预览功能
1.2 工程引入 CameraX
首先,在 Gradle 中引入 CameraX 相关库如下
implementation "androidx.camera:camera-lifecycle:1.2.0"implementation "androidx.camera:camera-view:1.2.0"implementation "androidx.camera:camera-camera2:1.2.0"
另外,需要使用相机,所以在 AndroidManifest 中申请相机权限
1.3 获取 ProcessCameraProvider
CameraX 通过 ProcessCameraProvider 访问相机实例。顾名思义,ProcessCamera 表示每个 Application Process 期间可使用的相机服务,所以 ProcessCameraProvider 是一个进程单例,通过 getInstance 创建并获取。创建是一个异步过程,所以借助 CameraProviderFuture 异步返回:
// 通过 cameraProviderFuture 异步返回创建的 ProcessCameraProvider 实例val cameraProviderFuture = ProcessCameraProvider.getInstance(context)//监听 ProcessCameraProvider 获取成功cameraProviderFuture.addListener( Runnable { //获取 cameraProvider val cameraProvider = cameraProviderFuture.get() ... }, ContextCompat.getMainExecutor(context) // Runnable 运行的 Executor)在 Runnable 中成功获取 ProcessCameraProvider 单例,接下来可以用它来组装 UseCase ,实现相机功能了。
CameraX 的一个重要特征是 LifecycleAware,相机可以根据应用的前后台情况自动开启或关闭,降低开发者的心智负担。ProcessCameraProvider 添加 UseCase 时会关联 LifecycleOwner。
UseCase 根据 Lifecycle 调用 onStateAttached / onStateDetatched,当我们自定义 UseCase 时,可以在这里进行一些自定义前 / 后处理。
1.4 添加 Preview UseCase
//选择后置镜头val cameraSelector = CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build()//添加 Preivew UseCase cameraProvider.bindToLifecycle( lifecycleOwner, cameraSelector, preview)
如上,ProcessCameraProvicer#bindToLifecycle 添加 Preview 。
Preview UseCase 的创建非常简单,如下:
val preview = Preview.Builder().build().ly { setSurfaceProvider(previewView.surfaceProvider)}创建 Preview 的关键是设置渲染用的 Surface,这是通过 PreviewView 获取的。
PreviewView 是 CameraX 提供的用于显示相机预览流的自定义 View,它内部可以根据需要切换 TexureView 或者 SurfaceView。
SurfaceView 有更好的性能,但在 Android 7.0 之前无法实现旋转、透明、动画等常规自定义 View 的能力,此时需要使用 TextureView 替代。PreviewView 默认使用性能优先的 SurfaceView,如果如果需要其有更好的兼容性,则可以设置 previewView.implementationMode = PreviewView.ImplementationMode.COMPATIBLE
1.5 布局 PreviewView
我们可以像下面这样在 xml 中布局使用 PreviewView
如果我们使用 Compose 渲染 UI ,可以借助 AndroidView 显示 PreviewView,Compose 展示相机预览的代码大体如下所示:
@Composablefun CameraScreen() { //获取 ProcessCameraProvider val cameraProviderFuture = remember { ProcessCameraProvider.getInstance(context) } // 显示预览 AndroidView( modifier = Modifier.fillMaxSize(), factory = { ctx -> PreviewView(ctx).ly { cameraProviderFuture.addListener({ val cameraProvider = cameraProviderFuture.get() val preview = //略 val cameraSelector = //略 cameraProvider.unbindAll() cameraProvider.bindToLifecycle( LocalLifecycleOwner.current, cameraSelector, preview ) }, ContextCompat.getMainExecutor(previewView.context)) } }) }2. MLKit 实现文字识别
2.1 MLKit 简介
MLKit 是谷歌的面向移动端开发者的机器学习库,帮助移动应用在离线状态下使用各种端智能技术,例如:
智能视觉处理:二维码扫描、文字识别、人脸检测、物体捕捉等;
自然语言处理:语言识别、智能回复、自动翻译等
这些端上的技术让应用变得更加智能的同时依然保持高性能,更重要的是这一切都是免费的,且不依赖 GMS(Google Mobile Service)。
2.2 工程引入 MLKit
本文我们主要使用到 MLKit 的文字识别功能,只需要添加以下依赖即可:
implementation 'com.google.mlkit:text-recognition-chinese:16.0.0-6'
text-recognition-chinese 可以识别中文字符,另外也有其他的 Artifact 可以识别日文韩文等非拉丁系的语言。
2.3 CameraX 实现图像分析
前面我们通过 Preview 实现了相机预览,接下来我们为 CameraProvider 添加 ImageAnalysis ,它可以接收相机的预览帧用于图像分析和处理。
val imageAnalysis = ImageAnalysis.Builder) .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST).build() .ly //设置图像分析器 setAnalyzer Executors.newSingleThreadExecutor(), OcrAnalyzer result: String - //基于 MLKit 处理 OCR,并返回 result cameraProvider.bindToLifecycle LocalLifecycleOwner.current, cameraSelector, preview, imageAnalysis // 增加 ImageAnalysis 能力,关联 Lifecycle
setBackpressureStrategy 是设置预览帧的生产消费的缓冲策略,其默认值 ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST 表示在每一帧没有分析结束之前,新的渲染帧会自动丢弃,避免排队。
ImageAnalysis#setAnalyzer 添加自定义图像分析器,这里我们定义一个 OcrAnalyzer,它基于 MLKit 实现 OCR 功能。
2.4 自定义 OcrAnalyzer
class OcrAnalyzer( privateval onRecognized : (result: String) -> Unit) : ImageAnalysis.Analyzer { // 获取可识别中文的 TextRecognition privateval recognition = TextRecognition.getClient(ChineseTextRecognizerOptions.Builder().build()) // 对 Image 进行处理 override fun analyze(imageProxy: ImageProxy) { val image = imageProxy.image if (image != null) { val imageRotation = imageProxy.imageInfo.rotationDegrees val inputImage = InputImage.fromMediaImage(image, imageRotation) recognition.process(inputImage) .addOnSuccessListener { recognizedText -> val textBlocks = recognizedText.textBlocks //解析 textBlocks 获取所需的信息并返回 extractText(textBlocks)?.let { onRecognized(it) } imageProxy.close() }.addOnFailureListener { imageProxy.close() } } }}ImageAnalysis.Analyzer 返回的 ImageProxy 中包含了预览帧信息:
imageProxy.image:图像信息
ImageInfo.rotationDegrees:根据设备情况获得的图片旋转角度。
InputImage.fromMediaImage 根据这两个参数获取具体的 InputImage,后者提交 recognition 处理。这里的 recognition 是一个可识别中文的 TextRecognition。
2.5 解析 TextBlocks
经过 TextRecognition 文字识别后将返回 Block / Line / Element 这样的数据结构,这种结构有利于进一步细粒度的解析。
Block 代表一个自然段落,由若干 Line(行) 组成,每一个 Line 又包含多个 Element(单词) 。
假设我们希望从身份证中获取姓名以及身份证号,虽然不确定身份证这样的排版会被识别为怎样的 Block,但是姓名和身份证号肯定处于不同 Line 中。我们定义 extractText 方法,将所有的 Block 下的 Line 聚合到一起,统一进行解析:
private fun extractText(textBlocks: List): String { val lines = textBlocks.flatMap { it.lines } var name = "unknown" var id = "unknown" lines.forEach { val lineText = it.elements.joinToString { it.text } if (lineText.contains("姓名")) { name = lineText.substringAfter("姓名") } if (lineText.contains("公民身份证号码")) { id = lineText.substringAfter("公民身份证号码") } } return "$name\n$id"}
成功识别文字后的效果如下:
结束语
透过文字识别这样一个小的应用场景,我们切实感受到了 CameraX 以及 MLKit 开箱即用般的的易用性。作为谷歌官方工具包,它们还与 Compose 等其他 Jetpack 组件有着不错的兼容性。感谢谷歌强大的开发者生态,让开发者们可以低成本地开发自己的移动应用。
CameraX:https://developer.android.com/training/camerax
MLKit:https://developers.google.com/ml-kit
本文来自微信公众号:AndroidPub (ID:gh_e312d1adb6ec),作者:fundroid
2023-02-12 19:06:31相关文章
炒港股要补交多少税?我也接到催交补税特别行动的电话了2025-07-23 17:36:43
淘宝天猫仅退款属于诈骗吗?淘宝天猫开始部分取消仅退款2024-10-01 13:01:28
哈啰app借钱|哈啰借钱app下载安装免费小小上当和电话骚扰2024-10-01 11:22:38
白嫖党|山西大同大学学生网购申请“仅退款”被拒骂客服一小时2024-09-27 09:10:44
北大数学教授袁新意《姜萍事件的疑点分析》点评姜萍板书 阿里巴巴竞赛受质疑2024-06-28 10:07:40
天猫新规可以无条件申请“仅退款”了?淘宝天猫又离狗多多零元购近了一步2024-06-28 09:27:13
美国法院裁定阿里须为Squishmallows玩具侵权案答辩2023-12-28 19:59:34
小米汽车传员工3700人 雷军称小米汽车不可能卖9万92023-12-28 19:41:57
国家新闻出版署:认真研究《网络游戏管理办法(草桉徵求意见稿)》关切 实行前进一步完善2023-12-28 19:14:56
印度以打击金融犯罪为由逮捕了两名 vivo 高管2023-12-26 16:49:01
在国外微信收不到国内信息?微信和WeChat将被拆分2023-12-15 10:40:15
苹果iPhone15 系列手机发布最新消息 预计上市发布时间9月2023-08-06 23:21:02
华为将发布鸿蒙HarmonyOS4操作系统 功能五大升级支持设备清单2023-08-06 23:17:37
整治自媒体网红账号 400万粉丝网红发布擦边视频被无限期封禁2023-07-12 09:56:09
网传微信文件传输助手是真人是真的吗?微信官方回应2023-06-27 15:53:32
电信移动送手机成了“信用购”?你上了运营商的贷款套路了吗?2023-06-12 17:18:55
中国电信广东地区崩了无信号 客服回应已在核实处理2023-06-08 15:39:04
消息称小米新能源汽车价格表正讨论定价区间:双版本不同配置,高配或超 35 万元2023-03-06 12:56:03
华为因制裁被传或分拆剥离手机业务? 内部人士回应:可能性不大.2023-03-05 23:26:41
OPPO正式发布安第斯智能云,让终端更智能2023-02-24 16:02:27














