Search code examples
androidandroid-camerax

How to decrease frame rate of Android CameraX ImageAnalysis?


How to decrease the frame rate to 1 fps in image analysis so that I don't detect barcode multiple times. In my use-case, scanning the same barcode multiple times with a 1-second interval should increment a counter. So I want it to work correctly. (Similar to product scanner at shop tills)

cameraX version : 1.0.0-beta02

Similar questions :

Current implementation :

https://proandroiddev.com/update-android-camerax-4a44c3e4cdcc
Following this doc, to throttle image analysis.

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

A better solution would be helpful.


Solution

  • Tried bmdelacruz's solution. Had issues with closing the image.
    Was getting an error similar to this.
    Couldn't get it working.

    Using delay worked well for me.

    Code

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

    Complete BarcodeAnalyser code

    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()
                        }
                    }
            }
        }
    }