ZIM 1 год назад
Родитель
Сommit
aee8b7e7b2

+ 1 - 0
Assets/InfraredProject/InfraredCamera/Scripts/ScreenLocate.cs

@@ -46,6 +46,7 @@ public partial class ScreenLocate : MonoBehaviour
 
             //screenIdentification?.SetScreenQuad(quad);
             screenIdentification.QuadManual = quad;
+            SelectScreenAfterLocate(ScreenIdentificationTag.Manual);
             Debug.Log($"[ScreenLocate] 记录手动数据: {quad}");
         }
         ToMode(Mode.InfraredLocate);

+ 56 - 55
Assets/InfraredProject/WebCamera/Script/ZIM/InfraredLocate/InfraredLocate.cs

@@ -134,8 +134,8 @@ namespace ZIM
             (int x, int y) rectMin = ((int)rect.min.x / SamplingScale, (int)rect.min.y / SamplingScale);
             (int x, int y) rectMax = ((int)rect.max.x / SamplingScale, (int)rect.max.y / SamplingScale);
 
-            var spotPoint = new List<Vector2>(200);     // 预估的初始容量
-            var brightPoint = new List<Vector2>(1000);
+            var spotPoint = new List<Vector2>(100);     // 预估的初始容量
+            var brightPoint = new List<Vector2>(500);
 
             Parallel.For(rectMin.x, rectMax.x, (i) =>
             {
@@ -172,14 +172,15 @@ namespace ZIM
 
             //if (ScreenLocate.Main.DebugOnZIMDemo)
             {
-                if (spotPoint.Count > 500)     // 如果亮点太多,控制亮点数量在500左右
+                float maxPoints = 200;      // 如果亮点太多,通过间隔采样控制亮点在一定数量以内
+                if (spotPoint.Count > maxPoints)
                 {
-                    SamplingScale = (int)Math.Ceiling(SamplingScale * Math.Sqrt(spotPoint.Count / 500.0));
+                    SamplingScale = (int)Math.Ceiling(SamplingScale * Math.Sqrt(spotPoint.Count / maxPoints));
                     return new List<ISpotArea>();
                 }
-                else if (SamplingScale > 1 && spotPoint.Count < 100)
+                else if (SamplingScale > 1 && spotPoint.Count < maxPoints * 0.2f) 
                 {
-                    SamplingScale = Math.Max((int)Math.Ceiling(SamplingScale * Math.Sqrt(spotPoint.Count / 200.0)), 1);
+                    SamplingScale = Math.Max((int)Math.Ceiling(SamplingScale * Math.Sqrt(spotPoint.Count / maxPoints * 3)), 1);
                     return new List<ISpotArea>();
                 }
             }
@@ -187,72 +188,72 @@ namespace ZIM
             //times.Add(watch.ElapsedMilliseconds);
             //UnityEngine.Debug.Log("time1: " + (times[times.Count - 1] - times[times.Count - 2]));
 
-            // 所有点映射到屏幕空间
-            Parallel.For(0, spotPoint.Count, (i) => spotPoint[i] = screenIdentification.Screen.TransformToScreen(spotPoint[i]));
-            Parallel.For(0, brightPoint.Count, (i) => brightPoint[i] = screenIdentification.Screen.TransformToScreen(brightPoint[i]));
+            //Parallel.For(0, spotPoint.Count, (i) => spotPoint[i] = screenIdentification.Screen.TransformToScreen(spotPoint[i]));
+            //Parallel.For(0, brightPoint.Count, (i) => brightPoint[i] = screenIdentification.Screen.TransformToScreen(brightPoint[i]));
 
             // 筛掉屏幕外的点
-            var temp0 = new List<Vector2>(spotPoint.Count);
-            var temp1 = new List<Vector2>(spotPoint.Count);
-            foreach (var p in spotPoint)
+            if (screenIdentification.Screen.Active)
             {
-                if (screenIdentification.Screen.UVInScreen(p))
-                    temp0.Add(p);
-            }
-            foreach (var p in brightPoint)
-            {
-                if (screenIdentification.Screen.UVInScreen(p))
-                    temp1.Add(p);
+                var temp0 = new List<Vector2>(spotPoint.Count);
+                var temp1 = new List<Vector2>(spotPoint.Count);
+                foreach (var p in spotPoint)
+                {
+                    var pS = screenIdentification.Screen.TransformToScreen(p);
+                    if (screenIdentification.Screen.UVInScreen(pS))
+                        temp0.Add(p);
+                }
+                foreach (var p in brightPoint)
+                {
+                    var pS = screenIdentification.Screen.TransformToScreen(p);
+                    if (screenIdentification.Screen.UVInScreen(pS))
+                        temp1.Add(p);
+                }
+                spotPoint = temp0;
+                brightPoint = temp1;
             }
-            spotPoint = temp0;
-            brightPoint = temp1;
 
+            //times.Add(watch.ElapsedMilliseconds);
+            //UnityEngine.Debug.Log("time2: " + (times[times.Count - 1] - times[times.Count - 2]));
+
+            // 聚类算法,得到结果
             if (spotPoint.Count > 0)
             {
-                //times.Add(watch.ElapsedMilliseconds);
-                //UnityEngine.Debug.Log("time2: " + (times[times.Count - 1] - times[times.Count - 2]));
-
                 var db = Dbscan.Run(spotPoint, ZIM.Unity.ZIMMath.LengthManhattan, SamplingScale, 4);
                 var spotArea = DbscanToSpotAreas(db, brightPoint);
                 //var spotArea = PixelSpotArea.Cluster(spotPoint, brightPoint, screenIdentification.Screen.UVInScreen);
 
-                if (ScreenLocate.Main.DebugOnZIMDemo)
-                    DebugAreas(spotArea);
-
-
-                //Debug.Log("db: " + db.Clusters.Count);
-                //Debug.Log("db noise: " + db.Noise.Count);
-                //foreach (var i in spotArea)
-                //{
-                //    Debug.Log("i.Radius" + i.Radius);
-                //}
-
                 //times.Add(watch.ElapsedMilliseconds);
                 //UnityEngine.Debug.Log("time3: " + (times[times.Count - 1] - times[times.Count - 2]));
 
-                return spotArea;
-
-                //半径再按透视修正一遍,降低一点常规角度下反射的影响
-                //foreach (var i in spotArea)
-                //{
-                //    var r0 = i.Radius / 2 / mCameraInfo.CurrentWidth;
-                //    var center = i.Centroid;
-                //    var offset1 = center + new Vector2(i.Radius / 2, 0);
-                //    var offset2 = center - new Vector2(i.Radius / 2, 0);
-                //    var offset3 = center + new Vector2(0, i.Radius / 2);
-                //    var offset4 = center - new Vector2(0, i.Radius / 2);
-                //    var transR = ((screenIdentification.Screen.TransformToScreen(offset1) - screenIdentification.Screen.TransformToScreen(offset2)).magnitude +
-                //        (screenIdentification.Screen.TransformToScreen(offset3) - screenIdentification.Screen.TransformToScreen(offset4)).magnitude) / 4;
-                //    var r1 = transR / screenIdentification.Screen.UVSize.x;
-                //    //Debug.Log(r1 / r0);
-                //    i.Radius *= (float)Math.Pow(r1 / r0, 2);      // 摄像机位置不同参数也可能不同
-                //}
+                //半径和中心按透视调整
+                if (screenIdentification.Screen.Active)
+                {
+                    foreach (var i in spotArea)
+                    {
+                        var center = i.Centroid;
+                        var offset1 = center + new Vector2(i.Radius, 0);
+                        var offset2 = center - new Vector2(i.Radius, 0);
+                        var offset3 = center + new Vector2(0, i.Radius);
+                        var offset4 = center - new Vector2(0, i.Radius);
+                        var transC = screenIdentification.Screen.TransformToScreen(i.Centroid);
+                        var transR = ((screenIdentification.Screen.TransformToScreen(offset1) - screenIdentification.Screen.TransformToScreen(offset2)).magnitude +
+                            (screenIdentification.Screen.TransformToScreen(offset3) - screenIdentification.Screen.TransformToScreen(offset4)).magnitude) / 4;
+                        //var r0 = i.Radius / mCameraInfo.CurrentWidth;
+                        //var r1 = transR / screenIdentification.Screen.UVSize.x;
+                        //i.Radius *= (float)Math.Pow(r1 / r0, 2);      // 摄像机位置不同参数也可能不同
+
+                        i.Centroid = transC;
+                        i.Radius = transR;
+                    }
+                }
 
-                //if (spotArea.Count == 1)
-                //Debug.Log($"{spotArea[0].MaxRadius}");
+                //times.Add(watch.ElapsedMilliseconds);
+                //UnityEngine.Debug.Log("time4: " + (times[times.Count - 1] - times[times.Count - 2]));
 
-                //return spotArea;
+                if (ScreenLocate.Main.DebugOnZIMDemo)
+                    DebugAreas(spotArea);
 
+                return spotArea;
 
                 //// 排序亮区
                 //spotArea.Sort((a, b) => b.MaxRadius.CompareTo(a.MaxRadius));

+ 4 - 3
Assets/InfraredProject/WebCamera/Script/ZIM/InfraredLocate/InfraredSpot/ISpotArea.cs

@@ -3,10 +3,11 @@ using System.Collections.Generic;
 
 public interface ISpotArea
 {
-    float Radius { get; }
+    float Radius { get; set; }
     public List<Vector2> Pixels0 { get; }       // 亮区,红外灯中心高亮部分
     public List<Vector2> Pixels1 { get; }       // 泛光区,红外灯边缘较暗的部分
-    Vector2 Centroid { get; }       // 中心坐标
+    Vector2 Centroid { get; set; }       // 中心坐标
 
-    float CalculateRadius();    // 手动计算半径
+    Vector2 CalculateCentroid();    // 手动计算中心点
+    float CalculateRadius();        // 手动计算半径
 }

+ 13 - 11
Assets/InfraredProject/WebCamera/Script/ZIM/InfraredLocate/InfraredSpot/PixelSpotArea.cs

@@ -104,35 +104,37 @@ namespace ZIM
         Vector2 centroid = default;       // 该项目里center不可能等于0,0
         public Vector2 Centroid
         {
+            set { centroid = value; }
             // 在添加完亮区之后可以调用
             get
             {
                 if (centroid != default)
                     return centroid;
-
-                foreach (var p in Pixels0)
-                {
-                    centroid += p;
-                }
-                return centroid /= Pixels0.Count;
+                return CalculateCentroid();
             }
         }
         float radius = 0;
         public float Radius
         {
-            set
-            {
-                radius = value;
-            }
+            set { radius = value; }
             get
             {
                 if (radius != 0)
                     return radius;
-
                 return CalculateRadius();
             }
         }
 
+        public Vector2 CalculateCentroid()
+        {
+            centroid = Vector2.zero;
+            foreach (var p in Pixels0)
+            {
+                centroid += p;
+            }
+            return centroid /= Pixels0.Count;
+        }
+
         public float CalculateRadius()
         {
             //var radiusDic = new Dictionary<int, float>() { { 0, 0 }, { 45, 0 }, { 90, 0 }, { 135, 0 }, { 180, 0 }, { 225, 0 }, { 270, 0 }, { 315, 0 } };

+ 17 - 14
Assets/InfraredProject/WebCamera/Script/ZIM/InfraredLocate/InfraredSpot/PixelSpotArea_DbScan.cs

@@ -16,37 +16,40 @@ namespace ZIM
     // 亮区的点用来定位(计算center),泛光区域的点用来计算radius
     public class PixelSpotArea_DbScan : ISpotArea
     {
-        // 中心
         Vector2 centroid = default;       // 该项目里center不可能等于0,0
         public Vector2 Centroid
         {
+            set { centroid = value; }
+            // 在添加完亮区之后可以调用
             get
             {
                 if (centroid != default)
                     return centroid;
-
-                foreach (var p in Pixels0)
-                    centroid += p;
-                return centroid /= Pixels0.Count;
+                return CalculateCentroid();
             }
         }
-
-        // 亮区的半径,计算含泛光点
         float radius = 0;
         public float Radius
         {
-            set
-            {
-                radius = value;
-            }
+            set { radius = value; }
             get
             {
                 if (radius != 0)
                     return radius;
-                
-                return CalculateRadius();       // 函数里会赋值 radius
+                return CalculateRadius();
             }
         }
+
+        public Vector2 CalculateCentroid()
+        {
+            centroid = Vector2.zero;
+            foreach (var p in Pixels0)
+            {
+                centroid += p;
+            }
+            return centroid /= Pixels0.Count;
+        }
+
         public float CalculateRadius()
         {
             //var radiusDic = new Dictionary<int, float>() { { 0, 0 }, { 45, 0 }, { 90, 0 }, { 135, 0 }, { 180, 0 }, { 225, 0 }, { 270, 0 }, { 315, 0 } };
@@ -80,7 +83,7 @@ namespace ZIM
         // 泛光
         public List<Vector2> Pixels1 { get; set; }
 
-        public PixelSpotArea_DbScan(IEnumerable<Vector2> points)        // kmeans中用随机点初始化,作为中心
+        public PixelSpotArea_DbScan(IEnumerable<Vector2> points)
         {
             Pixels0 = new List<Vector2>();
             Pixels1 = new List<Vector2>();

+ 2 - 2
Assets/InfraredProject/WebCamera/Script/ZIM/InfraredLocate/ScreenMap.cs

@@ -52,8 +52,8 @@ namespace ZIM.Unity
             if (QuadInCamera != null)
             {
                 var quad = QuadInCamera.Quad;
-                var x = Math.Min((quad.A - quad.B).Length, (quad.C - quad.D).Length);
-                var y = Math.Min((quad.A - quad.C).Length, (quad.B - quad.D).Length);
+                var x = ((quad.A - quad.B).Length + (quad.C - quad.D).Length) / 2;
+                var y = ((quad.A - quad.C).Length + (quad.B - quad.D).Length) / 2;
                 UVSize = new Vector2(x, y);
                 perspective = new ZIMPerspectiveTransform(quad, new OrdinalQuadrilateral(new Vector(0, 0), new Vector(x, 0), new Vector(0, y), new Vector(x, y)));