MLKit目标检测无法识别物体且无法绘制边界框求助
问题排查与修复
1. 未正确关闭ImageProxy(核心问题)
在ObjectDetectorProcessor的analyze方法中,仅在mediaImage为null时调用了imageProxy.close(),但MLKit检测成功或失败的回调中未关闭ImageProxy。这会阻塞CameraX的图像分析管道,导致后续帧无法被处理,表现为“无法识别物体”。
修复代码:
@SuppressLint("UnsafeOptInUsageError") override fun analyze(imageProxy: ImageProxy) { val mediaImage = imageProxy.image ?: kotlin.run { Log.e(TAG, "Error: imageProxy null") imageProxy.close() return } val image = InputImage.fromMediaImage(mediaImage, imageProxy.imageInfo.rotationDegrees) detector.process(image) .addOnSuccessListener { objectList -> listener(objectList, image.mediaImage?.cropRect!!) imageProxy.close() // 必须关闭图像代理 } .addOnFailureListener { Log.e(TAG, "Error: ${it.message}", it) imageProxy.close() // 必须关闭图像代理 } }
2. 边界框坐标映射错误
GraphicOverlay.Graphics.calculateRect方法中,边界框的左右坐标被错误反转,导致绘制的框位置完全偏移(可能超出屏幕),看起来像是没有识别结果:
// 错误代码 val mappedBox = RectF().apply { left = boundingBoxT.right * scale + offsetX top = boundingBoxT.top * scale + offsetY right = boundingBoxT.left * scale + offsetX bottom = boundingBoxT.bottom * scale + offsetY } // 修复后 val mappedBox = RectF().apply { left = boundingBoxT.left * scale + offsetX top = boundingBoxT.top * scale + offsetY right = boundingBoxT.right * scale + offsetX bottom = boundingBoxT.bottom * scale + offsetY }
3. 多物体检测模式未启用(按需修复)
从ScanFragment代码看,你传入了multiObjectMode参数但未在处理器中使用。如果需要检测多个物体,需在MLKit配置中启用该模式:
// 修改ObjectDetectorProcessor构造函数与配置 class ObjectDetectorProcessor( private val multiObjectMode: Boolean, private val listener: (MutableList<DetectedObject>, Rect) -> Unit ) : ImageAnalysis.Analyzer { private val options = ObjectDetectorOptions.Builder() .apply { setDetectorMode(ObjectDetectorOptions.STREAM_MODE) setMultipleObjectsEnabled(multiObjectMode) // 启用多物体检测 }.build() // ... 其余代码 }
4. UI操作未切换到主线程
createOverlay中操作GraphicOverlay属于UI操作,而MLKit回调运行在后台线程,直接操作会导致异常或不生效,需切换到主线程执行:
private fun createOverlay(objectList: MutableList<DetectedObject>, rect: Rect) { requireActivity().runOnUiThread { binding.cameraPreviewGraphicOverlay.clear() objectList.forEach { detectedObject -> val overlayView = ObjectDetectorGraphic(binding.cameraPreviewGraphicOverlay, detectedObject, rect) binding.cameraPreviewGraphicOverlay.add(overlayView) } } }
内容的提问来源于stack exchange,提问作者archisei
相关产品推荐
相关产品推荐

