using o0; using o0.Num; using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using UnityEngine; using ZIM.Unity; using static ScreenLocate; using Color = UnityEngine.Color; namespace ZIM { public interface IPixel { // 像素坐标点 T Point { get;} } // 亮区的点用来定位(计算center),泛光区域的点用来计算radius public class PixelSpotArea_DbScan { // 中心 Vector2 centroid = default; // 该项目里center不可能等于0,0 public Vector2 Centroid { get { if (centroid != default) return centroid; foreach (var p in Pixels0) centroid += p.Point; return centroid /= Pixels0.Count; } } // 亮区的半径,计算含泛光点 float radius = 0; public float Radius { set { radius = value; } get { if (radius != 0) return radius; return radius = CalculateRadius(); } } 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.Point - 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 radiusDic.Mean(); } // 中心亮点 public List> Pixels0 = new List>(); // 泛光 public List Pixels1 = new List(); public PixelSpotArea_DbScan(IEnumerable> p) // kmeans中用随机点初始化,作为中心 { Pixels0.AddRange(p); } // 中心亮点 public void Add0(IPixel 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; } } }