| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 | 
							- using o0;
 
- using o0.Num;
 
- using System;
 
- using System.Collections.Generic;
 
- using System.Linq;
 
- using System.Threading.Tasks;
 
- using UnityEngine;
 
- using static ScreenLocate;
 
- namespace ZIM 
 
- { 
 
-     public class KMeans
 
-     {
 
-         public System.Random Rand = new System.Random();
 
-         // 用轮廓系数评价K值
 
-         public List<PixelSpotAreaOld> InfraredSpotCluster(List<Vector2> spotPoint, List<Vector2> brightPoint, int spotMaxCount, Func<Vector2, bool> PointFilter = null)
 
-         {
 
-             if (PointFilter != null)    // 筛掉屏幕外的点
 
-             {
 
-                 var temp0 = new List<Vector2>(spotPoint.Count);
 
-                 var temp1 = new List<Vector2>(spotPoint.Count);
 
-                 foreach (var p in spotPoint)
 
-                 {
 
-                     if (PointFilter(p))
 
-                         temp0.Add(p);
 
-                 }
 
-                 foreach (var p in brightPoint)
 
-                 {
 
-                     if (PointFilter(p))
 
-                         temp1.Add(p);
 
-                 }
 
-                 spotPoint = temp0;
 
-                 brightPoint = temp1;
 
-             }
 
-             // 从1-k,计算多次聚类,再评估选出best k
 
-             List<PixelSpotAreaOld>[] ClustersArray = new List<PixelSpotAreaOld>[spotMaxCount];   // 各个K对应的Clusters
 
-             float[] silhouetteScores = new float[spotMaxCount];                    // 轮廓系数
 
-             for (int i = 0; i < spotMaxCount; i++)
 
-             {
 
-                 int k = i + 1;
 
-                 var clusters = Cluster(spotPoint, brightPoint, k);
 
-                 Debug.Log("k: " + k);
 
-                 foreach (var j in clusters)
 
-                 {
 
-                     Debug.Log(j.Centroid + ", " + j.Radius);
 
-                 }
 
-                 silhouetteScores[i] = CalculateSilhouetteScore(spotPoint, clusters);
 
-                 ClustersArray[i] = clusters;
 
-                 Debug.Log("silhouetteScore: " + silhouetteScores[i]);
 
-             }
 
-             int best = silhouetteScores.MaxIndex();
 
-             foreach (var j in ClustersArray[best])
 
-             {
 
-                 Debug.Log("select: " + j.Centroid + ", " + j.Radius);
 
-             }
 
-             return ClustersArray[best];
 
-         }
 
-         // 计算轮廓系数
 
-         public float CalculateSilhouetteScore(List<Vector2> points, List<PixelSpotAreaOld> clusters)
 
-         {
 
-             int numPoints = points.Count;
 
-             float totalSilhouetteScore = 0f;
 
-             Dictionary<Vector2, int> pointToClusterMap = new Dictionary<Vector2, int>();
 
-             for (int i = 0; i < clusters.Count; i++)
 
-             {
 
-                 foreach (var p in clusters[i].Pixels0)
 
-                     pointToClusterMap[p] = i;
 
-             }
 
-             foreach (var point in points)
 
-             {
 
-                 int clusterIndex = pointToClusterMap[point];
 
-                 float a = AverageDistance(point, clusters[clusterIndex]);
 
-                 float b = float.MaxValue;
 
-                 for (int i = 0; i < clusters.Count; i++)
 
-                 {
 
-                     if (i == clusterIndex) continue;
 
-                     float distance = AverageDistance(point, clusters[i]);
 
-                     if (distance < b)
 
-                     {
 
-                         b = distance;
 
-                     }
 
-                 }
 
-                 float s = (b - a) / Mathf.Max(a, b);
 
-                 totalSilhouetteScore += s;
 
-             }
 
-             return totalSilhouetteScore / numPoints;
 
-         }
 
-         private float AverageDistance(Vector2 point, PixelSpotAreaOld cluster)
 
-         {
 
-             float totalDistance = 0f;
 
-             foreach (var c in cluster.Pixels0)
 
-                 totalDistance += Vector2.Distance(point, c);
 
-             return totalDistance / cluster.Pixels0.Count;
 
-         }
 
-         // KMeans聚类
 
-         private List<PixelSpotAreaOld> Cluster(List<Vector2> spotPoint, List<Vector2> brightPoint, int k, int maxIterations = 10)
 
-         {
 
-             if (spotPoint.Count < k)
 
-                 return new List<PixelSpotAreaOld>();
 
-             var clusters = InitializeClusters(spotPoint, k);
 
-             bool centroidsChanged = true;
 
-             int iterations = 0;
 
-             while (centroidsChanged && iterations < maxIterations)
 
-             {
 
-                 foreach (var i in clusters)
 
-                     i.Clear();
 
-                 foreach (var point in spotPoint)
 
-                 {
 
-                     int closestCentroidIndex = GetClosestClusterIndex(point, clusters);
 
-                     clusters[closestCentroidIndex].Add0(point);
 
-                 }
 
-                 centroidsChanged = false;
 
-                 foreach (var i in clusters)
 
-                 {
 
-                     if (i.UpdateCentroid())
 
-                         centroidsChanged = true;
 
-                 }
 
-                 iterations++;
 
-             }
 
-             // 聚类完成,添加泛光点
 
-             foreach (var point in brightPoint)
 
-             {
 
-                 int closestCentroidIndex = GetClosestClusterIndex(point, clusters);
 
-                 clusters[closestCentroidIndex].Add1(point);
 
-             }
 
-             return clusters;
 
-         }
 
-         private List<PixelSpotAreaOld> InitializeClusters(List<Vector2> points, int k)
 
-         {
 
-             Vector2[] centroids = new Vector2[k];
 
-             HashSet<int> chosenIndices = new HashSet<int>();
 
-             for (int i = 0; i < k; i++)
 
-             {
 
-                 int index;
 
-                 do
 
-                 {
 
-                     index = Rand.Next(points.Count);
 
-                 } while (chosenIndices.Contains(index));
 
-                 chosenIndices.Add(index);
 
-                 centroids[i] = points[index];
 
-             }
 
-             List<PixelSpotAreaOld> clusters = new List<PixelSpotAreaOld>(k);
 
-             foreach (var i in centroids)
 
-                 clusters.Add(new PixelSpotAreaOld(i));
 
-             return clusters;
 
-         }
 
-         private int GetClosestClusterIndex(Vector2 point, List<PixelSpotAreaOld> centroids)
 
-         {
 
-             int closestIndex = 0;
 
-             float minDistance = Vector2.Distance(point, centroids[0].Centroid);
 
-             for (int i = 1; i < centroids.Count; i++)
 
-             {
 
-                 float distance = Vector2.Distance(point, centroids[i].Centroid);
 
-                 if (distance < minDistance)
 
-                 {
 
-                     minDistance = distance;
 
-                     closestIndex = i;
 
-                 }
 
-             }
 
-             return closestIndex;
 
-         }
 
-     }
 
- }
 
 
  |