这是我剥离的条形码扫描源代码
build.gradle
dependencies {
.....
// MLKit Dependencies
implementation 'com.google.android.gms:play-services-vision:20.1.3'
implementation 'com.google.mlkit:barcode-scanning:17.0.2'
def camerax_version = "1.1.0-beta01"
implementation "androidx.camera:camera-core:${camerax_version}"
implementation "androidx.camera:camera-camera2:${camerax_version}"
implementation "androidx.camera:camera-lifecycle:${camerax_version}"
implementation "androidx.camera:camera-video:${camerax_version}"
......
}ScanCameraFragment.kt
class ScanCameraFragment : BaseFragment() {
private lateinit var binding: FragmentScanCameraBinding
private lateinit var cameraExecutor: ExecutorService
//region Lifecycle Methods
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
binding = FragmentScanCameraBinding.inflate(inflater, container, false)
cameraExecutor = Executors.newSingleThreadExecutor()
startCamera()
return binding.root
}
override fun onDestroyView() {
super.onDestroyView()
cameraExecutor.shutdown()
}
companion object {
fun newInstance() = ScanCameraFragment().apply {}
}
private fun startCamera() {
context?.let { context ->
val cameraProviderFuture = ProcessCameraProvider.getInstance(context)
cameraProviderFuture.addListener({
val cameraProvider = cameraProviderFuture.get()
// Preview
val preview = Preview.Builder()
.build()
.also {
it.setSurfaceProvider(binding.previewView.surfaceProvider)
}
// Image analyzer
val imageAnalyzer = ImageAnalysis.Builder()
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
.also {
it.setAnalyzer(cameraExecutor,
QrCodeAnalyzer(context, binding.barcodeBoxView,
binding.previewView.width.toFloat(),
binding.previewView.height.toFloat()
)
)
}
// Select back camera as a default
val cameraSelector = CameraSelector.DEFAULT_BACK_CAMERA
try {
// Unbind use cases before rebinding
cameraProvider.unbindAll()
// Bind use cases to camera
var camera = cameraProvider.bindToLifecycle(this, cameraSelector,
preview, imageAnalyzer)
} catch (exc: Exception) {
exc.printStackTrace()
}
}, ContextCompat.getMainExecutor(context))
}
}
}QRCodeAnalyzer.kt
class QrCodeAnalyzer(private val context: Context,
private val barcodeBoxView: BarcodeBoxView, private val previewViewWidth: Float,
private val previewViewHeight: Float) : ImageAnalysis.Analyzer {
private var scaleX = 1f
private var scaleY = 1f
private fun translateX(x: Float) = x * scaleX
private fun translateY(y: Float) = y * scaleY
private fun adjustBoundingRect(rect: Rect) = RectF(
translateX(rect.left.toFloat()),
translateY(rect.top.toFloat()),
translateX(rect.right.toFloat()),
translateY(rect.bottom.toFloat())
)
@SuppressLint("UnsafeOptInUsageError")
override fun analyze(image: ImageProxy) {
val img = image.image
if (img != null) {
// Update scale factors
scaleX = previewViewWidth / img.height.toFloat()
scaleY = previewViewHeight / img.width.toFloat()
val inputImage = InputImage.fromMediaImage(img,
image.imageInfo.rotationDegrees)
// Process image searching for barcodes
val options = BarcodeScannerOptions.Builder()
.build()
val scanner = BarcodeScanning.getClient(options)
scanner.process(inputImage)
.addOnSuccessListener { barcodes ->
for (barcode in barcodes) {
barcode?.rawValue?.let {
if (it.trim().isNotBlank()) {
Scanner.updateBarcode(it)
barcode.boundingBox?.let { rect ->
barcodeBoxView.setRect(adjustBoundingRect(rect))
}
}
return@addOnSuccessListener
}
}
// coming here means no satisfiable barcode was found
barcodeBoxView.setRect(RectF())
}
.addOnFailureListener {
image.close()
}
.addOnFailureListener { }
}
image.close()
}
}这个代码工作,我可以扫描条形码。但有时条形码检测很慢。文档说,提高性能的一种方法是限制图像分辨率。
不要在摄像机的本机分辨率上捕捉输入。在某些设备上,以本机分辨率捕获输入会产生非常大(10+百万像素)的图像,这会导致很低的延迟,而对准确性没有好处。相反,只要求相机的大小,这是条形码检测所需的,通常不超过200万像素。 如果扫描速度重要,则可以进一步降低图像捕获分辨率。但是,请记住上面概述的最低条形码大小要求。
不幸的是,文档没有指定如何降低图像分辨率。我的一些终端用户使用的是带有强大摄像头的高端设备,因此我们假设性能较差的原因是图像大小。
如何将图像的分辨率降低到固定值(类似于1024x768),而不是默认的相机分辨率?
发布于 2022-06-29 06:39:28
用户HarmenH的答案正确地告诉如何设置图像分辨率,所以我在这里不再重复。
事实证明,我的性能问题并不是因为图像分辨率。我似乎过早地关闭了imageProxy。
override fun analyze(image: ImageProxy) {
val img = image.image
if (img != null) {
// Update scale factors
scaleX = previewViewWidth / img.height.toFloat()
scaleY = previewViewHeight / img.width.toFloat()
val inputImage = InputImage.fromMediaImage(img,
image.imageInfo.rotationDegrees)
// Process image searching for barcodes
val options = BarcodeScannerOptions.Builder()
.build()
val scanner = BarcodeScanning.getClient(options)
scanner.process(inputImage)
.addOnSuccessListener { barcodes - >
for (barcode in barcodes) {
barcode?.rawValue?.let {
if (it.trim().isNotBlank()) {
Scanner.updateBarcode(it)
barcode.boundingBox?.let { rect - >
barcodeBoxView.setRect(adjustBoundingRect(rect))
}
}
return @addOnSuccessListener
}
}
// coming here means no satisfiable barcode was found
barcodeBoxView.setRect(RectF())
}
.addOnFailureListener {
image.close()
}
.addOnFailureListener {
//added this here.
image.close()
}
}
//Removed this because we don't close the
//imageProxy before analysis completes
//image.close()
}发布于 2022-06-27 07:20:48
可以在imageAnalyzer构建器bij上使用.setTargetResolution(大小)设置它。
val imageAnalysisUseCaseBuilder = ImageAnalysis.Builder()
imageAnalysisUseCaseBuilder.setTargetResolution(Size(1024, 768))
imageAnalysisUseCase = imageAnalysisUseCaseBuilder.build()或者在你的情况下
val imageAnalyzer = ImageAnalysis.Builder()
.setTargetResolution(Size(1024, 768))
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.build()
.also {
it.setAnalyzer(cameraExecutor,
QrCodeAnalyzer(context, binding.barcodeBoxView,
binding.previewView.width.toFloat(),
binding.previewView.height.toFloat()
)
)
}https://stackoverflow.com/questions/72767423
复制相似问题