PixelSpotArea_DbScan.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. using o0;
  2. using o0.Num;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Threading.Tasks;
  7. using UnityEngine;
  8. using ZIM.Unity;
  9. using static ScreenLocate;
  10. using Color = UnityEngine.Color;
  11. namespace ZIM
  12. {
  13. public interface IPixel<T>
  14. {
  15. // 像素坐标点
  16. T Point { get;}
  17. }
  18. // 亮区的点用来定位(计算center),泛光区域的点用来计算radius
  19. public class PixelSpotArea_DbScan
  20. {
  21. // 中心
  22. Vector2 centroid = default; // 该项目里center不可能等于0,0
  23. public Vector2 Centroid
  24. {
  25. get
  26. {
  27. if (centroid != default)
  28. return centroid;
  29. foreach (var p in Pixels0)
  30. centroid += p.Point;
  31. return centroid /= Pixels0.Count;
  32. }
  33. }
  34. // 亮区的半径,计算含泛光点
  35. float radius = 0;
  36. public float Radius
  37. {
  38. set
  39. {
  40. radius = value;
  41. }
  42. get
  43. {
  44. if (radius != 0)
  45. return radius;
  46. return radius = CalculateRadius();
  47. }
  48. }
  49. public float CalculateRadius()
  50. {
  51. //var radiusDic = new Dictionary<int, float>() { { 0, 0 }, { 45, 0 }, { 90, 0 }, { 135, 0 }, { 180, 0 }, { 225, 0 }, { 270, 0 }, { 315, 0 } };
  52. var radiusDic = new float[8];
  53. foreach (var p in Pixels0)
  54. {
  55. var dir = p.Point - Centroid;
  56. var radius = dir.magnitude;
  57. var degreeI = radius < 0.00001f ? 0 : (int)(dir.DegreeToXAxis() / 45);
  58. if (degreeI > 7) degreeI = 0; // 防止正好360度
  59. if (radius > radiusDic[degreeI])
  60. radiusDic[degreeI] = radius;
  61. }
  62. foreach (var p in Pixels1)
  63. {
  64. var dir = p - Centroid;
  65. var radius = dir.magnitude;
  66. var degreeI = radius < 0.00001f ? 0 : (int)(dir.DegreeToXAxis() / 45);
  67. if (degreeI > 7) degreeI = 0;
  68. if (radius > radiusDic[degreeI])
  69. radiusDic[degreeI] = radius;
  70. }
  71. return radiusDic.Mean();
  72. }
  73. // 中心亮点
  74. public List<IPixel<Vector2>> Pixels0 = new List<IPixel<Vector2>>();
  75. // 泛光
  76. public List<Vector2> Pixels1 = new List<Vector2>();
  77. public PixelSpotArea_DbScan(IEnumerable<IPixel<Vector2>> p) // kmeans中用随机点初始化,作为中心
  78. {
  79. Pixels0.AddRange(p);
  80. }
  81. // 中心亮点
  82. public void Add0(IPixel<Vector2> p)
  83. {
  84. Pixels0.Add(p);
  85. }
  86. // 泛光
  87. public void Add1(Vector2 point)
  88. {
  89. Pixels1.Add(point);
  90. }
  91. public void Clear()
  92. {
  93. Pixels0.Clear();
  94. Pixels1.Clear();
  95. }
  96. public float TotalBrightness(Color[] pixels, Func<int, int, int> Vector2ToIndex, int outer_size = 3)
  97. {
  98. (int x, int y) rectMin = ((int)(Centroid.x - Radius - outer_size), (int)(Centroid.y - Radius - outer_size));
  99. (int x, int y) rectMax = ((int)(Centroid.x + Radius + outer_size), (int)(Centroid.y + Radius + outer_size));
  100. var total = 0f;
  101. Parallel.For(rectMin.x, rectMax.x, (i) =>
  102. {
  103. var t = 0;
  104. for (int j = rectMin.y; j < rectMax.y; j++)
  105. {
  106. var index = Vector2ToIndex(i, j);
  107. var b = pixels[index].Brightness(64);
  108. t += b;
  109. }
  110. lock (InfraredLocate.locker)
  111. {
  112. total += t;
  113. }
  114. });
  115. //total /= (rectMax.y - rectMin.y) * (rectMax.x - rectMin.x);
  116. return total;
  117. }
  118. }
  119. }