Ver Fonte

识别黑边功能应用到半自动识别

ZIM há 11 meses atrás
pai
commit
e1af30cca1

+ 52 - 33
Assets/InfraredProject/WebCamera/Script/ZIM/InfraredLocate/ScreenIdentification.cs

@@ -131,7 +131,7 @@ namespace o0.Project
                 areaSelected = -1;
                 quadTemp.Clear();
                 sumTemp.Clear();
-                ScreenLocate.Main.DebugScreenImages.Clear();
+                //ScreenLocate.Main.DebugScreenImages.Clear();
                 return;
             }
 
@@ -1003,8 +1003,7 @@ namespace o0.Project
                 var gM = ScreenGrad(line);
                 float e = (float)Math.Sqrt(Math.Ceiling(line.Line.Length / minLength));       // 长度系数,筛选时梯度更大、长度更长的线段更优
                 float d = (1.3f - distanceRatio) / 0.3f;             // 距离系数,距离越近,系数越大
-
-                line.ZIMGradient = e * d * gM;      // 记录一下综合梯度,全自动新增的功能会二次使用
+                line.ZIMGradient = e * d * gM;      // 记录一下综合梯度,新增的识别黑边功能会二次使用
                 return line.ZIMGradient;
             }
             // 根据线段梯度的角度,判断是不是屏幕的边,index代表是哪条边(顺序是: 下、右、上、左)
@@ -1037,6 +1036,7 @@ namespace o0.Project
             var quadLinesAuto = new List<(float, LineIdentified)>[4] { new List<(float, LineIdentified)>(), new List<(float, LineIdentified)>(), new List<(float, LineIdentified)>(), new List<(float, LineIdentified)>() };
             possibleLines = new List<LineIdentified>();
 
+            #region 半自动(利用手动数据)
             // 如果已有手动定位数据,根据现有数据筛选线条(半自动)
             manualLines = null;
             if (QuadManual != null)
@@ -1050,7 +1050,7 @@ namespace o0.Project
                 foreach (var line in innerLines)
                 {
                     // 筛选条件:1-梯度方向匹配,2-垂足的距离足够近, 3-线段的AB点均在旧线段外部, 4-新的线段的中点,到旧线段的垂足,要在旧线段内
-                    if (line.ScreenLineIndex >= 0) 
+                    if (line.ScreenLineIndex >= 0)
                     {
                         var distanceToOld = (o0Extension.PointPedal(line.Line, avgPoint, out _) - avgPointPedal[line.ScreenLineIndex]).Length;
                         if (distanceToOld < calibration &&
@@ -1067,7 +1067,23 @@ namespace o0.Project
                     }
                 }
             }
+            // 获得结果
+            var resultSemiAuto = new LineIdentified[4];
+            var resultSemiAutoPedal = new Vector[4];       // 用于找平行线
+            for (int i = 0; i < 4; i++)
+            {
+                resultSemiAuto[i] = quadLinesSemiAuto[i].Max((a, b) => a.Item1.CompareTo(b.Item1)).Item2;
+                if (resultSemiAuto[i] != null)
+                    resultSemiAutoPedal[i] = o0Extension.PointPedal(resultSemiAuto[i].Line, avgPoint, out _);
+            }
+            // 新增功能(解决黑边问题):根据 result 再找平行线,判断是否替换(1-在 result 内部,且离中点最近,2-接近平行)
+            UpdateResultlines(resultSemiAuto, FindInterLinePair(
+                (i) => true,
+                GetInterSelectableLines(quadLinesSemiAuto, resultSemiAuto, resultSemiAutoPedal, avgPoint)));
 
+            #endregion
+
+            #region 全自动
             // 全自动
             foreach (var line in innerLines)
             {
@@ -1076,57 +1092,60 @@ namespace o0.Project
                     quadLinesAuto[line.ScreenLineIndex].Add((estimateGradient(line, 1), line));
                 }
             }
-
-            // 获得半自动和全自动的结果
-            var resultSemiAuto = new LineIdentified[4];
+            // 获得结果
             var resultAuto = new LineIdentified[4];
-            var resultAutoPedal = new Vector[4];       // 用于找全自动的平行线
+            var resultAutoPedal = new Vector[4];       // 用于找平行线
             for (int i = 0; i < 4; i++)
             {
-                if (quadLinesSemiAuto[i].Count > 0)
-                    resultSemiAuto[i] = quadLinesSemiAuto[i].Max((a, b) => a.Item1.CompareTo(b.Item1)).Item2;
-                if (quadLinesAuto[i].Count > 0)
-                {
-                    resultAuto[i] = quadLinesAuto[i].Max((a, b) => a.Item1.CompareTo(b.Item1)).Item2;
-                    if (resultAuto[i] != null)
-                        resultAutoPedal[i] = o0Extension.PointPedal(resultAuto[i].Line, avgPoint, out _);
-                }
+                resultAuto[i] = quadLinesAuto[i].Max((a, b) => a.Item1.CompareTo(b.Item1)).Item2;
+                if (resultAuto[i] != null)
+                    resultAutoPedal[i] = o0Extension.PointPedal(resultAuto[i].Line, avgPoint, out _);
             }
+            // 新增功能(解决黑边问题):根据 resultAuto 再找平行线,判断是否替换(1-在 result 内部,且离中点最近,2-接近平行,3-LineGuess判断是直线)
+            UpdateResultlines(resultAuto, FindInterLinePair(
+                new LineGuess(screenLocateMatList, gradientLength * 2, minLength).GuessIsLine,
+                GetInterSelectableLines(quadLinesAuto, resultAuto, resultAutoPedal, avgPoint)));
+            #endregion
 
-            // 新增功能(全自动,为了解决黑边问题):根据 resultAuto 再找平行线,判断是否替换(1-在 resultAuto 内部,2-接近平行,3-LineGuess判断是直线)
-            // 半自动不增加这个功能,直接通过增加到手动数据的距离阈值来解决黑边问题
-            var interSelectable = new List<LineIdentified>();
-            foreach (var line in innerLines)
+            return (resultSemiAuto.ToList(), resultAuto.ToList());
+        }
+
+        List<LineIdentified> GetInterSelectableLines(List<(float, LineIdentified)>[] quadLines, LineIdentified[] resultLines, Vector[] resultPedal, Vector avgPoint)
+        {
+            var result = new List<LineIdentified>();
+            foreach (var ql in quadLines)
             {
-                if (line.ScreenLineIndex >= 0 && line.Batch < 1)
+                foreach (var (_, line) in ql)
                 {
-                    if (line != resultAuto[line.ScreenLineIndex])
+                    if (line != resultLines[line.ScreenLineIndex])
                     {
                         var pedal = o0Extension.PointPedal(line.Line, avgPoint, out _);
                         var a0 = pedal - avgPoint;
                         var a0L = a0.Length;
                         line.DistanceToMiddle = a0L;
-                        var a1 = resultAutoPedal[line.ScreenLineIndex] - avgPoint;
+                        var a1 = resultPedal[line.ScreenLineIndex] - avgPoint;
                         var a1L = a1.Length;
                         if (a0L < a1L)
                         {
                             var dotN = a0.Dot(a1) / a0L / a1L;
-                            if (Math.Abs(dotN - 1) < 0.001) // 接近平行即可
-                                interSelectable.Add(line);
+                            if (Math.Abs(dotN - 1) < 0.002) // 接近平行即可
+                                result.Add(line);
                         }
                     }
                 }
             }
-            var (interA, interB) = FindInterLinePair(new LineGuess(screenLocateMatList, gradientLength * 2, minLength), interSelectable, 8);
-            if (interA != null)   // 替换上一步筛选的结果中的部分边,得到最终的结果
-                resultAuto[interA.ScreenLineIndex] = interA;
-            if (interB != null)
-                resultAuto[interB.ScreenLineIndex] = interB;
+            return result;
+        }
 
-            return (resultSemiAuto.ToList(), resultAuto.ToList());
+        void UpdateResultlines(LineIdentified[] result, (LineIdentified a, LineIdentified b) inter)
+        {
+            if (inter.a != null)   // 替换上一步筛选的结果中的部分边,得到最终的结果
+                result[inter.a.ScreenLineIndex] = inter.a;
+            if (inter.b != null)
+                result[inter.b.ScreenLineIndex] = inter.b;
         }
 
-        (LineIdentified a, LineIdentified b) FindInterLinePair(LineGuess lineGuess, List<LineIdentified> interSelectable, int maxCountToSelect = 12)
+        (LineIdentified a, LineIdentified b) FindInterLinePair(Func<LineIdentified, bool> guessIsLine, List<LineIdentified> interSelectable, int maxCountToSelect = 8)
         {
             Debug.Log("[ScreenIdentification] selectable inter line count: " + interSelectable.Count);
             interSelectable.Sort((a, b) => b.ZIMGradient.CompareTo(a.ZIMGradient));
@@ -1134,7 +1153,7 @@ namespace o0.Project
             LineIdentified[] selected = new LineIdentified[4];
             foreach (var line in interSelectable)
             {
-                if (lineGuess.GuessIsLine(line))        // 评价是不是Line, 并且找到离中心点最近的
+                if (guessIsLine(line))        // 评价是不是Line, 并且找到离中心点最近的
                 {
                     if (ScreenLocate.Main.DebugOnZIMDemo)
                         Debug.Log($"[ScreenIdentification] {interSelectable.IndexOf(line)}, guess is line: (index)" + line.ScreenLineIndex);

+ 1 - 1
Assets/InfraredProject/WebCamera/Script/ZIM/ScreenLocate.cs

@@ -795,7 +795,7 @@ public partial class ScreenLocate : MonoBehaviour
     {
         if (DebugScreenImages.Count != 0)
         {
-            screenIdentification = new o0.Project.ScreenIdentification();
+            //screenIdentification = new o0.Project.ScreenIdentification();
             CameraSize = new o0.Geometry2D.Vector<int>(DebugScreenImages[0].width, DebugScreenImages[0].height);
             WebCamIsReady(DebugScreenImages[0]);
 

+ 8 - 4
Assets/SmartBow/Scripts/Views/InfraredViewParts/InfraredScreenPositioningView.cs

@@ -298,12 +298,16 @@ public class InfraredScreenPositioningView : JCUnityLib.ViewBase
         pointsParent.gameObject.SetActive(true);
         if (ScreenLocate.Main) {
             ZIM.Unity.QuadrilateralInCamera screen = ScreenLocate.Main.ScreenIdentification.Screen.QuadInCamera;
-            //设置points点
-            for (int i = 0; i < 4; i++)
+            if (screen != null) 
             {
-                RectTransform t = pointsParent.GetChild(i) as RectTransform;
-                t.anchoredPosition = screen.Quad[i].pixelToLocalPosition_AnchorCenter(screen.CameraSize, pointsParent.rect);
+                //设置points点
+                for (int i = 0; i < 4; i++)
+                {
+                    RectTransform t = pointsParent.GetChild(i) as RectTransform;
+                    t.anchoredPosition = screen.Quad[i].pixelToLocalPosition_AnchorCenter(screen.CameraSize, pointsParent.rect);
+                }
             }
+
         }