Android CameraX+MLKit如何仅分析预览界面矩形框内的条码内容
解决方案
以下是两种可直接落地的实现方案,优先推荐性能更高、实现更简单的坐标过滤方案:
方案1:条码识别后坐标过滤(推荐)
不需要裁剪图像,仅对识别返回的条码结果做坐标校验,只保留落在扫描框内的结果即可:
改造步骤
- 给
BarcodeAnalyzer增加构造参数,传入PreviewView和ViewFinderOverlay实例用于坐标转换 - 在识别成功回调中,将条码的图像坐标系坐标转换为预览View的坐标系,判断是否落在扫描框内
核心代码修改
首先修改BarcodeAnalyzer类:
class BarcodeAnalyzer( private val previewView: PreviewView, private val overlay: ViewFinderOverlay ) : ImageAnalysis.Analyzer { @SuppressLint("UnsafeOptInUsageError") override fun analyze(imageProxy: ImageProxy) { val mediaImage = imageProxy.image ?: run { imageProxy.close() return } val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees) // 条码识别客户端建议改成全局单例,不要每次分析重复创建 val scanner = BarcodeScanning.getClient() scanner.process(image) .addOnSuccessListener { barcodes -> val scanBox = overlay.boxRect ?: return@addOnSuccessListener // 构建坐标转换器:将图像分析的输出坐标转换为PreviewView的显示坐标 val transform = CoordinateTransform(imageProxy.imageInfo, previewView) barcodes.forEach { barcode -> barcode.boundingBox?.let { barcodeRect -> val mappedRect = RectF(barcodeRect) transform.mapRect(mappedRect) // 可根据业务需求调整判断逻辑:比如允许部分落在框内即可 if (scanBox.contains(mappedRect)) { val rawValue = barcode.rawValue ?: return@let // 此处处理符合要求的条码结果 } } } } .addOnCompleteListener { // 确保imageProxy总是被关闭,避免相机卡住 imageProxy.close() } } }
然后修改CameraSource类,新增PreviewView构造参数,创建Analyzer时传入实例:
class CameraSource( private val previewView: PreviewView, private val overlay: ViewFinderOverlay ) { // 原有代码保持不变 @SuppressLint("UnsafeOptInUsageError") private fun bindCameraUseCases(cameraProvider: ProcessCameraProvider) { // 原有代码保持不变 val analyzer = BarcodeAnalyzer(previewView, overlay) imageAnalysis.setAnalyzer(cameraExecutor, analyzer) // 原有代码保持不变 } }
注意:需确保项目依赖了CameraX的view核心库,
CoordinateTransform类需要androidx.camera:camera-view:1.1.0及以上版本支持
方案2:裁剪图像后再识别
如果需要严格限制仅识别扫描框区域内容,可以先裁剪图像再传入ML Kit:
- 先通过坐标映射计算出扫描框在相机输出图像上的对应区域
- 将
ImageProxy转换为Bitmap,裁剪对应区域后封装为InputImage传入识别接口
该方案涉及Bitmap转换和裁剪,性能比方案1低,仅适合对识别范围有强限制的场景。
额外优化建议
- 在
ViewFinderOverlay的onSizeChanged回调中调用setViewFinder()方法,确保布局大小变化时扫描框坐标能正确更新 - 坐标判断逻辑可灵活调整,比如扫码场景下允许条码部分露出即可触发识别,提升用户体验
内容的提问来源于stack exchange,提问作者TOvchinnikova
相关产品推荐
相关产品推荐

