I implemented firebase MLKit to scan QRCode, it is scanning, but it is scanning all QRcode on screen. I need to scan only QRCode that are captured on the center (has arrow ImageView on the center), how can I do it?
I tried to crop on the Analisys function (inside analysisUseCase?.setAnalyzer)
imageProxy.cropRect()
I tried to crop on the processImageProxy function. But with no success, I think that I can't crop with this
class QrcodeScanner(
private val onQrCapture: Barcode.() -> Unit,
private val onFailure: Throwable.() -> Unit,
private val lifecycleOwner: LifecycleOwner,
private val context: Context,
private val previewView: PreviewView
) {
private var cameraSelector: CameraSelector = CameraSelector.Builder()
.requireLensFacing(CameraSelector.LENS_FACING_BACK)
.build()
private var cameraProvider: ProcessCameraProvider? = null
private var previewUseCase: Preview? = null
private var analysisUseCase: ImageAnalysis? = null
fun startCamera() {
val cameraProviderFuture =
ProcessCameraProvider.getInstance(context)
cameraProviderFuture.addListener(
{
runCatching {
val provider = cameraProviderFuture.get()
cameraProvider = provider
startPreview()
startAnalysis()
}.onFailure {
onFailure(it)
}
},
ContextCompat.getMainExecutor(context)
)
}
private fun startPreview() {
if (previewUseCase != null) {
cameraProvider?.unbind(previewUseCase)
}
previewUseCase = Preview.Builder()
.setTargetRotation(previewView.display.rotation)
.build()
previewUseCase?.setSurfaceProvider(previewView.surfaceProvider)
runCatching {
cameraProvider?.bindToLifecycle(lifecycleOwner,
cameraSelector,
previewUseCase
)
}.onFailure {
onFailure(it)
}
}
private fun startAnalysis() {
val options = BarcodeScannerOptions.Builder()
.setBarcodeFormats(Barcode.FORMAT_QR_CODE)
.build()
val barcodeScanner: BarcodeScanner = BarcodeScanning.getClient(options)
if (cameraProvider == null) {
return
}
if (analysisUseCase != null) {
cameraProvider?.unbind(analysisUseCase)
}
analysisUseCase = ImageAnalysis.Builder()
.setTargetRotation(previewView.display.rotation)
.build()
val cameraExecutor = Executors.newSingleThreadExecutor()
analysisUseCase?.setAnalyzer(cameraExecutor, ImageAnalysis.Analyzer { imageProxy ->
processImageProxy(barcodeScanner, imageProxy)
})
runCatching {
cameraProvider?.bindToLifecycle(lifecycleOwner,
cameraSelector,
analysisUseCase
)
}.onFailure {
onFailure(it)
}
}
@SuppressLint("UnsafeExperimentalUsageError")
private fun processImageProxy(
barcodeScanner: BarcodeScanner,
imageProxy: ImageProxy
) {
runCatching {
val img = imageProxy.image
if (img != null) {
val inputImage =
InputImage.fromMediaImage(img, imageProxy.imageInfo.rotationDegrees)
barcodeScanner.process(inputImage)
.addOnSuccessListener { barcodes ->
barcodes.forEach {
onQrCapture(it)
}
}
.addOnFailureListener {
onFailure(it)
}.addOnCompleteListener {
imageProxy.close()
}
} else {
throw Exception("Falha ao processar a imagem")
}
}.onFailure {
onFailure(it)
}
}
}
imageProxy.cropRect() only put a metadata in the image, but not do the cropping operation. For static image, you could convert to bitmap, and crop. A better way is to filter out the results when you have all the returned barcode with the detected barcode boundingbox.
Within MLKit, we are adding supports for image cropping.