| 
					
				 | 
			
			
				@@ -131,7 +131,7 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 areaSelected = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 quadTemp.Clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 sumTemp.Clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                ScreenLocate.Main.DebugScreenImages.Clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //ScreenLocate.Main.DebugScreenImages.Clear(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 return; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1009,8 +1009,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代表是哪条边(顺序是: 下、右、上、左) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1043,6 +1042,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) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1056,7 +1056,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 && 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1073,7 +1073,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) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1082,57 +1098,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)); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1140,7 +1159,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); 
			 |