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 :
How to increase frame rate with Android CameraX ImageAnalysis?
In this, the answer is based on the preview config & analysis config Builders, which was in cameraX alpha versions. But it is not found in beta versions.
How to pause barcode scanning in android ML-kit when using ByteBuffer from SurfaceView
In this, the image analysis is throttled, but I want the call to the image analyzer to be at a lower frame rate. i.e Call from image analysis usecase to image analyzer should be once in a second.
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.
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()
}
}
}
}
}
You can take advantage of the fact that the next analysis will not begin until you close the provided ImageProxy.
In my case, I just put the thread to sleep since my analyzer's executor is a single thread executor.
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)
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With