CameraX Qrcode扫描仪检测到错误
原学程将引见CameraX Qrcode扫描仪检测到毛病的处置办法,这篇学程是从其余处所瞅到的,而后减了1些海外法式员的疑问与解问,愿望能对于您有所赞助,佳了,上面开端进修吧。
成绩描写
您佳,我用CameraX开辟了1个简略的两维码扫描器。它不妨任务,但是我想在Qrcode四周展现1个预览外形。
我创立了1个定制的望图并收送条形码的界限框,然则..尺寸以及地位毛病。
我以为这是1个坐标翻译成绩。或许:(
这里有1个小项目
https://github.com/giuseppesorce/cameraxscan
部门代码:
package com.gs.scancamerax
import android.Manifest.permission.CAMERA
import android.annotation.SuppressLint
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.DisplayMetrics
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
import androidx.camera.core.*
import androidx.camera.lifecycle.ProcessCameraProvider
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import com.谷歌.mlkit.vision.barcode.BarcodeScanning
import com.谷歌.mlkit.vision.co妹妹on.InputImage
import com.gs.scancamerax.databinding.FragmentScanBarcodeBinding
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors
import java.util.concurrent.atomic.AtomicBoolean
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
typealias BarcodeListener = (barcode: String) -> Unit
class ScanBarcodeFragment : Fragment() {
private var scanningResultListener: ScanningResultListener? = null
private var flashEnabled: Boolean = false
private var camera: Camera? = null
private var processingBarcode = AtomicBoolean(false)
private lateinit var cameraExecutor: ExecutorService
private var _binding: FragmentScanBarcodeBinding? = null
private val binding get() = _binding!!
private val TAG = "CameraXBasic"
private val RATIO_四_三_VALUE = 四.0 / 三.0
private val RATIO_一六_九_VALUE = 一六.0 / 九.0
private var imageCapture: ImageCapture? = null
private var imageAnalyzer: ImageAnalysis? = null
private var cameraProvider: ProcessCameraProvider? = null
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentScanBarcodeBinding.inflate(inflater, container, false)
val view = binding.root
return view
}
override fun onResume() {
super.onResume()
processingBarcode.set(false)
initFragment()
}
private fun startCamera() {
val cameraProviderFuture = ProcessCameraProvider.getInstance(requireContext())
cameraProviderFuture.addListener(Runnable {
// CameraProvider
cameraProvider = cameraProviderFuture.get()
// Build and bind the camera use cases
bindCameraUseCases()
}, ContextCompat.getMainExecutor(requireContext()))
}
private fun aspectRatio(width: Int, height: Int): Int {
val previewRatio = max(width, height).toDouble() / min(width, height)
if (abs(previewRatio - RATIO_四_三_VALUE) <= abs(previewRatio - RATIO_一六_九_VALUE)) {
return AspectRatio.RATIO_四_三
}
return AspectRatio.RATIO_一六_九
}
private var preview: Preview? = null
private fun bindCameraUseCases() {
// Get screen metrics used to setup camera for full screen resolution
val metrics =
DisplayMetrics().also { binding.fragmentScanBarcodePreviewView.display.getRealMetrics(it) }
Log.d(TAG, "Screen metrics: ${metrics.widthPixels} x ${metrics.heightPixels}")
val screenAspectRatio = aspectRatio(metrics.widthPixels, metrics.heightPixels)
Log.d(TAG, "Preview aspect ratio: $screenAspectRatio")
val rotation = binding.fragmentScanBarcodePreviewView.display.rotation
// CameraProvider
val cameraProvider = cameraProvider
?: throw IllegalStateException("Camera initialization failed.")
// CameraSelector
val cameraSelector = CameraSelector.Builder().requireLensFacing(lensFacing).build()
// Preview
preview = Preview.Builder()
// We request aspect ratio but no resolution
.setTargetAspectRatio(screenAspectRatio)
// Set initial target rotation
.setTargetRotation(rotation)
.build()
// ImageCapture
imageCapture = ImageCapture.Builder()
.setCaptureMode(ImageCapture.CAPTURE_MODE_MINIMIZE_LATENCY)
// We request aspect ratio but no resolution to match preview config, but letting
// CameraX optimize for whatever specific resolution best fits our use cases
.setTargetAspectRatio(screenAspectRatio)
// Set initial target rotation, we will have to call this again if rotation changes
// during the lifecycle of this use case
.setTargetRotation(rotation)
.build()
// ImageAnalysis
imageAnalyzer = ImageAnalysis.Builder()
// We request aspect ratio but no resolution
.setTargetAspectRatio(screenAspectRatio)
// Set initial target rotation, we will have to call this again if rotation changes
// during the lifecycle of this use case
.setTargetRotation(rotation)
.build()
// The analyzer can then be assigned to the instance
.also {
it.setAnalyzer(cameraExecutor, BarcodeAnalyzer { luma ->
// Values returned from our analyzer are passed to the attached listener
// We log image analysis results here - you should do something useful
// instead!
Log.d(TAG, "Average luminosity: $luma")
})
}
// Must unbind the use-cases before rebinding them
cameraProvider.unbindAll()
try {
// A variable number of use-cases can be passed here -
// camera provides access to CameraControl & CameraInfo
camera = cameraProvider.bindToLifecycle(
this, cameraSelector, preview, imageCapture, imageAnalyzer
)
// Attach the viewfinder's surface provider to preview use case
preview?.setSurfaceProvider(binding.fragmentScanBarcodePreviewView.surfaceProvider)
} catch (exc: Exception) {
Log.e(TAG, "Use case binding failed", exc)
}
}
private var lensFacing: Int = CameraSelector.LENS_FACING_BACK
private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
ContextCompat.checkSelfPermission(
requireContext(), it
) == PackageManager.PERMISSION_GRANTED
}
fun initFragment() {
cameraExecutor = Executors.newSingleThreadExecutor()
if (allPermissionsGranted()) {
binding.fragmentScanBarcodePreviewView.post {
startCamera()
}
} else {
requestPermissions(REQUIRED_PERMISSIONS, REQUEST_CODE_PERMISSIONS)
}
}
override fun onRequestPermissionsResult(
requestCode: Int, permissions: Array<String>,
grantResults: IntArray
) {
if (requestCode == REQUEST_CODE_PERMISSIONS) {
if (allPermissionsGranted()) {
startCamera()
} else {
activity?.let {
Toast.makeText(
it.applicationContext,
"Permissions not granted by the user.",
Toast.LENGTH_SHORT
).show()
}
}
}
}
private fun searchBarcode(barcode: String) {
Log.e("driver", "searchBarcode: $barcode")
}
override fun onDestroy() {
cameraExecutor.shutdown()
camera = null
_binding = null
super.onDestroy()
}
inner class BarcodeAnalyzer(private val barcodeListener: BarcodeListener) :
ImageAnalysis.Analyzer {
private val scanner = BarcodeScanning.getClient()
@SuppressLint("UnsafeExperimentalUsageError")
override fun analyze(imageProxy: ImageProxy) {
val mediaImage = imageProxy.image
if (mediaImage != null) {
val image =
InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees)
// Pass image to the scanner and have it do its thing
scanner.process(image)
.addOnSuccessListener { barcodes ->
for (barcode in barcodes) {
barcodeListener(barcode.rawValue ?: "")
binding.myView.setBounds(barcode.boundingBox)
}
}
.addOnFailureListener {
// You should really do something about Exceptions
}
.addOnCompleteListener {
// It's important to close the imageProxy
imageProxy.close()
}
}
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
fun setScanResultListener(listener: ScanningResultListener) {
this.scanningResultListener = listener
}
companion object {
private val REQUIRED_PERMISSIONS = arrayOf(CAMERA)
private const val REQUEST_CODE_PERMISSIONS = 一0
const val TAG = "BarCodeFragment"
@JvmStatic
fun newInstance() = ScanBarcodeFragment()
}
}
推举谜底
没有肯定您能否依然有这个成绩,但是如今CameraX供给了1个名为CoordinateTransform的助脚类,它将坐标从1个用例转换到另外一个用例。比方,您不妨将从ImageAnalysis检测到的两维码的边框转换为预览望图坐标,并在那边画制1个边框。
// ImageProxy is the output of an ImageAnalysis.
OutputTransform source = ImageProxyTransformFactory().getOutputTransform(imageProxy);
OutputTransform target = previewView.getOutputTransform();
// Build the transform from ImageAnalysis to PreviewView
CoordinateTransform coordinateTransform = new CoordinateTransform(source, target);
// Detect barcode in ImageProxy and transform the coordinates to PreviewView.
RectF boundingBox = detectBarcodeInImageProxy(imageProxy);
coordinateTransform.mapRect(boundingBox);
// Now boundingBox contains the coordinates of the bounding box in PreviewView.
佳了闭于CameraX Qrcode扫描仪检测到毛病的学程便到这里便停止了,愿望趣模板源码网找到的这篇技巧文章能赞助到年夜野,更多技巧学程不妨在站内搜刮。