132 lines
3.8 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|