You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 23:47:33