homuler / MediaPipeUnityPlugin

Unity plugin to run MediaPipe
MIT License
1.76k stars 460 forks source link

FaceLandmarkListWithIrisAnnotation: Collection was modified; enumeration operation may not execute. #1223

Closed yuwei-chen-lm closed 1 month ago

yuwei-chen-lm commented 1 month ago

Plugin Version or Commit ID

v0.14.4

Unity Version

2022.3.16

Your Host OS

win11, note book camera

Target Platform

UnityEditor

Target Device

No response

[Windows Only] Visual Studio C++ and Windows SDK Version

No response

[Linux Only] GCC/G++ and GLIBC Version

No response

[Android Only] Android Build Tools and NDK Version

No response

[iOS Only] XCode Version

No response

Build Command

-

Bug Description

// bug: Collection was modified; enumeration operation may not execute. // https://stackoverflow.com/questions/604831/collection-was-modified-enumeration-operation-may-not-execute

// change (add ToList() to copy a new list)

in class FaceLandmarkListWithIrisAnnotation.cs:

var enumerator = landmarks.ToList().GetEnumerator(); var faceLandmarks = new List(_FaceLandmarkCount); for (var i = 0; i < _FaceLandmarkCount; i++) { if (enumerator.MoveNext()) { faceLandmarks.Add(enumerator.Current); } }

Steps to Reproduce the Bug

run scene tasks/Face Landmark Detection, sometimes the error occurs

Log

-

Screenshot/Video

No response

Additional Context

No response

homuler commented 1 month ago

Could you attach the complete error log?

yuwei-chen-lm commented 1 month ago
InvalidOperationException: Collection was modified; enumeration operation may not execute.
System.Collections.Generic.List`1+Enumerator[T].MoveNextRare () (at <17d9ce77f27a4bd2afb5ba32c9bea976>:0)
System.Collections.Generic.List`1+Enumerator[T].MoveNext () (at <17d9ce77f27a4bd2afb5ba32c9bea976>:0)
Mediapipe.Unity.FaceLandmarkListWithIrisAnnotation.PartitionLandmarkList[T] (System.Collections.Generic.IReadOnlyList`1[T] landmarks) (at ./Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/Annotation/FaceLandmarkListWithIrisAnnotation.cs:170)
Mediapipe.Unity.FaceLandmarkListWithIrisAnnotation.Draw (System.Collections.Generic.IReadOnlyList`1[T] target, System.Boolean visualizeZ, System.Int32 circleVertices) (at ./Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/Annotation/FaceLandmarkListWithIrisAnnotation.cs:109)
Mediapipe.Unity.FaceLandmarkListWithIrisAnnotation.Draw (Mediapipe.Tasks.Components.Containers.NormalizedLandmarks target, System.Boolean visualizeZ, System.Int32 circleVertices) (at ./Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/Annotation/FaceLandmarkListWithIrisAnnotation.cs:117)
Mediapipe.Unity.MultiFaceLandmarkListAnnotation+<>c__DisplayClass18_0.<Draw>b__0 (Mediapipe.Unity.FaceLandmarkListWithIrisAnnotation annotation, Mediapipe.Tasks.Components.Containers.NormalizedLandmarks target) (at ./Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/Annotation/MultiFaceLandmarkListAnnotation.cs:111)
Mediapipe.Unity.ListAnnotation`1[T].CallActionForAll[TArg] (System.Collections.Generic.IReadOnlyList`1[T] argumentList, System.Action`2[T1,T2] action) (at ./Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/Annotation/ListAnnotation.cs:118)
Mediapipe.Unity.MultiFaceLandmarkListAnnotation.Draw (System.Collections.Generic.IReadOnlyList`1[T] targets, System.Boolean visualizeZ) (at ./Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/Annotation/MultiFaceLandmarkListAnnotation.cs:109)
Mediapipe.Unity.FaceLandmarkerResultAnnotationController.SyncNow () (at ./Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/Annotation/FaceLandmarkerResultAnnotationController.cs:38)
Mediapipe.Unity.AnnotationController`1[T].LateUpdate () (at ./Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/Annotation/AnnotationController.cs:74)
homuler commented 1 month ago

Did you modify some code?

homuler commented 1 month ago

This might be because the lock is not acquired here. https://github.com/homuler/MediaPipeUnityPlugin/blob/e007dd75335ba8a9daba32ba71c4c641f257ec70/Packages/com.github.homuler.mediapipe/Runtime/Scripts/Unity/Annotation/FaceLandmarkerResultAnnotationController.cs#L31

yuwei-chen-lm commented 1 month ago

UniRx is used,

in a custom script:

private void Start()
{
    _faceLandmarkerRunner.OnFaceLandmarkResult.ObserveOnMainThread().Subscribe(result =>
    {
        GetBlendShapes(result);

    }).AddTo(this);
}

in GetBlendShapes:

if (result.faceBlendshapes == null
    || result.faceBlendshapes[0].categories == null)
{
    return;
}

{

    for (int i = 0; i < 52; i++)
    {
        _initialFaceBS[i].Id = i;

        **(error here)**
        _initialFaceBS[i].Name = result.faceBlendshapes[0].categories[i].categoryName
            .Replace("_", "")
            .FirstToUpper();
        _initialFaceBS[i].Value = result.faceBlendshapes[0].categories[i].score;
    }
yuwei-chen-lm commented 1 month ago

add a try catch to handle this