动作检测结算界面更新

This commit is contained in:
terric 2023-11-07 23:28:19 +08:00
parent edfb397ac4
commit f6c45303ad
14 changed files with 251 additions and 26 deletions

View File

@ -201,7 +201,7 @@ AnimationClip:
m_Level: 0 m_Level: 0
m_CycleOffset: 0 m_CycleOffset: 0
m_HasAdditiveReferencePose: 0 m_HasAdditiveReferencePose: 0
m_LoopTime: 1 m_LoopTime: 0
m_LoopBlend: 0 m_LoopBlend: 0
m_LoopBlendOrientation: 0 m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0 m_LoopBlendPositionY: 0

View File

@ -24295,7 +24295,7 @@ AnimationClip:
floatParameter: 0 floatParameter: 0
intParameter: 0 intParameter: 0
messageOptions: 0 messageOptions: 0
- time: 6.3333335 - time: 6.1666665
functionName: CheckHeadTurnLeft functionName: CheckHeadTurnLeft
data: data:
objectReferenceParameter: {fileID: 0} objectReferenceParameter: {fileID: 0}
@ -24309,10 +24309,17 @@ AnimationClip:
floatParameter: 0 floatParameter: 0
intParameter: 0 intParameter: 0
messageOptions: 0 messageOptions: 0
- time: 6.6666665 - time: 6.8333335
functionName: CheckHeadTurnLeft functionName: CheckHeadTurnLeft
data: data:
objectReferenceParameter: {fileID: 0} objectReferenceParameter: {fileID: 0}
floatParameter: 0 floatParameter: 0
intParameter: 0 intParameter: 0
messageOptions: 0 messageOptions: 0
- time: 7
functionName: FinishCurrentActionCheck
data:
objectReferenceParameter: {fileID: 0}
floatParameter: 0
intParameter: 0
messageOptions: 0

View File

@ -0,0 +1,122 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &2741035673910363012
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5126881112078021239}
- component: {fileID: 3856882301601416915}
- component: {fileID: 3610759867344957577}
- component: {fileID: 8711614252624484816}
m_Layer: 5
m_Name: ClearingSettlementUI
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &5126881112078021239
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2741035673910363012}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 6891999240067574262}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 100, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!95 &3856882301601416915
Animator:
serializedVersion: 7
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2741035673910363012}
m_Enabled: 1
m_Avatar: {fileID: 0}
m_Controller: {fileID: 9100000, guid: 12ae8ac8969c0da4aba2b898164f1b12, type: 2}
m_CullingMode: 0
m_UpdateMode: 0
m_ApplyRootMotion: 0
m_LinearVelocityBlending: 0
m_StabilizeFeet: 0
m_AnimatePhysics: 0
m_WarningMessage:
m_HasTransformHierarchy: 1
m_AllowConstantClipSamplingOptimization: 1
m_KeepAnimatorStateOnDisable: 0
m_WriteDefaultValuesOnDisable: 0
--- !u!225 &3610759867344957577
CanvasGroup:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2741035673910363012}
m_Enabled: 1
m_Alpha: 1
m_Interactable: 1
m_BlocksRaycasts: 1
m_IgnoreParentGroups: 0
--- !u!114 &8711614252624484816
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 2741035673910363012}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8806e03c0fc88604aacf35936e8fe874, type: 3}
m_Name:
m_EditorClassIdentifier:
--- !u!1 &6838756836509648688
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6891999240067574262}
m_Layer: 5
m_Name: Contant
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6891999240067574262
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6838756836509648688}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 5126881112078021239}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 100, y: 100}
m_Pivot: {x: 0.5, y: 0.5}

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 1c317f5b047ffd047a9577a36fbd3cc2
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -7,12 +7,12 @@ public class RobotController : MonoBehaviour
{ {
public void CheckHeadTurnLeft() public void CheckHeadTurnLeft()
{ {
MotionCaptureManager.Instance.ScoreUpdate(); EventManager.Instance.Dispatch("EstimateAction", AvatarAction.HeadTurnLeft);
} }
public void FinishCurrentActionCheck() public void FinishCurrentActionCheck()
{ {
MotionCaptureManager.Instance.ScoreUpdate(); EventManager.Instance.Dispatch("ScoreUpdate");
} }
public void CheckHeadTurnRight() public void CheckHeadTurnRight()

View File

@ -32,7 +32,7 @@ public class EventManager : MonoSingleton<EventManager>
_actionDic[eventName] -= handler; _actionDic[eventName] -= handler;
} }
public void DispatchEvent(string eventName) public void Dispatch(string eventName)
{ {
if (!_actionDic.ContainsKey(eventName)) if (!_actionDic.ContainsKey(eventName))
return; return;

View File

@ -0,0 +1,15 @@

public class ClearingSettlementUI : UIPopupBase
{
public override void Init(object[] pageData)
{
base.Init(pageData);
//todo 成果展示
}
public void OnClickOK()
{
UIManager.Instance.CloseCurrent();
LoadingManager.Instance.Load("Boot");
}
}

View File

@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8806e03c0fc88604aacf35936e8fe874
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -18,7 +18,7 @@ public class GudieAnimationManager : MonoBehaviour
public void FrameEstimate() public void FrameEstimate()
{ {
EventManager.Instance.DispatchEvent("PoseEstimate"); EventManager.Instance.Dispatch("PoseEstimate");
} }
} }

View File

@ -61,8 +61,21 @@ namespace Yoga
private void OnEnable() private void OnEnable()
{ {
EventManager.Instance.AddEventListener("StartMotionCapture", OnStartMotionCapture); EventManager.Instance.AddEventListener("StartMotionCapture", OnStartMotionCapture);
EventManager.Instance.AddEventListener("EstimateAction", EstimateAction);
EventManager.Instance.AddEventListener("ScoreUpdate", ScoreUpdate);
} }
private void OnDisable()
{
EventManager.Instance.RemoveEventListener("StartMotionCapture", OnStartMotionCapture);
EventManager.Instance.RemoveEventListener("EstimateAction", EstimateAction);
EventManager.Instance.RemoveEventListener("ScoreUpdate", ScoreUpdate);
}
private void EstimateAction()
{
//检测动作
}
private void OnStartMotionCapture() private void OnStartMotionCapture()
{ {
@ -78,7 +91,7 @@ namespace Yoga
_webCamTextureToMatHelper = gameObject.GetComponent<WebCamTextureToMatHelper>(); _webCamTextureToMatHelper = gameObject.GetComponent<WebCamTextureToMatHelper>();
_webCamTextureToMatHelper.Initialize(); _webCamTextureToMatHelper.Initialize();
YogaManager.Instance.Init(); YogaManager.Instance.InitData();
//动作引导界面 //动作引导界面
var video = Resources.Load<VideoClip>("Video/Action1"); var video = Resources.Load<VideoClip>("Video/Action1");
@ -144,8 +157,8 @@ namespace Yoga
_objEstimation = StartCoroutine(ObjectEstimation(img)); _objEstimation = StartCoroutine(ObjectEstimation(img));
_involkCDTime = 0; _involkCDTime = 0;
} }
//#if DEBUG_MODE && UNITY_EDITOR //#if DEBUG_MODE && UNITY_EDITOR
if (_net == null) if (_net == null)
{ {
Imgproc.putText(img, "model file is not loaded.", new Point(5, img.rows() - 30), Imgproc.FONT_HERSHEY_SIMPLEX, 0.7, new Scalar(255, 255, 255), 2, Imgproc.LINE_AA, false); Imgproc.putText(img, "model file is not loaded.", new Point(5, img.rows() - 30), Imgproc.FONT_HERSHEY_SIMPLEX, 0.7, new Scalar(255, 255, 255), 2, Imgproc.LINE_AA, false);
@ -174,7 +187,7 @@ namespace Yoga
Imgproc.ellipse(img, points[idTo], new Size(3, 3), 0, 0, 360, new Scalar(0, 0, 255), Core.FILLED); Imgproc.ellipse(img, points[idTo], new Size(3, 3), 0, 0, 360, new Scalar(0, 0, 255), Core.FILLED);
} }
} }
//#endif //#endif
Utils.matToTexture2D(img, texture); Utils.matToTexture2D(img, texture);
} }
} }
@ -183,7 +196,7 @@ namespace Yoga
{ {
if (!_webCamTextureToMatHelper.IsPlaying() || !_webCamTextureToMatHelper.DidUpdateThisFrame()) if (!_webCamTextureToMatHelper.IsPlaying() || !_webCamTextureToMatHelper.DidUpdateThisFrame())
yield break; yield break;
if (_objectDetector == null) if (_objectDetector == null)
yield break; yield break;
@ -224,10 +237,10 @@ namespace Yoga
if (_voloResult == null) if (_voloResult == null)
yield break; yield break;
var box = _voloResult[0]; var box = _voloResult[0];
//对人体进行姿态检测 //对人体进行姿态检测
OpenCVForUnity.CoreModule.Rect rect = new OpenCVForUnity.CoreModule.Rect((int)box[0], (int)box[1], (int)(box[2] - box[0]), (int)(box[3] - box[1])); OpenCVForUnity.CoreModule.Rect rect = new OpenCVForUnity.CoreModule.Rect((int)box[0], (int)box[1], (int)(box[2] - box[0]), (int)(box[3] - box[1]));
Mat personRectImg = new Mat(_bgrMat, rect);//获取人体区域 Mat personRectImg = new Mat(_bgrMat, rect);//获取人体区域
_personPoints = _openPoseModel.estimate(personRectImg, (float)threshold).toList(); _personPoints = _openPoseModel.estimate(personRectImg, (float)threshold).toList();
@ -248,7 +261,7 @@ namespace Yoga
} }
private bool CheckResults(float[] box, float[] confidence, float[] classID , Mat rgbaMat) private bool CheckResults(float[] box, float[] confidence, float[] classID, Mat rgbaMat)
{ {
if ((int)classID[0] != 0 || confidence[0] < 0.8f) //只检测人体且置信度大于80% if ((int)classID[0] != 0 || confidence[0] < 0.8f) //只检测人体且置信度大于80%
return false; return false;
@ -295,8 +308,6 @@ namespace Yoga
Imgproc.putText(image, label, new Point(left, top), Imgproc.FONT_HERSHEY_SIMPLEX, 0.5, Scalar.all(255), 1, Imgproc.LINE_AA); Imgproc.putText(image, label, new Point(left, top), Imgproc.FONT_HERSHEY_SIMPLEX, 0.5, Scalar.all(255), 1, Imgproc.LINE_AA);
} }
/// <summary> /// <summary>
/// Raises the destroy event. /// Raises the destroy event.
/// </summary> /// </summary>
@ -369,18 +380,30 @@ namespace Yoga
} }
private bool _isCorrectAction = false; private bool _isCorrectAction = false;
private int _maxActionCount = 3;
public void ScoreUpdate() public void ScoreUpdate()
{ {
//如果达到最大数,则停止检测,跳转到下一个动作/下一个动作引导/奖励界面
if (YogaManager.Instance.CurrentActionCount >= _maxActionCount)
{
//停止检测
_isOnCamCapture = false;
//跳转到下一个动作/下一个动作引导/奖励界面
UIManager.Instance.ShowPanel<ClearingSettlementUI>(false, null);
return;
}
if (_isCorrectAction) if (_isCorrectAction)
{ {
//成功 EventManager.Instance.Dispatch("ActionSuccess");
YogaManager.Instance.CurrentSuccessActionCount++;
} }
else else
{ {
//失败 EventManager.Instance.Dispatch("ActionFailed");
} }
YogaManager.Instance.CurrentActionCount++;
} }
} }
} }

View File

@ -6,8 +6,8 @@ using UnityEngine;
public class GuideUI : UIPanelBase public class GuideUI : UIPanelBase
{ {
[HideInInspector]
private GameObject _guide; private GameObject _guide;
private Animator _effectAnimator;
public GudieAnimationManager GuideMgr => _guide.GetComponent<GudieAnimationManager>(); public GudieAnimationManager GuideMgr => _guide.GetComponent<GudieAnimationManager>();
private void Awake() private void Awake()
@ -17,11 +17,15 @@ public class GuideUI : UIPanelBase
{ {
Debug.LogError("Guide is null"); Debug.LogError("Guide is null");
} }
_effectAnimator = transform.Find("Content").GetComponentInChildren<Animator>();
} }
private void OnEnable() private void OnEnable()
{ {
EventManager.Instance.AddEventListener("PlayAnimation", PlayAnimation); EventManager.Instance.AddEventListener("PlayAnimation", PlayAnimation);
EventManager.Instance.AddEventListener("ActionSuccess", ShowSuccessEffect);
EventManager.Instance.AddEventListener("ActionFailed", ShowFailEffect);
} }
@ -29,6 +33,8 @@ public class GuideUI : UIPanelBase
private void OnDisable() private void OnDisable()
{ {
EventManager.Instance.RemoveEventListener("PlayAnimation", PlayAnimation); EventManager.Instance.RemoveEventListener("PlayAnimation", PlayAnimation);
EventManager.Instance.RemoveEventListener("ActionSuccess", ShowSuccessEffect);
EventManager.Instance.RemoveEventListener("ActionFailed", ShowFailEffect);
} }
#region Event Func #region Event Func
@ -55,6 +61,15 @@ public class GuideUI : UIPanelBase
} }
} }
private void ShowFailEffect()
{
_effectAnimator.Play("WindowEffectError", 0, 0f);
}
private void ShowSuccessEffect()
{
_effectAnimator.Play("WindowEffectCorrect", 0, 0f);
}
#endregion #endregion

View File

@ -12,6 +12,7 @@ public static class UILoadConfig
{ "ActionListUIPanel" , "UI/ActionListUI" }, { "ActionListUIPanel" , "UI/ActionListUI" },
{ "ActionGuideVideoPanel" , "UI/ActionGuideVideoPanel" }, { "ActionGuideVideoPanel" , "UI/ActionGuideVideoPanel" },
{ "GuideUI" , "UI/GuideUI" }, { "GuideUI" , "UI/GuideUI" },
{ "ClearingSettlementUI" , "UI/ClearingSettlementUI" },
}; };
public static string GetPath(string typeName) public static string GetPath(string typeName)

View File

@ -5,6 +5,7 @@ using UnityEngine;
using System.Linq; using System.Linq;
using OpenCVForUnity.CoreModule; using OpenCVForUnity.CoreModule;
using UnityEngine.SceneManagement; using UnityEngine.SceneManagement;
using Yoga;
public class UIManager : MonoSingleton<UIManager> public class UIManager : MonoSingleton<UIManager>
{ {
@ -207,4 +208,23 @@ public class UIManager : MonoSingleton<UIManager>
{ {
} }
public void CloseUI(UIBase targetUI)
{
if (_panelStack.Count <= 0)
{
return;
}
targetUI.OnHide();
targetUI.OnExit();
//从栈中移除
_panelStack = new Stack<UIBase>(_panelStack.Where(ui => ui != targetUI));
//打开顶层页面
if (_panelStack.Count > 0)
{
UIBase nextPanel = _panelStack.Peek();
nextPanel.OnResume();
}
}
} }

View File

@ -27,12 +27,16 @@ public class YogaManager : MonoSingleton<YogaManager>
public Action<string> ShowHint { get; internal set; } public Action<string> ShowHint { get; internal set; }
public int ActionIndex { get; internal set; } public int ActionIndex { get; internal set; }
public int CurrentActionCount { get => _currentActionCount; internal set => _currentActionCount = value; }
public int CurrentSuccessActionCount { get => _currentSuccessActionCount; internal set => _currentSuccessActionCount = value; }
//创建帧数据缓存 //创建帧数据缓存
private Dictionary<int, List<List<Point>>> _framePoints = new (); // actionID, frameID, points private Dictionary<int, List<List<Point>>> _framePoints = new (); // actionID, frameID, points
private int _currActionID; private int _currActionID;
private int _currentActionCount;
private int _currentSuccessActionCount;
public void Init() public void InitData()
{ {
_poseChecks.AddFirst(new IsReady(ModelType.OpenPose)); _poseChecks.AddFirst(new IsReady(ModelType.OpenPose));
_poseChecks.AddLast(new HeadTurnLeft(ModelType.OpenPose)); _poseChecks.AddLast(new HeadTurnLeft(ModelType.OpenPose));
@ -44,8 +48,8 @@ public class YogaManager : MonoSingleton<YogaManager>
_currPose.ShowHint(); _currPose.ShowHint();
_currActionID = 0; _currActionID = 0;
_isInited = true; _isInited = true;
_currentActionCount = 0;
_currentSuccessActionCount = 0;
} }
public void Dispose() public void Dispose()
@ -70,7 +74,7 @@ public class YogaManager : MonoSingleton<YogaManager>
{ {
if (!_isInited) if (!_isInited)
{ {
Init(); InitData();
} }
Points = points; Points = points;