Closing image in ImageAnalysis makes Mlkit stop working

1.3k Views Asked by At

Analyzer Class

private class Analyzer: ImageAnalysis.Analyzer {
val faceDetectObj=FaceDetectionActivity()
    @SuppressLint("UnsafeExperimentalUsageError")
    override fun analyze(image: ImageProxy) {
        val proxy=image
        val currentImage=proxy.image
        val rotDegree=  proxy.imageInfo.rotationDegrees
        if (currentImage!=null){
            val imageNew=InputImage.fromMediaImage(currentImage,rotDegree)
            faceDetectObj.detectFaces(imageNew)
         }  
        image.close()  //error because of this line
    }

FaceDetectionActivit.kt

class FaceDetectionActivity :AppCompatActivity() {
         fun detectFaces(image: InputImage) {
            // [START set_detector_options]
            val options = FaceDetectorOptions.Builder()
                .setClassificationMode(FaceDetectorOptions.PERFORMANCE_MODE_ACCURATE)
                .setLandmarkMode(FaceDetectorOptions.LANDMARK_MODE_ALL)
                .setClassificationMode(FaceDetectorOptions.CLASSIFICATION_MODE_ALL)
                .setMinFaceSize(0.15f)
                .enableTracking()
                .build()
            // [END set_detector_options]

            // [START get_detector]
            val detector = FaceDetection.getClient(options)
            // Or, to use the default option:
            // val detector = FaceDetection.getClient();
            // [END get_detector]

            // [START run_detector]
            val result = detector.process(image)
                .addOnSuccessListener { faces ->
                    // Task completed successfully
                    // [START_EXCLUDE]
                    // [START get_face_info]
                    for (face in faces) {
                        val bounds = face.boundingBox
                        val rotY = face.headEulerAngleY // Head is rotated to the right rotY degrees
                        val rotZ = face.headEulerAngleZ // Head is tilted sideways rotZ degrees
                      
                        // If landmark detection was enabled (mouth, ears, eyes, cheeks, and
                        // nose available):
                        val leftEar = face.getLandmark(FaceLandmark.LEFT_EAR)
                        leftEar?.let {
                            val leftEarPos = leftEar.position
                        }

                        // If classification was enabled:
                        if (face.smilingProbability != null) {
                            val smileProb = face.smilingProbability
                        }
                        if (face.rightEyeOpenProbability != null) {
                            val rightEyeOpenProb = face.rightEyeOpenProbability
                        }

                        // If face tracking was enabled:
                        if (face.trackingId != null) {
                            val id = face.trackingId
                        }
                    }
                    // [END get_face_info]
                    // [END_EXCLUDE]
                }
                .addOnFailureListener { e ->
                    e.printStackTrace()
                    // Task failed with an exception
                    // ...
                }
             result.addOnCompleteListener {
                 processFaceList(it.result as List<Face>)
             }.addOnFailureListener {
                 it.printStackTrace()
             }
            // [END run_detector]
        }

         fun processFaceList(faces: List<Face>) {
            // [START mlkit_face_list]
            for (face in faces) {
                val bounds = face.boundingBox
                val rotY = face.headEulerAngleY // Head is rotated to the right rotY degrees
                val rotZ = face.headEulerAngleZ // Head is tilted sideways rotZ degrees

                // If landmark detection was enabled (mouth, ears, eyes, cheeks, and
                // nose available):
                val leftEar = face.getLandmark(FaceLandmark.LEFT_EAR)
                leftEar?.let {
                    val leftEarPos = leftEar.position
                }
                // If contour detection was enabled:
                val leftEyeContour = face.getContour(FaceContour.LEFT_EYE)?.points
                val upperLipBottomContour = face.getContour(FaceContour.UPPER_LIP_BOTTOM)?.points
                Log.d("help ","Needed P2")
                // If classification was enabled:
                if (face.smilingProbability != null) {
                    val smileProb = face.smilingProbability
                }
                if (face.rightEyeOpenProbability != null) {
                    val rightEyeOpenProb = face.rightEyeOpenProbability
                }

                // If face tracking was enabled:
                if (face.trackingId != null) {
                    val id = face.trackingId
                }
            }
            // [END mlkit_face_list]
        }
}

im trying to detect face using above code(directly from documentation).ImageAnlayser needs to be closed after each frame , but if i do that mlkit throws

2020-10-13 23:38:42.121 30424-30424/? E/AndroidRuntime: FATAL EXCEPTION: main
   Process: com.airbender.camcorder, PID: 30424
   com.google.android.gms.tasks.RuntimeExecutionException: com.google.mlkit.common.MlKitException: Internal error has occurred when executing ML Kit tasks
       at com.google.android.gms.tasks.zzu.getResult(Unknown Source:15)
       at com.airbender.camcorder.FaceDetectionActivity$detectFaces$1.onComplete(FaceDetectionActivty.kt:67)
       at com.google.android.gms.tasks.zzj.run(Unknown Source:4)
       at android.os.Handler.handleCallback(Handler.java:883)
       at android.os.Handler.dispatchMessage(Handler.java:100)
       at android.os.Looper.loop(Looper.java:214)
       at android.app.ActivityThread.main(ActivityThread.java:7398)
       at java.lang.reflect.Method.invoke(Native Method)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:924)
    Caused by: com.google.mlkit.common.MlKitException: Internal error has occurred when executing ML Kit tasks
       at com.google.mlkit.common.sdkinternal.ModelResource.zza(com.google.mlkit:common@@17.0.0:32)
       at com.google.mlkit.common.sdkinternal.zzl.run(Unknown Source:10)
       at com.google.mlkit.common.sdkinternal.zzp.run(com.google.mlkit:common@@17.0.0:3)
       at com.google.mlkit.common.sdkinternal.MlKitThreadPool.zzd(com.google.mlkit:common@@17.0.0:24)
       at com.google.mlkit.common.sdkinternal.MlKitThreadPool.zza(com.google.mlkit:common@@17.0.0:30)
       at com.google.mlkit.common.sdkinternal.zzh.run(Unknown Source:2)
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
       at java.lang.Thread.run(Thread.java:919)
    Caused by: java.lang.IllegalStateException: Image is already closed
       at android.media.Image.throwISEIfImageIsInvalid(Image.java:72)
       at android.media.ImageReader$SurfaceImage$SurfacePlane.getBuffer(ImageReader.java:965)
       at com.google.android.gms.vision.Frame$Builder.setPlanes(com.google.android.gms:play-services-vision-common@@19.1.2:14)
       at com.google.mlkit.vision.face.internal.zzb.zza(com.google.android.gms:play-services-mlkit-face-detection@@16.1.1:61)
       at com.google.mlkit.vision.face.internal.zzb.zza(com.google.android.gms:play-services-mlkit-face-detection@@16.1.1:90)
       at com.google.mlkit.vision.face.internal.zzb.run(com.google.android.gms:play-services-mlkit-face-detection@@16.1.1:169)
       at com.google.mlkit.vision.common.internal.MobileVisionBase.zza(com.google.mlkit:vision-common@@16.1.0:23)
       at com.google.mlkit.vision.common.internal.zzc.call(Unknown Source:4)
       at com.google.mlkit.common.sdkinternal.ModelResource.zza(com.google.mlkit:common@@17.0.0:29)
       at com.google.mlkit.common.sdkinternal.zzl.run(Unknown Source:10) 
       at com.google.mlkit.common.sdkinternal.zzp.run(com.google.mlkit:common@@17.0.0:3) 
       at com.google.mlkit.common.sdkinternal.MlKitThreadPool.zzd(com.google.mlkit:common@@17.0.0:24) 
       at com.google.mlkit.common.sdkinternal.MlKitThreadPool.zza(com.google.mlkit:common@@17.0.0:30) 
       at com.google.mlkit.common.sdkinternal.zzh.run(Unknown Source:2) 
       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
       at java.lang.Thread.run(Thread.java:919) 

how to close each frame so that i can process every current frame without error as the way it need to work . is there anything need to do?. Thanks.

1

There are 1 best solutions below

1
On

You should close the image in detector's onComplete listener instead since the image is used in the background thread by the ML Kit detector after the process call.