PixelCircleArea.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. using o0;
  2. using System;
  3. using System.Collections.Generic;
  4. using Unity.VisualScripting;
  5. using UnityEngine;
  6. namespace ZIM
  7. {
  8. internal class PixelCircleArea
  9. {
  10. public Vector2 Center;
  11. public float MaxRadius;
  12. public HashSet<Vector2> Pixels;
  13. HashSet<(int, int)> grids;
  14. public PixelCircleArea(Vector2 location)
  15. {
  16. Center = location;
  17. Pixels = new HashSet<Vector2> { location };
  18. MaxRadius = 0;
  19. grids = new HashSet<(int, int)>();
  20. Add(location);
  21. }
  22. public PixelCircleArea(IList<PixelCircleArea> areas)
  23. {
  24. Center = Vector2.zero;
  25. Pixels = new HashSet<Vector2>();
  26. MaxRadius = 0;
  27. grids = new HashSet<(int, int)>();
  28. foreach (var a in areas)
  29. {
  30. Pixels.AddRange(a.Pixels);
  31. grids.AddRange(a.grids);
  32. }
  33. foreach (var p in Pixels)
  34. {
  35. Center += p;
  36. }
  37. Center /= Pixels.Count;
  38. foreach (var p in Pixels)
  39. {
  40. var radius = (p - Center).magnitude;
  41. if (radius > MaxRadius)
  42. MaxRadius = radius;
  43. }
  44. }
  45. public bool Include((int, int) grid) => grids.Contains(grid);
  46. public void Add(Vector2 point) => Add(point, PixelArea.GetGrid(point));
  47. public void Add(Vector2 point, (int x, int y) grid)
  48. {
  49. Center += (point - Center) / Pixels.Count;
  50. var radius = (point - Center).magnitude;
  51. if (radius > MaxRadius)
  52. MaxRadius = radius;
  53. Pixels.Add(point);
  54. grids.AddRange(new (int, int)[]
  55. {
  56. (grid.x + -1, grid.y + 0) , (grid.x + 1 , grid.y + 0),
  57. (grid.x + 1, grid.y + -1) , (grid.x + -1, grid.y + 1),
  58. (grid.x + 0, grid.y + -1) , (grid.x + 0 , grid.y + 1),
  59. (grid.x + -1, grid.y + -1) , (grid.x + 1 , grid.y + 1),
  60. grid
  61. });
  62. }
  63. public float CircleBrightness(out float variance, int[] pixels, Func<int[], (int, int), int, float> GetBrightness, int kernel_size = 3)
  64. {
  65. var hash = new HashSet<(int, int)>();
  66. foreach (var (cos, sin) in PixelArea.AngleMathList)
  67. {
  68. var x = (int)Math.Round(Center.x + (MaxRadius + 1) * cos); // +1防止区域太小
  69. var y = (int)Math.Round(Center.y + (MaxRadius + 1) * sin);
  70. hash.Add((x, y));
  71. }
  72. var sum = 0f;
  73. var sum2 = 0f;
  74. foreach (var p in hash)
  75. {
  76. var value = GetBrightness(pixels, p, kernel_size);
  77. sum += value;
  78. sum2 += value * value;
  79. }
  80. var avg = sum / hash.Count;
  81. variance = sum2 / hash.Count - avg * avg;
  82. //Debug.Log(hash.Count + " -- bright: " + avg);
  83. return avg;
  84. }
  85. }
  86. }