Health/Assets/_VoiceAssistant/Scripts/FaceExpression/ExpressionRecognition.cs

132 lines
3.8 KiB
C#

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<FaceInfo.Expression, ExpressionDuration> expressionDuration = new Dictionary<FaceInfo.Expression, ExpressionDuration>();
/// <summary>
/// 当检测到一个表情持续一定时间后,触发事件
/// </summary>
public float triggerEventDuration = 2;
/// <summary>
/// 当一个表情长时间未检测到,就重置它的状态
/// </summary>
public float resetExpDurationInterval = 5;
/// <summary>
/// 触发表情事件后的冷却时间
/// </summary>
public float triggerEventCD = 20;
public event UnityAction<FaceInfo.Expression> onRecognizingExpression;
IFaceRecognizer recognizer;
float triggerCDTimer = 0;
class ExpressionDuration
{
/// <summary>
/// 检测到的时长
/// </summary>
public float duration
{
get
{
return _duration;
}
set
{
_duration = value;
unrecognizedInterval = 0;
}
}
float _duration;
/// <summary>
/// 未检测到的时间间隔
/// </summary>
public float unrecognizedInterval;
}
private void Awake()
{
recognizer = GetComponentInChildren<IFaceRecognizer>(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;
}
}
}