using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Events; public class ExpressionRecognition : MonoBehaviour { public FaceInfo.Expression currentExpression { get { return _currentExpression; } private set { if(_currentExpression != value) { _currentExpression = value; if(!expressionDuration.ContainsKey(value)) { expressionDuration.Add(value, new ExpressionDuration()); } } } } FaceInfo.Expression _currentExpression; Dictionary expressionDuration = new Dictionary(); /// /// 当检测到一个表情持续一定时间后,触发事件 /// public float triggerEventDuration = 2; /// /// 当一个表情长时间未检测到,就重置它的状态 /// public float resetExpDurationInterval = 5; /// /// 触发表情事件后的冷却时间 /// public float triggerEventCD = 20; public event UnityAction onRecognizingExpression; IFaceRecognizer recognizer; float triggerCDTimer = 0; class ExpressionDuration { /// /// 检测到的时长 /// public float duration { get { return _duration; } set { _duration = value; unrecognizedInterval = 0; } } float _duration; /// /// 未检测到的时间间隔 /// public float unrecognizedInterval; } private void Awake() { recognizer = GetComponentInChildren(false); recognizer.BindListener(OnRecognizedFaces); triggerCDTimer = triggerEventCD; } // Start is called before the first frame update void Start() { } // Update is called once per frame void Update() { triggerCDTimer += Time.deltaTime; foreach (var item in expressionDuration) { if(item.Key == currentExpression) { item.Value.duration += Time.deltaTime; //当前表情持续时间大于一定值后,触发表情识别事件 if (item.Key != FaceInfo.Expression.Neutral && item.Value.duration > triggerEventDuration && triggerCDTimer > triggerEventCD) { Debug.Log("触发表情:" + currentExpression); triggerCDTimer = 0; if (onRecognizingExpression != null) onRecognizingExpression(item.Key); } } else { item.Value.unrecognizedInterval += Time.deltaTime; if (item.Value.unrecognizedInterval > resetExpDurationInterval) { item.Value.duration = 0; } } } } void OnRecognizedFaces(FaceInfo[] infos) { if(infos!= null && infos.Length > 0) { FaceInfo largestFace = infos[0]; for (int i = 1; i < infos.Length; i++) { var info = infos[i]; //取面积最大的一个 if (info.box.height * info.box.width > largestFace.box.height * largestFace.box.width) { largestFace = info; } } currentExpression = largestFace.expression; return; } else { currentExpression = FaceInfo.Expression.Neutral; return; } } }