using OpenCVForUnity.CoreModule; using System; using System.Collections.Generic; using System.Linq; using UnityEngine; public abstract class PoseBase { public Dictionary GetVaildPoints(List points, List pointName) { var retVal = new Dictionary(); foreach (var name in pointName) { if (points[YogaConfig.BODY_PARTS[name]] != new Point(-1, -1)) { retVal.Add(name, points[YogaConfig.BODY_PARTS[name]]); } } return retVal; } public abstract Vector2 GetBasicVectorDirection(List startPoint, List endPoint); //public abstract void SpeedCheck(double v); public abstract void ValidationMovement(Vector2 distance, TimeSpan totalTimeSpan, int level); public abstract void ExcellenceEstimate(List<(TimeSpan, Vector2)> frameData, Vector2 distance, TimeSpan totalTimeSpan); protected Vector2 GetAverageVector(List startPoint, List endPoint, string movePoint) { List vectors = new List(); for (int i = 0; i < endPoint.Count; i++) { string tagName = i.tagName(); //自身不计算 if (movePoint.Equals(tagName) || movePoint.Equals(tagName)) continue; //动点位不计算 if (IsMovePoint(tagName)) continue; if (!tagName.IsValid(startPoint) || !tagName.IsValid(endPoint)) continue; //动点-静点 Vector2 startEyeV = new Vector2((float)movePoint.p(startPoint).x - (float)tagName.p(startPoint).x, (float)movePoint.p(startPoint).y - (float)tagName.p(startPoint).y); Vector2 endEyeV = new Vector2((float)movePoint.p(endPoint).x - (float)tagName.p(endPoint).x, (float)movePoint.p(endPoint).y - (float)tagName.p(endPoint).y); vectors.Add(endEyeV - startEyeV); } //计算平均矢量 Vector2 averageV = new Vector2(0, 0); foreach (var v in vectors) { averageV += v; } averageV /= vectors.Count; return averageV; } /// /// 确定该点位是否为运动时会跟着动的点位 /// 内部重写,写明该动作的所有动点 /// /// 点位名称 /// 是否为动点 protected abstract bool IsMovePoint(string tagName); /// /// 动作检测 /// /// /// public virtual void AnalyzingAction(List<(DateTime, List)> points, bool isDataReGather = false) { if (points.Count < 2) // 0级实现逻辑 不做操作 return; var distance = Vector2.zero; TimeSpan totalTimeSpan = TimeSpan.MinValue; for (int i = 0; i < points.Count - 1; i++) { var p1 = points[i].Item2; var p2 = points[i + 1].Item2; var vector = GetAverageVector(p1, p2, "Nose"); //关键点Nose distance += vector; if (vector.magnitude > 0.1f) //如果矢量长度大于0.1f,说明有运动 { TimeSpan timeSpan = points[i + 1].Item1 - points[i].Item1; if (totalTimeSpan == TimeSpan.MinValue) totalTimeSpan = timeSpan; else totalTimeSpan += timeSpan; } } LogPrint.Log($"distance: {distance}, totalTimeSpan: {totalTimeSpan}", PrintLevel.Normal); int level = 0; if (points.Count > 3 && !isDataReGather) //1级实现逻辑 { level = 1; } if (points.Count > 10 && !isDataReGather) //2级实现逻辑 { level = 2; } //动作方位是否正确 ValidationMovement(distance, totalTimeSpan, level); } }