You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android CameraX+MLKit如何仅分析预览界面矩形框内的条码内容

解决方案

以下是两种可直接落地的实现方案,优先推荐性能更高、实现更简单的坐标过滤方案:

方案1:条码识别后坐标过滤(推荐)

不需要裁剪图像,仅对识别返回的条码结果做坐标校验,只保留落在扫描框内的结果即可:

改造步骤

  1. 给BarcodeAnalyzer增加构造参数,传入PreviewView和ViewFinderOverlay实例用于坐标转换
  2. 在识别成功回调中,将条码的图像坐标系坐标转换为预览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:

  1. 先通过坐标映射计算出扫描框在相机输出图像上的对应区域
  2. 将ImageProxy转换为Bitmap,裁剪对应区域后封装为InputImage传入识别接口
    该方案涉及Bitmap转换和裁剪,性能比方案1低,仅适合对识别范围有强限制的场景。

额外优化建议

  • 在ViewFinderOverlay的onSizeChanged回调中调用setViewFinder()方法,确保布局大小变化时扫描框坐标能正确更新
  • 坐标判断逻辑可灵活调整,比如扫码场景下允许条码部分露出即可触发识别,提升用户体验

内容的提问来源于stack exchange,提问作者TOvchinnikova

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.11 01:24:03