ML Kit 条码扫描性能不佳

Bru*_*yne 4 android barcode-scanner kotlin google-mlkit

我使用 Google 的 ML Kit 进行条形码扫描,并从 Google 提供的示例和教程中收集了以下代码。然而,表演却很戏剧化。识别条形码需要几秒钟,可能是 10、15 秒。有什么办法可以改善这一点吗?

另外,这如何与倒置的条形码一起使用?我发现我需要反转图像,但是,如果在分析器中我尝试获取 image.bitmapInternal 或 image.byteBuffer,它始终为空。

构建.gradle

 implementation 'com.google.mlkit:barcode-scanning:17.0.0'
 // CameraX core library using camera2 implementation
implementation "androidx.camera:camera-camera2:1.0.2"
// CameraX Lifecycle Library
implementation "androidx.camera:camera-lifecycle:1.0.2"
// CameraX View class
implementation "androidx.camera:camera-view:1.0.0-alpha31"
Run Code Online (Sandbox Code Playgroud)

然后,在一个片段中:

typealias BarCodeListener = (barCode: String) -> Unit
const val TAG = "ConnectorScanner"
[...]

override fun onResume() {
    super.onResume()
    cameraExecutor = Executors.newSingleThreadExecutor()
    startCamera()
}

private fun startCamera() {
    val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())
    val resolution = Size(720, 1280)
    cameraProviderFuture.addListener({
        // Used to bind the lifecycle of cameras to the lifecycle owner
        val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()

        // Preview
        val preview = Preview.Builder()
            .setTargetResolution(resolution)
            .build()
            .also {
                it.setSurfaceProvider(binding.viewFinder.surfaceProvider)
            }

        imageCapture = ImageCapture.Builder()
            .setTargetResolution(resolution)
            .setCaptureMode(ImageCapture.CAPTURE_MODE_MAXIMIZE_QUALITY)
            .build()

        val imageAnalyzer = ImageAnalysis.Builder()
            .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
            .build()
            .also {
                it.setAnalyzer(cameraExecutor, BarCodeAnalyzer { barCode ->
                    if (BuildConfig.DEBUG) {
                        Toast.makeText(context, "Code: $barCode", Toast.LENGTH_LONG).show()
                    }
                    viewModel.onConnectorCodeScanned(barCode)
                    cameraProvider.unbindAll()
                })
            }

        // Select back camera as a default
        val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA

        try {
            // Unbind use cases before rebinding
            cameraProvider.unbindAll()

            // Bind use cases to camera
            cameraProvider.bindToLifecycle(
                this, cameraSelector, preview, imageCapture, imageAnalyzer
            )

        } catch (exc: Exception) {
            Log.e(TAG, "Use case binding failed", exc)
            showErrorDialog()
        }

    }, ContextCompat.getMainExecutor(requireContext()))
}
Run Code Online (Sandbox Code Playgroud)

图像分析仪

private class BarCodeAnalyzer(private val listener: BarCodeListener) : ImageAnalysis.Analyzer {
    val options = BarcodeScannerOptions.Builder()
        .setBarcodeFormats(
            Barcode.FORMAT_DATA_MATRIX
        )
        .build()

    @SuppressLint("UnsafeOptInUsageError")
    override fun analyze(imageProxy: ImageProxy) {
        val mediaImage = imageProxy.image
        mediaImage?.let {
            val image =
                InputImage.fromMediaImage(it, imageProxy.imageInfo.rotationDegrees)
                val scanner = BarcodeScanning.getClient(options)

            scanner.process(image)
                .addOnSuccessListener { barcodes ->
                    if (barcodes.isNotEmpty()) {
                        barcodes.firstOrNull()?.rawValue?.let { barcode ->
                            Log.d(TAG, barcode)
                            listener(barcode)
                        }
                        imageProxy.close()
                    }
                }
        }
        imageProxy.close()
    }
}
Run Code Online (Sandbox Code Playgroud)

Bru*_*yne 9

幸运的是,我找到了性能问题的解决方案,它添加了一个 OnCompleteListener 并关闭那里的图像。所以分析器将是

scanner.process(image)
                .addOnSuccessListener { barcodes ->
                    if (barcodes.isNotEmpty()) {
                        barcodes.firstOrNull()?.rawValue?.let { barcode ->
                            Log.d(TAG, barcode)
                                listener(barcode)
                        }
                    }
                }
                .addOnCompleteListener {
                    imageProxy.close()
                }
        }
Run Code Online (Sandbox Code Playgroud)

现在条形码的扫描速度快如闪电!