CameraX | 启用/禁用图像分析

4
我正在尝试使用CameraX和ZXing条形码扫描库实现条形码扫描器。
我编写了自定义分析器来解码条形码,这些条形码应该被处理(处理逻辑显然需要一些时间)。
因此,我想实时禁用图像分析,并在处理操作的结果不成功时再次启用它。
我的基本设置逻辑:
    private fun setupCamera() {
        processCameraProvider.unbindAll()
        val camera = processCameraProvider.bindToLifecycle(
            this,
            CameraSelector.DEFAULT_BACK_CAMERA,
            buildPreviewUseCase(),
            buildImageAnalysisUseCase())
    }

    private fun buildPreviewUseCase(): Preview {
        return Preview.Builder()
            .setTargetRotation(cameraPreview.display.rotation)
            .build()
            .apply {
                previewSurfaceProvider = cameraPreview.previewSurfaceProvider
            }
    }

    private fun buildImageAnalysisUseCase(): ImageAnalysis {
        return ImageAnalysis.Builder()
            .setTargetRotation(cameraPreview.display.rotation)
            .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
            .build()
            .apply {
                setAnalyzer(Executors.newSingleThreadExecutor(),
                    ZxingBarcodeAnalyzer { qrResult ->
                        Handler(Looper.getMainLooper()).post {
                            viewModel.handleBarcode(qrResult.text)
                        }
                    })
            }
    }

在查看库源代码后,我仍然不了解如何实现所需的行为?

如果我在 processCameraProvider 上调用 unbind(imageAnalysisUseCase object),我将无法再次绑定该对象(processCameraProvider 仅具有 bindToLifecycle() 方法,而没有 bind(imageAnalysisUseCase object) 方法)。

ImageAnalysis 上调用 clearAnalyzer() 将完全重置图像分析,尽管之后再调用 setAnalyzer()


你成功让它工作了吗? - Balasubramanian
@c0nst,你找到解决方案了吗?我也有同样的目标。 - Vaclovas Rekašius Jr.
3个回答

2

您可以要求生产者一次只生产一张图像,直到您关闭代理。

ImageAnalysis imageAnalysis = imageAnalysisBuilder.setBackpressureStrategy(ImageAnalysis.STRATEGY_BLOCK_PRODUCER).setImageQueueDepth(1).build();

根据文档,https://developer.android.com/reference/androidx/camera/core/ImageAnalysis#STRATEGY_BLOCK_PRODUCER 阻止生产者生成新的图像。一旦生产者产生了等于图像队列深度的图像数量,并且没有关闭任何图像,则生产者将停止生成图像。请注意,图像可能会在内部排队,直到最后一个交付的图像使用ImageProxy.close()关闭为止,才会交付给分析器。

1
假设我想要停止分析10秒钟,然后再正常继续,我该如何实施您的解决方案呢?谢谢。 - Vaclovas Rekašius Jr.
这段代码解决了我的问题。预览会暂停,直到手动调用 imageProxy.close()。谢谢! - Gilbert Parreno

1

有一个问题与clearAnalyzer()相关,

在修复之前我会这样使用:

  fun enableAnalysis(enable: Boolean) {
    if (!enable) {
        isAnalyzerSet = false
        imageAnalysisUseCase?.clearAnalyzer()
        imageAnalysisUseCase.setAnalyzer(analysisExecutor, ImageAnalysis.Analyzer { })

    } else {
        if (isAnalyzerSet) return
        isAnalyzerSet = true
        imageAnalysisUseCase?.setAnalyzer(analysisExecutor, analyzer)
    }
}

问题出现在哪个版本? - Matthias Wiedemann
1
我也遇到了重新启动分析器的问题,但它没有起作用。我的问题是我没有执行imageProxy.close()。 - Matthias Wiedemann
你能解释一下这段代码在尝试做什么吗? - Vaclovas Rekašius Jr.

0

如果你只想在处理图像时不处理任何图像,你可以在分析方法中设置一个标签,如果正在处理图像,则立即返回。类似这样:

class MyViewModel: ViewModel() {

    private var isProcessing = false

    fun handleBarcode(text: String) {
        if (isProcessing) {
            return
        }
        // Do your processing here.
    }
}

如果您调用processCameraProvider.unbind(imageAnalysis),则可以通过使用相同的实例调用processCameraProvider.bindToLifecycle(, , imageAnalysis)来重新绑定用例,但我不确定这是否有效。重新绑定相同的预览用例实例无效,我不确定该规则是否适用于ImageAnalysis。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接