| 
					
				 | 
			
			
				@@ -9,6 +9,7 @@ using System.Linq; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 using System.Threading.Tasks; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 using UnityEngine; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 using UnityEngine.UIElements; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+using UnityStandardAssets.Utility; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 using ZIM; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 using ZIM.Unity; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -144,6 +145,9 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //bStartLocateScreen = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ScreenWhiteTexture = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            ScreenBlackTexture = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             OnLocateScreenEnter?.Invoke(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <summary> 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -667,15 +671,18 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // 屏幕黑白差值,存放多批次的图像用于识别, 该List数量不能等于 0  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             List<UnityEngine.Color[]> PixelsMultipleBatches = new List<UnityEngine.Color[]>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            var sw = new System.Diagnostics.Stopwatch(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            sw.Start(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //var sw = new System.Diagnostics.Stopwatch(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            //sw.Start(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //读取数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (debugImages != null && debugImages.Count != 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var dSize = debugImages.First().Size(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 foreach (var i in debugImages) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     Debug.Log($"<color=aqua>Debug {i.name}</color>"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (i.Size() != dSize) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        throw new InvalidOperationException("Multiple Debug textures have different sizes"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     PixelsMultipleBatches.Add(i.GetPixels()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -698,8 +705,8 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     for (int y = 0; y < Size.y; y++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         var i = y * Size.x + x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        var d = ScreenWhiteTexture[i] - ScreenBlackTexture[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        differPixel[i] = new UnityEngine.Color(d.x, d.y, d.z) * scale; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        var d = ScreenWhiteTexture[i] * scale - ScreenBlackTexture[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        differPixel[i] = new UnityEngine.Color(d.x, d.y, d.z); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         whitePixel[i] = new UnityEngine.Color(ScreenWhiteTexture[i].x, ScreenWhiteTexture[i].y, ScreenWhiteTexture[i].z) * scale; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 }); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -710,8 +717,8 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             int conSize = (int)Math.Ceiling(0.007f * Size.y) * 2 + 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             conSize = Math.Max(conSize, 7);     // 设置最小为7 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            float minLength = conSize * 7.7f; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            minLength = locateIndex == -1 ? minLength : minLength * areaPercent;    // minLength需要按比例缩小 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            float minLength = conSize * 6f; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            minLength = locateIndex == -1 ? minLength : minLength * areaPercent;    // minLength需要按areaPercent比例缩小 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             string log = $"[Log][ScreenLocate Auto] Size: ({Size.x},{Size.y}), 卷积核Size: {conSize}, 最小线段长度: {minLength}"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var allLines = new List<LineIdentified>(); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -722,20 +729,47 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 var locateTex = ToLocateTex(PixelsMultipleBatches[batch]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 LocateTexTemp.Add(locateTex); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 var ScreenLocateMat = locateTex.Too0Mat();        // 用于获取Lines的Matrix 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                var lineCount = ZIMIdentifyQuadLSD(ref allLines, batch, ScreenLocateMat.zimIdentifyEdgeGradientAny(conSize), minLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var lineCount = ZIMIdentifyQuadLSD( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    ref allLines, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    batch, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    ScreenLocateMat.zimIdentifyEdgeGradientAny(conSize), 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    minLength, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    new Vector(minLength * 0.4f, conSize * 1.6f)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 log += $"\r\n识别图片{batch}, 识别到的线段数量为: {lineCount}"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 ScreenLocateMatList.Add(ScreenLocateMat); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             Texture2D ScreenLocateTexture = LocateTexTemp[0];       // for output 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // LSD计算得到的矩阵尺寸较小(因为卷积),这里必须进行位移 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 新增:根据阈值筛去梯度太低的线段 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            float minGradient = 0.09f; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var offset = new Vector((conSize - 1) / 2, (conSize - 1) / 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var tempList = new List<LineIdentified>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            for (int i = 0; i < allLines.Count; i++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var l = allLines[i]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (l.Gradient > minGradient * l.Line.Length)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    l.Offset(offset); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    tempList.Add(l); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            allLines = tempList; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            log += $"\r\n根据梯度阈值筛选,最终线段数量为: {allLines.Count}"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // 如果有手动数据,刷新一下Size 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             QuadManual?.ReSize(new Vector(Size.x, Size.y), ScreenMap.ViewAspectRatioSetting); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // 估算屏幕中点,如果已有手动定位数据,根据现有数据取平均即可,否则从色差计算,ScreenLocateMatList[0]默认是屏幕的黑白色差 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             Vector AvgPoint = QuadManual != null ? QuadManual.Quad.Centroid : GetAvgPoint(ScreenLocateMatList[0]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // 过滤得到四边形的四条边, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            var (quadLinesSemiAuto, quadLinesAuto) = FilterLines(ScreenLocateMatList, allLines, AvgPoint, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                out LineIdentified[] manualLines, out List<LineIdentified> possibleLines, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                conSize, conSize, minLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var (quadLinesSemiAuto, quadLinesAuto) = FilterLines( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                ScreenLocateMatList,  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                allLines,  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                AvgPoint, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                out LineIdentified[] manualLines,  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                out List<LineIdentified> possibleLines, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                conSize,  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                minLength); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             #region 全自动识别的结果 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             List<LineIdentified> LineIdentifiedAuto = new List<LineIdentified>();               // 线段顺序: 下、右、上、左 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -808,7 +842,7 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     o0Extension.DrawLine(ScreenQuadMap, LineIdentifiedSemiAuto[i].DrawLine, (x, y) => 5, new Geometry2D.Float.Vector(0, 10)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     o0Extension.DrawLine(ScreenQuadMap, LineIdentifiedSemiAuto[i].DrawLine, (x, y) => 3, new Geometry2D.Float.Vector(0, 6), true); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            }  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // 绘制全自动 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             foreach (var i in LineIdentifiedAuto.Index()) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -910,9 +944,9 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // 返回查找到的线段数量,0是查找失败 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         int ZIMIdentifyQuadLSD(ref List<LineIdentified> allLines, int batch, (Matrix edgeMat, Matrix edgeDirMat) edgeGradient, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            float minLength = 100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            float minLength, Vector LineCaptureSize) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            var l = edgeGradient.edgeMat.IdentifyLineLSD(edgeGradient.edgeDirMat, minLength, 50, LineCaptureSize: new Vector(10, 6)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var l = edgeGradient.edgeMat.IdentifyLineLSD(edgeGradient.edgeDirMat, minLength, 25, LineCaptureSize); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (l == null || l.Count == 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 return 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             allLines.AddRange(l.Select((i) => new LineIdentified(batch, i))); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -921,14 +955,8 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         // 返回四边形的四条边(半自动、全自动),List长度一定是4 (如果没有识别到就是null),且线段顺序是: 下、右、上、左 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         (List<LineIdentified>, List<LineIdentified>) FilterLines(List<Matrix> screenLocateMatList, List<LineIdentified> allLines, Vector avgPoint, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            out LineIdentified[] manualLines, out List<LineIdentified> possibleLines, float conSize, float gradientLength, float minLength = 100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            out LineIdentified[] manualLines, out List<LineIdentified> possibleLines, float gradientLength, float minLength = 100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            //Debug.Log("[IdentifyLineLSD] lines.Count: " + lines.Count); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            var offset = new Vector((conSize - 1) / 2, (conSize - 1) / 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            // LSD计算得到的矩阵尺寸较小(因为卷积),这里必须进行位移 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            for (int i = 0; i < allLines.Count; i++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                allLines[i].Offset(offset); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // 筛掉椭圆框外的线段(超出一半会筛掉) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var innerLines = new List<LineIdentified>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             for (int i = 0; i < allLines.Count; i++) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -955,12 +983,12 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // 角度阈值,用来判断线段的梯度方向是否指向屏幕中心(avgPoint) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var avaAngleHalf = 75f; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            // 沿直线计算综合梯度(梯度乘以长度系数,再乘以距离系数), distanceRatio是实际距离除以最大距离 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            float estimateGradient(LineIdentified line, float distanceRatio) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            #region 内部函数 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            float ScreenGrad(LineIdentified line) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 var dir = (line.Line.B - line.Line.A).Normalized; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 var vertical = new Vector(-dir.y, dir.x) * (gradientLength / 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                var step = 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                int step = (int)(minLength / 5); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 var ll = line.Line.Length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 var lg = new List<float>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 for (int i = 0; i <= ll; i += step) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -970,17 +998,24 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     var gb = point - vertical; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     lg.Add(screenLocateMatList[line.Batch][(int)ga.x, (int)ga.y] - screenLocateMatList[line.Batch][(int)gb.x, (int)gb.y]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return Math.Abs(lg.Mean()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 沿直线计算综合梯度(梯度乘以长度系数,再乘以距离系数), distanceRatio是实际距离除以最大距离 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            float estimateGradient(LineIdentified line, float distanceRatio) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var gM = ScreenGrad(line); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 float e = (float)Math.Sqrt(Math.Ceiling(line.Line.Length / minLength));       // 长度系数,筛选时梯度更大、长度更长的线段更优 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                float d = (3 - distanceRatio) / 2;            // 距离系数,距离越近,系数越大 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                return e * d * Math.Abs(lg.Mean()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                float d = (5 - distanceRatio) / 4;             // 距离系数,距离越近,系数越大 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                line.ZIMGradient = e * d * gM;      // 记录一下综合梯度,全自动新增的功能会二次使用 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return line.ZIMGradient; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            // 根据线段梯度的角度,判断是不是屏幕的边,out index代表是哪条边(顺序是: 下、右、上、左) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            bool isScreenLine(LineIdentified line, out int index) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 根据线段梯度的角度,判断是不是屏幕的边,index代表是哪条边(顺序是: 下、右、上、左) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            void GetScreenLineIndex(LineIdentified line) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 var a = (avgPoint - (line.Line.A + line.Line.B) / 2).DegreeToXAxis(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 //Debug.Log(a + ", " + gradient + ", " + sum); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                index = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var index = -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (Math.Abs(a - line.GradientDegree) < avaAngleHalf || Math.Abs(a - 360 - line.GradientDegree) < avaAngleHalf || Math.Abs(a + 360 - line.GradientDegree) < avaAngleHalf) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     if (line.GradientDegree > 45 && line.GradientDegree < 135)     // 下 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -991,11 +1026,14 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         index = 2; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         index = 3; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                line.ScreenLineIndex = index; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            #endregion 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 根据梯度方向,判断是哪条边 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            foreach (var l in innerLines) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                GetScreenLineIndex(l); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // 下、右、上、左, 半自动和自动 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var quadLinesSemiAuto = new List<(float, LineIdentified)>[4] { new List<(float, LineIdentified)>(), new List<(float, LineIdentified)>(), new List<(float, LineIdentified)>(), new List<(float, LineIdentified)>() }; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1015,17 +1053,17 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 foreach (var line in innerLines) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     // 筛选条件:1-梯度方向匹配,2-垂足的距离足够近, 3-线段的AB点均在旧线段外部, 4-新的线段的中点,到旧线段的垂足,要在旧线段内 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if (isScreenLine(line, out int index)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (line.ScreenLineIndex >= 0)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        var distanceToOld = (o0Extension.PointPedal(line.Line, avgPoint, out _) - avgPointPedal[index]).Length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        var distanceToOld = (o0Extension.PointPedal(line.Line, avgPoint, out _) - avgPointPedal[line.ScreenLineIndex]).Length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         if (distanceToOld < calibration && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            manualLines[index].Line.LineCrossWithPoint(line.Line.A) * avgPointCross[index] <= 0 && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            manualLines[index].Line.LineCrossWithPoint(line.Line.B) * avgPointCross[index] <= 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            manualLines[line.ScreenLineIndex].Line.LineCrossWithPoint(line.Line.A) * avgPointCross[line.ScreenLineIndex] <= 0 && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            manualLines[line.ScreenLineIndex].Line.LineCrossWithPoint(line.Line.B) * avgPointCross[line.ScreenLineIndex] <= 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                            var middleToOldLine = o0Extension.PointPedal(manualLines[index].Line, (line.Line.A + line.Line.B) / 2, out bool inLineSegment); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            var middleToOldLine = o0Extension.PointPedal(manualLines[line.ScreenLineIndex].Line, (line.Line.A + line.Line.B) / 2, out bool inLineSegment); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             if (inLineSegment) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                                quadLinesSemiAuto[index].Add((estimateGradient(line, distanceToOld / calibration), line)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                quadLinesSemiAuto[line.ScreenLineIndex].Add((estimateGradient(line, distanceToOld / calibration), line)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                                 possibleLines.Add(line); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         } 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1034,29 +1072,96 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // 全自动 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            foreach (var line in allLines) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            foreach (var line in innerLines) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (isScreenLine(line, out int index)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (line.ScreenLineIndex >= 0 && line.Batch < 1)    // 全自动只处理第一张图,默认是色差图 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if (line.Batch < 1)     // 全自动只处理第一张图,默认是色差图 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        quadLinesAuto[index].Add((estimateGradient(line, 1), line)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    quadLinesAuto[line.ScreenLineIndex].Add((estimateGradient(line, 1), line)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 获得半自动和全自动的结果 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var resultSemiAuto = new LineIdentified[4]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var resultAuto = new LineIdentified[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 再找平行线,判断是否替换(1-在 resultAuto 内部,2-接近平行,3-LineGuess判断是直线) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            // 半自动不增加这个功能,直接通过增加到手动数据的距离阈值来解决黑边问题 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var interSelectable = new List<LineIdentified>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            foreach (var line in innerLines) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (line.ScreenLineIndex >= 0 && line.Batch < 1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (line != resultAuto[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 a1L = a1.Length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (a0L < a1L) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            var dotN = a0.Dot(a1) / a0L / a1L; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            if (Math.Abs(dotN - 1) < 0.001) // 接近平行即可 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                                interSelectable.Add(line); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            var (interA, interB) = FindInterLinePair(new LineGuess(screenLocateMatList, gradientLength * 2, minLength), interSelectable, 12); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (interA != null && interB != null)   // 替换上一步筛选的结果中的一对边,得到最终的结果 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                resultAuto[interA.ScreenLineIndex] = interA; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                resultAuto[interB.ScreenLineIndex] = interB; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return (resultSemiAuto.ToList(), resultAuto.ToList()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        (LineIdentified a, LineIdentified b) FindInterLinePair(LineGuess lineGuess, List<LineIdentified> interSelectable, int maxCountToSelect = 12) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            Debug.Log("[ScreenIdentification] selectable inter line count: " + interSelectable.Count); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            interSelectable.Sort((a, b) => b.ZIMGradient.CompareTo(a.ZIMGradient)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            int count = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            LineIdentified[] selected = new LineIdentified[4]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            foreach (var line in interSelectable) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (lineGuess.GuessIsLine(line))        // 评价是不是Line, 并且找到离中心点最近的 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    Debug.Log("[ScreenIdentification] guess is line: (index)" + line.ScreenLineIndex); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    if (selected[line.ScreenLineIndex] == null || selected[line.ScreenLineIndex].DistanceToMiddle > line.DistanceToMiddle) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        selected[line.ScreenLineIndex] = line; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (count++ >= maxCountToSelect) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    break; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (selected[0] != null && selected[1] != null && selected[2] != null && selected[3] != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (selected[0].ZIMGradient + selected[2].ZIMGradient > selected[1].ZIMGradient + selected[3].ZIMGradient) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return (selected[0], selected[2]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    return (selected[1], selected[3]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else if (selected[0] != null && selected[2] != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return (selected[0], selected[2]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else if (selected[1] != null && selected[3] != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return (selected[1], selected[3]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                return (null, null); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         void SaveImages(string FileDirectory, string log, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             Texture2D ScreenLocateTex, Texture2D allLinesTex, Texture2D ChoosableLineTex, Texture2D ScreenQuadTex) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 |