InfraredSpot.cs 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using ZIM.Unity;
  4. using Color = UnityEngine.Color;
  5. namespace ZIM
  6. {
  7. public class InfraredSpot
  8. {
  9. // 达到该数量才完成初始化
  10. //static int InitCount = 5;
  11. static int MaxVerifyFailLimit = 20;
  12. public static float MinVerifyLength = 240;
  13. public static void RefreshMinVerifyLength(o0.Geometry2D.Float.Vector cameraSize)
  14. {
  15. MinVerifyLength = (cameraSize.x + cameraSize.y) / 20;
  16. }
  17. // 返回null代表没有点,范围在[0, 1]内
  18. public Vector2? ScreenUV
  19. {
  20. get
  21. {
  22. if (ScreenLocation.HasValue)
  23. {
  24. return screenMap.UVNormalized(ScreenLocation.Value);
  25. }
  26. else
  27. {
  28. return null;
  29. }
  30. }
  31. }
  32. // 范围在摄像机的Size内
  33. public Vector2? CameraLocation
  34. {
  35. get
  36. {
  37. if (ScreenLocation.HasValue)
  38. {
  39. return screenMap.TransformToCamera(ScreenLocation.Value);
  40. }
  41. else
  42. return null;
  43. }
  44. }
  45. public Vector2? Predict { get; set; } // 为null时代表未初始化
  46. public InfraredMatch Match { get; private set; }
  47. public bool Disappear;
  48. //PixelSpotArea verifyArea;
  49. int verifyFailLimit;
  50. List<PixelSpotArea> spots;
  51. SimpleLocationEstimation estimation;
  52. Vector2? ScreenLocation;
  53. ScreenMap screenMap;
  54. public InfraredSpot(ScreenMap screenMap, InfraredMatch match)
  55. {
  56. this.screenMap = screenMap;
  57. Match = match;
  58. spots = new List<PixelSpotArea>();
  59. Reset();
  60. }
  61. public void Reset()
  62. {
  63. spots.Clear();
  64. estimation = new SimpleLocationEstimation(0.5f);
  65. ScreenLocation = null;
  66. Predict = null;
  67. Disappear = false;
  68. //verifyArea = null;
  69. verifyFailLimit = MaxVerifyFailLimit;
  70. }
  71. public bool Verify(List<PixelSpotArea> areas, Dictionary<InfraredMatch, PixelSpotArea> matchedArea)
  72. {
  73. if (Predict == null) // 未初始化
  74. return false;
  75. PixelSpotArea select = null;
  76. var minLength = float.MaxValue;
  77. var predict = Predict.Value;
  78. foreach (var i in areas)
  79. {
  80. var len = (i.Centroid - predict).magnitude;
  81. if (len < MinVerifyLength)
  82. {
  83. if (len < minLength)
  84. {
  85. select = i;
  86. minLength = len;
  87. }
  88. }
  89. }
  90. if (select == null)
  91. {
  92. //Debug.Log(verifyFailLimit);
  93. verifyFailLimit--;
  94. if (verifyFailLimit == 0)
  95. Reset();
  96. return false;
  97. }
  98. //verifyArea = select;
  99. matchedArea[Match] = select;
  100. return true;
  101. }
  102. //public void UpdateByVerifyArea()
  103. //{
  104. // Update(verifyArea);
  105. //}
  106. // 为null时采用预测点
  107. public void Update(PixelSpotArea area)
  108. {
  109. if (area == null)
  110. {
  111. //throw new System.Exception("[InfraredSpot] Update Wrong");
  112. UpdateByPredict();
  113. return;
  114. }
  115. var predict = estimation.Update(area.Centroid);
  116. //ScreenLocation = area.Center;
  117. ScreenLocation = area.Centroid * 0.8f + predict * 0.2f;
  118. spots.Add(area);
  119. if (spots.Count > 15)
  120. {
  121. Predict = predict;
  122. spots.RemoveAt(0);
  123. }
  124. }
  125. void UpdateByPredict()
  126. {
  127. if (spots.Count != 0)
  128. {
  129. if (Predict == null) // 还未初始化,直接Reset
  130. Reset();
  131. else
  132. {
  133. // 采用预测点,但超出屏幕则Reset
  134. if (screenMap.UVInScreen(Predict.Value))
  135. {
  136. ScreenLocation = Predict;
  137. var newP = estimation.Update(Predict.Value);
  138. Predict = newP;
  139. }
  140. else
  141. Reset();
  142. }
  143. }
  144. }
  145. }
  146. }