Android -使用MLKit的条形码扫描对于Barcode.FORMAT_CODE_39不准确

tzxcd3kk  于 2023-05-21  发布在  Android
关注(0)|答案(1)|浏览(190)

我正在我的Android应用程序中实现条形码扫描功能。它的工作伟大的基本QR码或条形码FORMAT-128。但对于条形码FORMAT-39不准确。有时它捕获正确的值,有时捕获错误的值。(特别是当条形码值包含重复值,如A00000190)下面是我尝试的代码和相应的扫描值。
1.条形码值:AA00000029001

扫描结果,随机选择以下之一:AA0000029001、AA000029001、A100029001、AA00029001 ..等等
下面是我的代码片段。

class MainActivity3 : AppCompatActivity(), BarcodeScannerListener {

    companion object {
        private const val CAMERA_REQUEST_CODE = 101
        private const val TAG = "MAIN_ACTIVITY"
    }

    private lateinit var viewBinding: ActivityMain3Binding

    private val executorService: ExecutorService by lazy {
        Executors.newSingleThreadExecutor()
    }

    private val barcodeScanner by lazy {
        BarcodeScanner(this)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        viewBinding = ActivityMain3Binding.inflate(layoutInflater)
        setContentView(viewBinding.root)

        setupCamera()
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>,
                                            grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == CAMERA_REQUEST_CODE && isCameraPermissionGranted()) {
            startCamera()
        }
    }

    private fun setupCamera() {
        if (isCameraPermissionGranted()) {
            startCamera()
        } else {
            requestPermission()
        }
    }

    private fun startCamera() {
        val cameraProviderFuture = ProcessCameraProvider.getInstance(this)

        cameraProviderFuture.addListener({
            val cameraProvider = cameraProviderFuture.get()
            val preview = Preview.Builder().build().apply {
                setSurfaceProvider(viewBinding.cameraPreview.surfaceProvider)
            }
            val imageAnalyzer = ImageAnalysis.Builder().build().apply {
                setAnalyzer(executorService, getImageAnalyzerListener())
            }

            try {
                cameraProvider.unbindAll()
                cameraProvider.bindToLifecycle(
                    this,
                    CameraSelector.DEFAULT_BACK_CAMERA,
                    preview,
                    imageAnalyzer
                )
            } catch (throwable: Throwable) {
                Log.e(TAG, "Use case binding failed", throwable)
            }
        }, ContextCompat.getMainExecutor(this))
    }

    @SuppressLint("UnsafeOptInUsageError")
    private fun getImageAnalyzerListener(): ImageAnalysis.Analyzer {
        return ImageAnalysis.Analyzer { imageProxy ->
            val image = imageProxy.image ?: return@Analyzer
            val inputImage = InputImage.fromMediaImage(image, imageProxy.imageInfo.rotationDegrees)
            barcodeScanner.scanImage(inputImage) {
                imageProxy.close()
            }
        }
    }

    override fun onSuccessScan(result: List<Barcode>) {
        result.forEachIndexed { index, barcode ->
            Log.e("MainActivity3","Barcode value : ${barcode.rawValue}")
            Toast.makeText(this, "Barcode value: ${barcode.rawValue}", Toast.LENGTH_SHORT).show()
        }
    }

    override fun onScanFailed() {
        Toast.makeText(this, "Fail", Toast.LENGTH_SHORT).show()
    }

    private fun isCameraPermissionGranted(): Boolean {
        return ContextCompat.checkSelfPermission(this,
            Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED
    }

    private fun requestPermission() {
        ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.CAMERA),
            CAMERA_REQUEST_CODE)
    }

    override fun onDestroy() {
        super.onDestroy()
        barcodeScanner.closeScanner()
        executorService.shutdown()
    }
}

扫描仪功能:

class BarcodeScanner(private val barcodeScannerListener: BarcodeScannerListener) {

    private val barcodeScanner: BarcodeScanner by lazy {
        constructBarcodeScanner()
    }

    private val executorService: ExecutorService by lazy {
        Executors.newSingleThreadExecutor()
    }

    fun scanImage(inputImage: InputImage, onScanComplete: (() -> Unit)? = null) {
        barcodeScanner.process(inputImage)
            .addOnCompleteListener {
                onScanComplete?.invoke()
            }
            .addOnSuccessListener {
                barcodeScannerListener.onSuccessScan(it)
            }
            .addOnFailureListener {
                Log.e("Scanner fail", "caused:", it)
                barcodeScannerListener.onScanFailed()
            }
    }

    fun closeScanner() {
        barcodeScanner.close()
        executorService.shutdown()
    }

    private fun constructBarcodeScanner(): BarcodeScanner {
        val barcodeScannerOptions = BarcodeScannerOptions.Builder()
            .setExecutor(executorService)
            .setBarcodeFormats(
              //  Barcode.FORMAT_ALL_FORMATS,
                Barcode.FORMAT_CODE_39
            )
            .build()
        return BarcodeScanning.getClient(barcodeScannerOptions)
    }
}

下面是我测试和扫描结果的一些其他条形码
1.条形码值:R000000590

扫描结果,随机选择以下之一:R00000590,R00000590,V00000590,40000590,200000590 ..等等
1.条形码值:ABC-1200000034


扫描结果随机选择以下之一:ABC-120000034、ABC-12000034、ABC-120000034、BP712000034、BP-12000034、ABC712000034 ..等等
有人可以帮助解决这些条形码与格式-39问题。其他类型,如QR Codeformat-128都可以正常工作。

vlju58qv

vlju58qv1#

因为分析仪多次读取图像,所以数据重复。阅读完成后必须关闭图像

fun scanImage(inputImage: InputImage, onScanComplete: (() -> Unit)? = null) {
        barcodeScanner.process(inputImage)
            .addOnCompleteListener {
                 barcodeScannerListener.onSuccessScan(it)
            //imageProxy should be closed here 
            }
            .addOnFailureListener {
                Log.e("Scanner fail", "caused:", it)
                barcodeScannerListener.onScanFailed()
            }
    }

或者试试这个,看看结果:

override fun onSuccessScan(result: List<Barcode>) {
        Log.e("MainActivity3","Barcode value : ${result.toString()}")
  
}

相关问题