using System.Collections.Generic; 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; // 返回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; MinVerifyLength = screenMap.UVSize.y / 6; 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; foreach (var i in areas) { var len = (i.Centroid - predict).magnitude; if (len < MinVerifyLength) { if (len < minLength) { 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.Center; 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(); } } } } }