280 lines
9.9 KiB
C#
280 lines
9.9 KiB
C#
using OpenCVForUnity.CoreModule;
|
|
using OpenCVForUnity.DnnModule;
|
|
using OpenCVForUnity.ImgprocModule;
|
|
using OpenCVForUnity.UnityUtils;
|
|
using OpenCVForUnity.UnityUtils.Helper;
|
|
using OpenCVForUnityExample;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using UnityEngine;
|
|
using UnityEngine.Video;
|
|
|
|
namespace Yoga
|
|
{
|
|
[RequireComponent(typeof(WebCamTextureToMatHelper))]
|
|
public class MotionCaptureManager : MonoSingleton<MotionCaptureManager>
|
|
{
|
|
private WebCamTextureToMatHelper _webCamTextureToMatHelper;
|
|
private Texture2D texture;
|
|
|
|
public float SamplingRate = 0.3f;
|
|
|
|
private List<float[]> _voloResult = new List<float[]>();
|
|
private List<Point> _currPersonPoints = new List<Point>();
|
|
|
|
private Mat _bgrMat;
|
|
|
|
private bool _isOnCamCapture = false;
|
|
public bool IsOnCamCapture { get => _isOnCamCapture; internal set => _isOnCamCapture = value; }
|
|
public WebCamTextureToMatHelper WebCamTextureToMatHelper => _webCamTextureToMatHelper;
|
|
|
|
public List<Point> CurrPersonPoints { get => _currPersonPoints; set => _currPersonPoints = value; }
|
|
public List<float[]> VoloResult { get => _voloResult; set => _voloResult = value; }
|
|
private bool _isCorrectAction = false;
|
|
private Mat _rgbaMat;
|
|
public Mat RgbaMat { get => _rgbaMat; set => _rgbaMat = value; }
|
|
|
|
private void OnEnable()
|
|
{
|
|
EventManager.Instance.AddEventListener(YogaEventType.StartMotionCapture, OnStartMotionCapture);
|
|
EventManager.Instance.AddEventListener(YogaEventType.StopMotionCapture, OnStopMotionCapture);
|
|
EventManager.Instance.AddEventListener(YogaEventType.EstimateAction, EstimateAction);
|
|
EventManager.Instance.AddEventListener(YogaEventType.ScoreUpdate, ScoreUpdate);
|
|
EventManager.Instance.AddEventListener(YogaEventType.GetActionBasePoint, GetActionBasePoint);
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
EventManager.Instance.RemoveEventListener(YogaEventType.StartMotionCapture, OnStartMotionCapture);
|
|
EventManager.Instance.RemoveEventListener(YogaEventType.StopMotionCapture, OnStopMotionCapture);
|
|
EventManager.Instance.RemoveEventListener(YogaEventType.EstimateAction, EstimateAction);
|
|
EventManager.Instance.RemoveEventListener(YogaEventType.ScoreUpdate, ScoreUpdate);
|
|
EventManager.Instance.RemoveEventListener(YogaEventType.GetActionBasePoint, GetActionBasePoint);
|
|
}
|
|
|
|
public override void Init()
|
|
{
|
|
base.Init();
|
|
|
|
_webCamTextureToMatHelper = gameObject.GetComponent<WebCamTextureToMatHelper>();
|
|
|
|
#if UNITY_ANDROID && !UNITY_EDITOR
|
|
// Avoids the front camera low light issue that occurs in only some Android devices (e.g. Google Pixel, Pixel2).
|
|
_webCamTextureToMatHelper.avoidAndroidFrontCameraLowLightIssue = true;
|
|
#endif
|
|
|
|
_webCamTextureToMatHelper.Initialize();
|
|
|
|
UIManager.Instance.LoadReset();
|
|
|
|
if (YogaManager.Instance.Action == null)
|
|
YogaManager.Instance.InitData();
|
|
|
|
UIManager.Instance.ShowPanel<ActionGuideVideoPanel>(false, YogaManager.Instance.Action);
|
|
|
|
Utils.setDebugMode(true); //打印日志
|
|
|
|
CVEstimator.Instance.Init();//初始化姿态检测
|
|
}
|
|
|
|
private void Update()
|
|
{
|
|
if (!_isOnCamCapture)
|
|
{
|
|
return;
|
|
}
|
|
if (!transform.gameObject.activeSelf)
|
|
transform.gameObject.SetActive(true);
|
|
|
|
if (_webCamTextureToMatHelper.IsPlaying() && _webCamTextureToMatHelper.DidUpdateThisFrame())
|
|
{
|
|
Mat img = _webCamTextureToMatHelper.GetMat();
|
|
Imgproc.cvtColor(img, img, Imgproc.COLOR_BGR2RGB);
|
|
_rgbaMat = img.clone();
|
|
|
|
YogaManager.Instance.CurrentEstimator.Check(ref img);//检测模型,将错误信息打印在图片上
|
|
|
|
|
|
if (_voloResult.Count >= 2)
|
|
YogaManager.Instance.CurrentEstimator.DebugPrint(img);//DebugPrintObjectLayout(img, _voloResult[0], _voloResult[1], _voloResult[2]);
|
|
|
|
if (_currPersonPoints != null && _currPersonPoints.Count > 0)
|
|
{
|
|
List<Point> points = _currPersonPoints;
|
|
|
|
for (int i = 0; i < YogaConfig.POSE_PAIRS.GetLength(0); i++)
|
|
{
|
|
string partFrom = YogaConfig.POSE_PAIRS[i, 0];
|
|
string partTo = YogaConfig.POSE_PAIRS[i, 1];
|
|
|
|
int idFrom = YogaConfig.BODY_PARTS[partFrom];
|
|
int idTo = YogaConfig.BODY_PARTS[partTo];
|
|
|
|
if (points[idFrom] == new Point(-1, -1) || points[idTo] == new Point(-1, -1))
|
|
continue;
|
|
|
|
if (points[idFrom] != null && points[idTo] != null)
|
|
{
|
|
Imgproc.line(img, points[idFrom], points[idTo], new Scalar(0, 255, 0), 3);
|
|
Imgproc.ellipse(img, points[idFrom], 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
|
|
Utils.matToTexture2D(img, texture);
|
|
}
|
|
}
|
|
|
|
#region Event Func
|
|
private void OnStartMotionCapture()
|
|
{
|
|
this.enabled = true;
|
|
_isOnCamCapture = true;
|
|
|
|
CVEstimator.Instance.StartEstimation();//开始姿态检测
|
|
}
|
|
|
|
private void OnStopMotionCapture()
|
|
{
|
|
this.enabled = false;
|
|
_isOnCamCapture = false;
|
|
}
|
|
private void GetActionBasePoint()
|
|
{
|
|
var startTime = DateTime.Now;
|
|
while (true)
|
|
{
|
|
if (_currPersonPoints != null && _currPersonPoints.Count != 0)
|
|
{
|
|
YogaManager.Instance.Points = _currPersonPoints;
|
|
break;
|
|
}
|
|
|
|
if (startTime.AddMilliseconds(100) < DateTime.Now)
|
|
{
|
|
Debug.LogError("GetActionBasePoint timeout");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void EstimateAction(params object[] args)
|
|
{
|
|
var type = args.FirstOrDefault();
|
|
if (type == null)
|
|
{
|
|
Debug.LogError("EstimateAction type is null");
|
|
return;
|
|
}
|
|
AvatarAction actionType = (AvatarAction)args.FirstOrDefault();
|
|
|
|
|
|
//检测动作
|
|
var startTime = DateTime.Now;
|
|
|
|
while (true)
|
|
{
|
|
if (YogaManager.Instance.ActionCheckPoints(_currPersonPoints))
|
|
{
|
|
_isCorrectAction = (_isCorrectAction || YogaManager.Instance.IsCorrectAction(_currPersonPoints, actionType));
|
|
break;
|
|
}
|
|
if (startTime.AddMilliseconds(100) < DateTime.Now)
|
|
{
|
|
Debug.LogWarning("请摆正姿势");
|
|
Debug.LogWarning("EstimateAction timeout");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
/// <summary>
|
|
/// Raises the destroy event.
|
|
/// </summary>
|
|
void OnDestroy()
|
|
{
|
|
_webCamTextureToMatHelper.Dispose();
|
|
|
|
YogaManager.Instance.CurrentEstimator.Dispose();
|
|
|
|
_bgrMat.Dispose();
|
|
CVEstimator.Instance.Dispose();
|
|
}
|
|
|
|
public void OnWebCamTextureToMatHelperInitialized()
|
|
{
|
|
Debug.Log("OnWebCamTextureToMatHelperInitialized");
|
|
|
|
Mat webCamTextureMat = _webCamTextureToMatHelper.GetMat();
|
|
|
|
texture = new Texture2D(webCamTextureMat.cols(), webCamTextureMat.rows(), TextureFormat.RGB24, false);
|
|
Utils.matToTexture2D(webCamTextureMat, texture);
|
|
|
|
this.gameObject.GetComponent<Renderer>().material.mainTexture = texture;
|
|
|
|
gameObject.transform.localScale = new Vector3(webCamTextureMat.cols() / 10, webCamTextureMat.rows() / 10, 1);
|
|
Debug.Log("Screen.width " + Screen.width + " Screen.height " + Screen.height + " Screen.orientation " + Screen.orientation);
|
|
|
|
float width = webCamTextureMat.width();
|
|
float height = webCamTextureMat.height();
|
|
|
|
float widthScale = (float)Screen.width / width;
|
|
float heightScale = (float)Screen.height / height;
|
|
if (widthScale < heightScale)
|
|
{
|
|
Camera.main.orthographicSize = (width * (float)Screen.height / (float)Screen.width) / 2;
|
|
}
|
|
else
|
|
{
|
|
Camera.main.orthographicSize = height / 2;
|
|
}
|
|
|
|
_bgrMat = new Mat(webCamTextureMat.rows(), webCamTextureMat.cols(), CvType.CV_8UC3);
|
|
}
|
|
|
|
//event call
|
|
public void OnWebCamTextureToMatHelperDisposed()
|
|
{
|
|
Debug.Log("OnWebCamTextureToMatHelperDisposed");
|
|
|
|
if (_bgrMat != null)
|
|
_bgrMat.Dispose();
|
|
|
|
if (texture != null)
|
|
{
|
|
Texture2D.Destroy(texture);
|
|
texture = null;
|
|
}
|
|
}
|
|
|
|
public void OnWebCamTextureToMatHelperErrorOccurred(WebCamTextureToMatHelper.ErrorCode errorCode)
|
|
{
|
|
Debug.Log("OnWebCamTextureToMatHelperErrorOccurred " + errorCode);
|
|
}
|
|
|
|
public void ScoreUpdate()
|
|
{
|
|
|
|
if (_isCorrectAction)
|
|
{
|
|
EventManager.Instance.Dispatch(YogaEventType.ActionSuccess);
|
|
}
|
|
else
|
|
{
|
|
EventManager.Instance.Dispatch(YogaEventType.ActionFailed);
|
|
}
|
|
|
|
_isCorrectAction = false;//重置
|
|
}
|
|
}
|
|
}
|