【问题标题】:Android MLKit scan QRcode only on center of screenAndroid MLKit 仅在屏幕中心扫描二维码
【发布时间】:2021-01-16 03:47:15
【问题描述】:

我实现了 firebase MLKit 来扫描 QRCode,它正在扫描,但它正在扫描屏幕上的所有 QRcode。 我只需要扫描中心捕获的二维码(中心有箭头 ImageView),我该怎么做?

我试图裁剪 Analisys 函数(在 analysisUseCase?.setAnalyzer 内)

imageProxy.cropRect()

我尝试在 processImageProxy 函数上进行裁剪。 但是没有成功,我认为我不能用这个来裁剪

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

    }

}

【问题讨论】:

  • 您好,您可以查看我在这里给出的解决方案 stackoverflow.com/a/67348548/13300615。 Mb 它可以帮助您裁剪图像。

标签: android firebase firebase-mlkit


【解决方案1】:

imageProxy.cropRect() 只在图片中放入元数据,不做裁剪操作。对于静态图像,您可以转换为位图并裁剪。更好的方法是在所有返回的条形码都带有检测到的条形码边界框时过滤掉结果。

在 MLKit 中,我们正在添加对图像裁剪的支持。

【讨论】:

  • 所以我不能为此使用crop,我必须使用另一种方式。因为我不拍照,所以我实时扫描QR...但是我如何过滤这个结果?当 QR 在 PreviewView (cam) 的中心时检测 QR 码。我不知道
  • 您现在可以做的是获取检测到的条形码列表,并且只处理(如显示检测到的结果)感兴趣区域内的条形码。每个条码的boundingbox可以通过Barcode#getBoundingBox()获取。
【解决方案2】:

您可以在BarcodeScannerProcessor 类中修改onSuccess() 以检查条形码的四个角位置。如果在扫描区域内,则从onSuccess()返回true,如下:

protected void onSuccess(List<Barcode> barcodes, GraphicOverlay graphicOverlay) {
    if (barcodes.isEmpty()) {
        Log.v(MANUAL_TESTING_LOG, "No barcode has been detected");
    }

    for (int i = 0; i < barcodes.size(); ++i) {
        Barcode barcode = barcodes.get(i);
        BarcodeGraphic barcodeGraphic = new BarcodeGraphic(graphicOverlay, barcode);

        // check whether within valid scan area, translateX and translateY is to convert to screen position in pixel
        if (barcode.getBoundingBox() != null &&
                withinScanArea(
                    barcodeGraphic.translateY(barcode.getBoundingBox().top),
                    barcodeGraphic.translateX(barcode.getBoundingBox().left),
                    barcodeGraphic.translateY(barcode.getBoundingBox().bottom),
                    barcodeGraphic.translateX(barcode.getBoundingBox().right)
                )
        ) {
            graphicOverlay.add(barcodeGraphic);

            if (barcode.getRawValue() != null && !barcode.getRawValue().isEmpty()) {
                exchangeScannedData.sendScannedCode(barcode.getRawValue());
            }
        }
    }
}

scanAreaTop等是局部变量,根据你的扫描视图取值

private boolean withinScanArea(float top, float left, float bottom, float right) {
    return top > scanAreaTop &&
           left > scanAreaLeft &&
           bottom < scanAreaBottom &&
           right < scanAreaRight;
}

【讨论】:

    猜你喜欢
    • 2020-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多