CameraX + MLKit 打造超简单 OCR 方案
身份證掃描主要需要用到文字識別技術(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 中申請相機權限
<uses-permissionandroid:name="android.permission.CAMERA" tools:ignore="PermissionImpliesUnsupportedChromeOsHardware"/>
1.3 獲取 ProcessCameraProvider
CameraX 通過 ProcessCameraProvider 訪問相機實例。顧名思義,ProcessCamera 表示每個 Application Process 期間可使用的相機服務,所以 ProcessCameraProvider 是一個進程單例,通過 getInstance 創建并獲取。創建是一個異步過程,所以借助 CameraProviderFuture 異步返回:
//通過cameraProviderFuture異步返回創建的ProcessCameraProvider實例
valcameraProviderFuture=ProcessCameraProvider.getInstance(context)
//監聽ProcessCameraProvider獲取成功
cameraProviderFuture.addListener(
Runnable{
//獲取cameraProvider
valcameraProvider=cameraProviderFuture.get()
...
},
ContextCompat.getMainExecutor(context)//Runnable運行的Executor
)
在 Runnable 中成功獲取 ProcessCameraProvider 單例,接下來可以用它來組裝 UseCase ,實現相機功能了。
CameraX 的一個重要特征是 LifecycleAware,相機可以根據應用的前后臺情況自動開啟或關閉,降低開發者的心智負擔。ProcessCameraProvider 添加 UseCase 時會關聯 LifecycleOwner。
UseCase 根據 Lifecycle 調用 onStateAttached / onStateDetatched,當我們自定義 UseCase 時,可以在這里進行一些自定義前 / 后處理。
1.4 添加 Preview UseCase
//選擇后置鏡頭 valcameraSelector= CameraSelector.Builder().requireLensFacing(CameraSelector.LENS_FACING_BACK).build() //添加PreivewUseCase cameraProvider.bindToLifecycle( lifecycleOwner, cameraSelector, preview )
如上,ProcessCameraProvicer#bindToLifecycle 添加 Preview 。
Preview UseCase 的創建非常簡單,如下:
valpreview=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
<FrameLayout android:id="@+id/container"> <androidx.camera.view.PreviewView android:id="@+id/previewView"/> </FrameLayout>
如果我們使用 Compose 渲染 UI ,可以借助 AndroidView 顯示 PreviewView,Compose 展示相機預覽的代碼大體如下所示:
@Composable
funCameraScreen(){
//獲取ProcessCameraProvider
valcameraProviderFuture=remember{
ProcessCameraProvider.getInstance(context)
}
//顯示預覽
AndroidView(
modifier=Modifier.fillMaxSize(),
factory={ctx->
PreviewView(ctx).ly{
cameraProviderFuture.addListener({
valcameraProvider=cameraProviderFuture.get()
valpreview=//略
valcameraSelector=//略
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 ,它可以接收相機的預覽幀用于圖像分析和處理。
valimageAnalysis=ImageAnalysis.Builder) .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST).build() .ly //設置圖像分析器 setAnalyzer Executors.newSingleThreadExecutor(), OcrAnalyzerresult: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
classOcrAnalyzer(
privatevalonRecognized:(result:String)->Unit
):ImageAnalysis.Analyzer{
//獲取可識別中文的TextRecognition
privatevalrecognition=
TextRecognition.getClient(ChineseTextRecognizerOptions.Builder().build())
//對Image進行處理
overridefunanalyze(imageProxy:ImageProxy){
valimage=imageProxy.image
if(image!=null){
valimageRotation=imageProxy.imageInfo.rotationDegrees
valinputImage=InputImage.fromMediaImage(image,imageRotation)
recognition.process(inputImage)
.addOnSuccessListener{recognizedText->
valtextBlocks=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 聚合到一起,統一進行解析:
privatefunextractText(textBlocks:List<Text.TextBlock>):String{
vallines=textBlocks.flatMap{it.lines}
varname="unknown"
varid="unknown"
lines.forEach{
vallineText=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
總結
以上是生活随笔為你收集整理的CameraX + MLKit 打造超简单 OCR 方案的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 首发2亿像素HP2!三星Galaxy S
- 下一篇: 有无关通配符的相等操作符