using System.Collections.Generic; using System.Linq; using UnityEngine; using ZIM.Unity; using Color = UnityEngine.Color; namespace ZIM { public class InfraredSpot { // 达到该数量才完成初始化 //static int InitCount = 5; static int MaxVerifyFailLimit = 20; public static float MinVerifyLength = 240; public static void RefreshMinVerifyLength(o0.Geometry2D.Float.Vector cameraSize) { MinVerifyLength = (cameraSize.x + cameraSize.y) / 20; } // 返回null代表没有点,范围在[0, 1]内 public Vector2? ScreenUV { get { if (ScreenLocation.HasValue) { return screenMap.UVNormalized(ScreenLocation.Value); } else { return null; } } } // 范围在摄像机的Size内 public Vector2? CameraLocation { get { if (ScreenLocation.HasValue) { return screenMap.TransformToCamera(ScreenLocation.Value); } else return null; } } public Vector2? Predict { get; set; } // 为null时代表未初始化 public InfraredMatch Match { get; private set; } public bool Disappear; //PixelSpotArea verifyArea; int verifyFailLimit; List spots; SimpleLocationEstimation estimation; Vector2? ScreenLocation; ScreenMap screenMap; public InfraredSpot(ScreenMap screenMap, InfraredMatch match) { this.screenMap = screenMap; Match = match; spots = new List(); Reset(); } public void Reset() { spots.Clear(); estimation = new SimpleLocationEstimation(0.5f); ScreenLocation = null; Predict = null; Disappear = false; //verifyArea = null; verifyFailLimit = MaxVerifyFailLimit; } public bool Verify(List areas, Dictionary matchedArea) { if (Predict == null) // 未初始化 return false; PixelSpotArea select = null; var minLength = float.MaxValue; var predict = Predict.Value; var refPoint = (predict + spots.Last().Centroid) / 2; // 用预测点和最后一个点的中点来判断是否追踪到 foreach (var i in areas) { var len = (i.Centroid - refPoint).magnitude; if (len < MinVerifyLength) { if (len < minLength) // 找到追踪到的,并且距离最近的spot { select = i; minLength = len; } } } if (select == null) { //Debug.Log(verifyFailLimit); verifyFailLimit--; if (verifyFailLimit == 0) Reset(); return false; } //verifyArea = select; matchedArea[Match] = select; return true; } //public void UpdateByVerifyArea() //{ // Update(verifyArea); //} // 为null时采用预测点 public void Update(PixelSpotArea area) { if (area == null) { //throw new System.Exception("[InfraredSpot] Update Wrong"); UpdateByPredict(); return; } var predict = estimation.Update(area.Centroid); ScreenLocation = area.Centroid * 0.8f + predict * 0.2f; // 参考一点预测点,防止光标不稳定 spots.Add(area); if (spots.Count > 15) { Predict = predict; spots.RemoveAt(0); } } void UpdateByPredict() { if (spots.Count != 0) { if (Predict == null) // 还未初始化,直接Reset Reset(); else { // 采用预测点,但超出屏幕则Reset if (screenMap.UVInScreen(Predict.Value)) { ScreenLocation = Predict; var newP = estimation.Update(Predict.Value); Predict = newP; } else Reset(); } } } } }