【问题标题】:How to decrease frame rate of Android CameraX ImageAnalysis?如何降低 Android CameraX ImageAnalysis 的帧率?
【发布时间】:2020-04-16 14:38:03
【问题描述】:

如何在图像分析中将帧速率降低到 1 fps,这样我就不会多次检测条形码。在我的用例中,以 1 秒的间隔多次扫描相同的条形码应该增加一个计数器。所以我希望它能够正常工作。 (类似于商店收银台的产品扫描仪)

cameraX 版本:1.0.0-beta02

类似问题:

当前实施:

https://proandroiddev.com/update-android-camerax-4a44c3e4cdcc
按照这个文档,来限制图像分析。

override fun analyze(image: ImageProxy) {
    val currentTimestamp = System.currentTimeMillis()
    if (currentTimestamp - lastAnalyzedTimestamp >= TimeUnit.SECONDS.toMillis(1)) {
        // Image analysis code
    }
    image.close()
}

更好的解决方案会有所帮助。

【问题讨论】:

  • 也许使用Image Capture 用例更有意义,您可以控制何时拍摄图像?我想知道在类似需求 atm 下我的项目也是如此。
  • 只是想更新并说我试过了,发现Image Capture用例返回的imageProxy是JPEG而不是你从Image Analysis得到的YUV_420_888。也许这对某些人来说是件好事,但我没有找到任何关于这种 Android JPEG 格式的平面或缓冲区结构的文档,所以我不知道如何从那里处理事情,所以切换回图像分析而只是忽略新图像。

标签: android android-camerax


【解决方案1】:

尝试了 bmdelacruz 的解决方案。关闭图像时遇到问题。
收到类似于 this 的错误。
无法正常工作。

使用delay 对我来说效果很好。

代码

CoroutineScope(Dispatchers.IO).launch {
    delay(1000 - (System.currentTimeMillis() - currentTimestamp))
    imageProxy.close()
}

完整的 BarcodeAnalyser 代码

class BarcodeAnalyser(
    private val onBarcodesDetected: (barcodes: List<Barcode>) -> Unit,
) : ImageAnalysis.Analyzer {
    private val barcodeScannerOptions = BarcodeScannerOptions.Builder()
        .setBarcodeFormats(Barcode.FORMAT_ALL_FORMATS)
        .build()
    private val barcodeScanner = BarcodeScanning.getClient(barcodeScannerOptions)
    var currentTimestamp: Long = 0

    override fun analyze(
        imageProxy: ImageProxy,
    ) {
        currentTimestamp = System.currentTimeMillis()
        imageProxy.image?.let { imageToAnalyze ->
            val imageToProcess =
                InputImage.fromMediaImage(imageToAnalyze, imageProxy.imageInfo.rotationDegrees)
            barcodeScanner.process(imageToProcess)
                .addOnSuccessListener { barcodes ->
                    // Success handling
                }
                .addOnFailureListener { exception ->
                    // Failure handling
                }
                .addOnCompleteListener {
                    CoroutineScope(Dispatchers.IO).launch {
                        delay(1000 - (System.currentTimeMillis() - currentTimestamp))
                        imageProxy.close()
                    }
                }
        }
    }
}

【讨论】:

    【解决方案2】:

    您可以利用在关闭提供的 ImageProxy 之前不会开始下一次分析这一事实。

    就我而言,我只是让线程休眠,因为我的分析器的执行器是单线程执行器。

    class MyAnalyzer : ImageAnalysis.Analyzer {
        override fun analyze(image: ImageProxy) {
            val elapsedAnalysisTime = measureTimeMillis {
                // do your stuff here
            }
            image.use {
                if (elapsedAnalysisTime < 1000) {
                    Thread.sleep(1000 - elapsedAnalysisTime)
                }
            }
        }
    }
    

    【讨论】:

    • 很好的答案,突出了 Kotlin 语言的优势。
    【解决方案3】:
    
    private var firstDetected = true
    
    for (barcode in barcodes) {
                if (barcodes.size > 0 && firstDetected) {
                    LoggingUtility.writeLog("Analyzer",
                            "MLKitBarcode Result",
                            "Barcode is ${barcode.rawValue!!}")
                    firstDetected = false
           }
    }
    

    这可能会有所帮助

    【讨论】:

      猜你喜欢
      • 2019-12-20
      • 2019-11-20
      • 2021-03-26
      • 1970-01-01
      • 1970-01-01
      • 2020-11-24
      • 2021-07-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多