如何使用MLKit读取条形码?

问题描述 投票:0回答:1

我一直在遵循这些指南:在 Android 上使用 ML Kit 扫描条形码图像分析以实现简单的条形码扫描仪。这是我到目前为止所得到的:

class MainActivity : ComponentActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        registerForActivityResult(ActivityResultContracts.RequestPermission()) { permission ->
            Log.d("-- CAMERA PERMISSION --", permission.toString())
        }.launch(Manifest.permission.CAMERA)

        val options = BarcodeScannerOptions.Builder()
            .setBarcodeFormats(Barcode.FORMAT_EAN_13, Barcode.FORMAT_EAN_8, Barcode.FORMAT_QR_CODE)
            .build()

        val scanner = BarcodeScanning.getClient(options)

        val analyzer = ImageAnalysis.Builder().build().apply {
            setAnalyzer(Executors.newSingleThreadExecutor()) {
                @OptIn(ExperimentalGetImage::class)
                val mediaImage = it.image
                if (mediaImage != null) {
                    val image = InputImage.fromMediaImage(mediaImage, it.imageInfo.rotationDegrees)
                    val result = scanner.process(image)
                        .addOnSuccessListener { barcodes ->
                            for (barcode in barcodes) {
                                Log.d("Barcode Scanner:", barcode.toString())
                            }
                        }
                        .addOnFailureListener { e ->
                            e.printStackTrace()
                        }
                }
            }
        }

        setContent {
            MyShopTheme {
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    CameraPreview(analyzer)
                }
            }
        }
    }
}

@Composable
fun CameraPreview(analyzer: ImageAnalysis) {
    val lifecycleOwner = LocalLifecycleOwner.current
    AndroidView(factory = { context ->
        val previewView = PreviewView(context).apply {
            scaleType = PreviewView.ScaleType.FILL_CENTER
            layoutParams = ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
            )
            implementationMode = PreviewView.ImplementationMode.COMPATIBLE
        }

        ProcessCameraProvider.getInstance(context).apply {
            addListener({
                val cameraProvider = this.get()
                val preview = androidx.camera.core.Preview.Builder().build().apply {
                    setSurfaceProvider(previewView.surfaceProvider)
                }

                try {
                    cameraProvider.unbindAll()
                    cameraProvider.bindToLifecycle(
                        lifecycleOwner,
                        CameraSelector.DEFAULT_BACK_CAMERA,
                        analyzer,
                        preview
                    )
                } catch (e: Exception) {
                    e.printStackTrace()
                }
            }, ContextCompat.getMainExecutor(context))
        }
        previewView
    })
}

有效的是我可以在显示屏上看到相机预览。当我将相机指向条形码时,我希望看到连续的输出:

条码扫描器:

但我什么也没得到。似乎图像分析从未被触发。我的预期是错误的吗?我是否需要以某种方式手动触发图像分析?还是我的代码有问题?

更新: 图像分析似乎只在应用程序启动时运行一次。未检测到条形码,因为相机没有时间捕获条形码的图像。因此,没有输出。

上面链接的文档让我相信,相机会持续向分析仪提供图像:

操作模式

当应用程序的分析管道无法跟上CameraX的分析管道时 帧速率要求,CameraX 可以配置为丢帧 以下方法之一:

非阻塞(默认):在此模式下,执行器始终缓存 将最新图像放入图像缓冲区(类似于深度为 一)当应用程序分析先前的图像时。如果相机X 在应用程序完成处理之前接收到新图像, 新图像保存到同一缓冲区,覆盖前一个图像。

那么为什么图像分析器只考虑一张图像呢?如何让它连续分析来自相机的图像?

android barcode-scanner google-mlkit
1个回答
0
投票

SudoKoach 的评论成功了:

    val analyzer = ImageAnalysis.Builder().build().apply {
        setAnalyzer(Executors.newSingleThreadExecutor()) { imageProxy ->
            @OptIn(ExperimentalGetImage::class)
            val mediaImage = imageProxy.image
            if (mediaImage != null) {
                val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)
                val result = scanner.process(image)
                    .addOnSuccessListener { barcodes ->
                        for (barcode in barcodes) {
                            Log.d("Barcode Scanner:", barcode.toString())
                        }
                    }
                    .addOnFailureListener { e ->
                        e.printStackTrace()
                    }
                    .addOnCompleteListener {
                        imageProxy.close()
                    }
            }
        }
    }

代码示例下方的文档中确实有一个注释,我错过了。

© www.soinside.com 2019 - 2024. All rights reserved.