using DbscanImplementation; using o0; using o0.Num; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Unity.VisualScripting; using UnityEngine; using ZIM.Unity; using static ScreenLocate; using Color = UnityEngine.Color; namespace ZIM { // 亮区的点用来定位(计算center),泛光区域的点用来计算radius public class PixelSpotArea_DbScan : ISpotArea { // 中心 Vector2 centroid = default; // 该项目里center不可能等于0,0 public Vector2 Centroid { get { if (centroid != default) return centroid; foreach (var p in Pixels0) centroid += p; return centroid /= Pixels0.Count; } } // 亮区的半径,计算含泛光点 float radius = 0; public float Radius { set { radius = value; } get { if (radius != 0) return radius; return CalculateRadius(); // 函数里会赋值 radius } } public float CalculateRadius() { //var radiusDic = new Dictionary() { { 0, 0 }, { 45, 0 }, { 90, 0 }, { 135, 0 }, { 180, 0 }, { 225, 0 }, { 270, 0 }, { 315, 0 } }; var radiusDic = new float[8]; foreach (var p in Pixels0) { var dir = p - Centroid; var radius = dir.magnitude; var degreeI = radius < 0.00001f ? 0 : (int)(dir.DegreeToXAxis() / 45); if (degreeI > 7) degreeI = 0; // 防止正好360度 if (radius > radiusDic[degreeI]) radiusDic[degreeI] = radius; } foreach (var p in Pixels1) { var dir = p - Centroid; var radius = dir.magnitude; var degreeI = radius < 0.00001f ? 0 : (int)(dir.DegreeToXAxis() / 45); if (degreeI > 7) degreeI = 0; if (radius > radiusDic[degreeI]) radiusDic[degreeI] = radius; } return radius = radiusDic.Mean(); } // 中心亮点 public List Pixels0 { get; set; } // 泛光 public List Pixels1 { get; set; } public PixelSpotArea_DbScan(IEnumerable points) // kmeans中用随机点初始化,作为中心 { Pixels0 = new List(); Pixels1 = new List(); Pixels0.AddRange(points); } public PixelSpotArea_DbScan(List> points) { Pixels0 = new List(); Pixels1 = new List(); Pixels0.AddRange(points.Select((i) => i.Point)); } // 中心亮点 public void Add0(Vector2 p) { Pixels0.Add(p); } // 泛光 public void Add1(Vector2 point) { Pixels1.Add(point); } public void Clear() { Pixels0.Clear(); Pixels1.Clear(); } public float TotalBrightness(Color[] pixels, Func Vector2ToIndex, int outer_size = 3) { (int x, int y) rectMin = ((int)(Centroid.x - Radius - outer_size), (int)(Centroid.y - Radius - outer_size)); (int x, int y) rectMax = ((int)(Centroid.x + Radius + outer_size), (int)(Centroid.y + Radius + outer_size)); var total = 0f; Parallel.For(rectMin.x, rectMax.x, (i) => { var t = 0; for (int j = rectMin.y; j < rectMax.y; j++) { var index = Vector2ToIndex(i, j); var b = pixels[index].Brightness(64); t += b; } lock (InfraredLocate.locker) { total += t; } }); //total /= (rectMax.y - rectMin.y) * (rectMax.x - rectMin.x); return total; } } }