Android后台协程处理TensorImage报错问题求助
后台协程中TensorFlow Lite目标检测报错排查与解决
问题详情
我在后台协程处理相机图像进行目标检测时触发报错,报错信息如下:
java.lang.IllegalStateException: Error occurred when detecting the image: Invoke() failed. at org.tensorflow.lite.task.vision.detector.ObjectDetector.detectNative(Native Method) at org.tensorflow.lite.task.vision.detector.ObjectDetector.detect(ObjectDetector.java:528) at org.tensorflow.lite.task.vision.detector.ObjectDetector.access$1200(ObjectDetector.java:88) at org.tensorflow.lite.task.vision.detector.ObjectDetector$4.run(ObjectDetector.java:481) at org.tensorflow.lite.task.vision.detector.ObjectDetector$4.run(ObjectDetector.java:477) at org.tensorflow.lite.task.vision.core.BaseVisionTaskApi.run(BaseVisionTaskApi.java:49) at org.tensorflow.lite.task.vision.detector.ObjectDetector.detect(ObjectDetector.java:476) at org.tensorflow.lite.task.vision.detector.ObjectDetector.detect(ObjectDetector.java:446) at com.nst.n692_android.ObjectDetectorHelper$detectAsync$2.invokeSuspend(ObjectDetectorHelper.kt:167) at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:106) at kotlinx.coroutines.internal.LimitedDispatcher.run(LimitedDispatcher.kt:42) at kotlinx.coroutines.scheduling.TaskImpl.run(Tasks.kt:95) at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:570) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:750) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:677) at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:664) Suppressed: kotlinx.coroutines.DiagnosticCoroutineContextException: [StandaloneCoroutine{Cancelling}@7613710, Dispatchers.Main.immediate]
我的代码实现:
return withContext(Dispatchers.IO){ // Preprocess the image and convert it into a TensorImage for detection. val inputImage = TensorImage.fromBitmap(rotatedImage) val outputs = objectDetector?.detect(inputImage) if (outputs.isNullOrEmpty()) return@withContext null val detectionResult = outputs[0] val category = detectionResult?.boundingBox ?: return@withContext null val cordLeft = PointF(category.left, category.top) val cordRight = PointF(category.right, category.top) inferenceTime = SystemClock.uptimeMillis() - inferenceTime val rotatedCoordinatesLeft = cordLeft.rotateCoordinates(rotatedImage.width, rotatedImage.height, imageRotation) val rotatedCoordinatesRight = cordRight.rotateCoordinates(rotatedImage.width, rotatedImage.height, imageRotation) return@withContext DetectedObjectResult( detectionResult.categories[0].score.toString(), rotatedCoordinatesLeft, rotatedCoordinatesRight ) }
排查与解决方案
1. ObjectDetector实例线程冲突
TensorFlow Lite的ObjectDetector并非线程安全,若多个协程/线程共享同一个实例调用detect,会触发Native层并发访问错误。
解决办法:
为每个IO协程创建独立的ObjectDetector实例,或用ThreadLocal确保每个线程持有专属实例:
return withContext(Dispatchers.IO) { val detector = ObjectDetector.createFromFileAndOptions(context, modelPath, options) val safeBitmap = rotatedImage.copy(rotatedImage.config, true) val inputImage = TensorImage.fromBitmap(safeBitmap) val outputs = detector.detect(inputImage) // 后续结果处理逻辑 detector.close() // 使用完毕释放资源 // 返回结果 }
2. Bitmap资源被提前回收
相机帧Bitmap可能在协程处理过程中被主线程回收,导致TensorImage读取无效数据触发异常。
解决办法:
转换为TensorImage前复制Bitmap,确保协程处理期间资源有效:
val safeBitmap = rotatedImage.copy(rotatedImage.config, true) val inputImage = TensorImage.fromBitmap(safeBitmap)
3. 协程取消中断检测
报错中的StandaloneCoroutine{Cancelling}表明协程执行detect时被取消,Native层调用被中断抛出异常。
解决办法:
添加异常捕获,处理协程取消场景:
return withContext(Dispatchers.IO) { try { val safeBitmap = rotatedImage.copy(rotatedImage.config, true) val inputImage = TensorImage.fromBitmap(safeBitmap) val outputs = objectDetector?.detect(inputImage) // 后续结果处理逻辑 } catch (e: CancellationException) { // 协程被取消,返回null或执行对应逻辑 null } catch (e: IllegalStateException) { // 捕获检测异常,打印日志或处理 e.printStackTrace() null } }
4. TensorImage格式不兼容
Bitmap格式与模型要求的输入格式不匹配,导致Native层处理失败。
解决办法:
检查模型输入格式(如ARGB_8888、RGB_565),转换Bitmap到对应格式:
val targetConfig = Bitmap.Config.ARGB_8888 // 按模型要求调整 val compatibleBitmap = if (rotatedImage.config != targetConfig) { rotatedImage.copy(targetConfig, true) } else { rotatedImage } val inputImage = TensorImage.fromBitmap(compatibleBitmap)
内容的提问来源于stack exchange,提问作者Test Label
相关产品推荐
相关产品推荐

