Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

computer vision - Android mlkit barcode scanner improve speed

Hello I'm using android mlkit barcode scanner without firebase with androidx ,I follow this code https://medium.com/@surya.n1447/google-vision-ml-kit-with-camerax-64bbbfd4c6fd When I scanning qrcode it is too slow and I don't know how to improve scanning speed is there some tricks or something like that ? Or is better switch to zxing or Google vision ? I using xiaomi mi 10 t pro

class ScanPersonFragment : Fragment() {

private var processingBarcode = AtomicBoolean(false)
private var mediaPlayer: MediaPlayer? = null
private lateinit var cameraExecutor: ExecutorService
private lateinit var scanBarcodeViewModel: ScanPersonViewModel


override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    cameraExecutor = Executors.newSingleThreadExecutor()
    scanBarcodeViewModel = ViewModelProvider(this).get(ScanPersonViewModel::class.java)
}

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    val v = inflater.inflate(R.layout.fragment_scan_person_destination, container, false)
    mediaPlayer = MediaPlayer.create(context, R.raw.beep)
    scanBarcodeViewModel.progressState.observe(viewLifecycleOwner, {
        v.fragment_scan_person_barcode_progress_bar.visibility = if (it) View.VISIBLE else View.GONE
    })

    scanBarcodeViewModel.navigation.observe(viewLifecycleOwner, { navDirections ->
        navDirections?.let {
            findNavController().navigate(navDirections)
            scanBarcodeViewModel.doneNavigating()
        }
    })

    return v
}

override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    if (allPermissionsGranted()) {
        startCamera()
    } else {
        requestPermissions(
            REQUIRED_PERMISSIONS,
            REQUEST_CODE_PERMISSIONS
        )
    }
}

override fun onResume() {
    super.onResume()
    processingBarcode.set(false)
}

private fun startCamera() {
    // Create an instance of the ProcessCameraProvider,
    // which will be used to bind the use cases to a lifecycle owner.
    val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())




    val imageCapture = ImageCapture.Builder()
        .setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
        //.setTargetResolution(Size(400, 400))
        .build()

    // Add a listener to the cameraProviderFuture.
    // The first argument is a Runnable, which will be where the magic actually happens.
    // The second argument (way down below) is an Executor that runs on the main thread.
    cameraProviderFuture.addListener({
        // Add a ProcessCameraProvider, which binds the lifecycle of your camera to
        // the LifecycleOwner within the application's life.
        val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
        // Initialize the Preview object, get a surface provider from your PreviewView,
        // and set it on the preview instance.
        val preview = Preview.Builder().build().also {
            it.setSurfaceProvider(
                fragment_scan_person_barcode_preview_view.surfaceProvider
            )
        }
        // Setup the ImageAnalyzer for the ImageAnalysis use case
        val imageAnalysis = ImageAnalysis.Builder()
            .setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
            .build()
            .also {
                it.setAnalyzer(cameraExecutor, BarcodeAnalyzer { barcode ->
                    if (processingBarcode.compareAndSet(false, true)) {
                        mediaPlayer?.start()
                        searchBarcode(barcode)
                    }
                })
            }

        // Select back camera
        val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
        try {
            // Unbind any bound use cases before rebinding
            cameraProvider.unbindAll()
            // Bind use cases to lifecycleOwner
            cameraProvider.bindToLifecycle(this, cameraSelector, preview,  imageAnalysis)
        } catch (e: Exception) {
            Log.e("PreviewUseCase", "Binding failed! :(", e)
        }
    }, ContextCompat.getMainExecutor(requireContext()))
}

private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
    ContextCompat.checkSelfPermission(
        requireContext(), it
    ) == PackageManager.PERMISSION_GRANTED
}

override fun onRequestPermissionsResult(
    requestCode: Int, permissions: Array<String>, grantResults:
    IntArray
) {
    if (requestCode == REQUEST_CODE_PERMISSIONS) {
        if (allPermissionsGranted()) {
            startCamera()
        } else {
            Toast.makeText(
                requireContext(),
                "Permissions not granted by the user.",
                Toast.LENGTH_SHORT
            ).show()
        }
    }
}

private fun searchBarcode(barcode: String) {
    scanBarcodeViewModel.searchBarcode(barcode)
}

override fun onDestroy() {
    cameraExecutor.shutdown()
    super.onDestroy()
}

companion object {
    private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
    private const val REQUEST_CODE_PERMISSIONS = 10
}

class BarcodeAnalyzer(private val barcodeListener: BarcodeListener) : ImageAnalysis.Analyzer {

@SuppressLint("UnsafeExperimentalUsageError")
override fun analyze(imageProxy: ImageProxy) {
    val mediaImage = imageProxy.image
    if (mediaImage != null) {
        val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)
        val options = BarcodeScannerOptions.Builder().setBarcodeFormats(Barcode.FORMAT_QR_CODE).build()
        val scanner = BarcodeScanning.getClient(options)
        // Pass image to the scanner and have it do its thing
        scanner.process(image)
            .addOnSuccessListener { barcodes ->
                // Task completed successfully
                for (barcode in barcodes) {

                    barcodeListener(barcode.rawValue ?: "")
                }
            }
            .addOnFailureListener {
                // You should really do something about Exceptions
            }
            .addOnCompleteListener {
                // It's important to close the imageProxy
                imageProxy.close()
            }
    }
}

}

question from:https://stackoverflow.com/questions/65652175/android-mlkit-barcode-scanner-improve-speed

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

To summarise some of the answers:

  • For very large images, say 108 megapixel camera, it is helpful to reduce the resolution. For typical usage, we find 1280x720 or 1920x1080 resolution to be sufficient.

  • In the near term, try using the "bundled" version of barcode SDK which has V2 of the barcode model:

    implementation 'com.google.mlkit:barcode-scanning:16.1.0'
    

    Barcode V2 implementation is faster and more accurate but it adds about 2.2 MB to your app size as a "bundled" model. The team working to bring this to the Google Play Services version (i.e. unbundled) and remove the need for the app to bundle the 2.2 MB model in the coming months.

    For more information between bundled and unbundled version, check out the table at the top of this page.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...