| 
					
				 | 
			
			
				@@ -87,6 +87,9 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         public void SetScreenQuad(QuadrilateralInCamera quad) => Screen.QuadInCamera = quad; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        // 上一次半自动识别的情况,false代表这条边识别失败,线段顺序: 下、右、上、左 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        public bool[] LastQuadSemiAutoState; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         public event Action OnLocateScreenEnter; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         public event Action OnLocateScreenEnd; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         public bool bStartLocateScreen { get; set; } = false;//是否进行捕获 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -146,7 +149,8 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// 初始化了两个数据 capture 和 delay 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// </summary> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         /// <returns></returns> 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        public bool isInitLocateScreen() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        public bool isInitLocateScreen() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return capture != 0 && delay != 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -167,28 +171,28 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     new QuadrilateralInCamera(quad, images[0].Size().o0Vector())); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 // 透视变换 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                var srcWidth = LocateLightedRedTex.width; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                var transformWidth = (int)((quad.B.x - quad.A.x + quad.D.x - quad.C.x) / 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                var transformHeight = (int)((quad.C.y - quad.A.y + quad.D.y - quad.B.y) / 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                var transformTex = new Texture2D(transformWidth, transformHeight); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                var pt = new ZIMPerspectiveTransform(new OrdinalQuadrilateral(new Vector(0, 0), new Vector(transformWidth, 0), new Vector(0, transformHeight), new Vector(transformWidth, transformHeight)), quad); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                var dstPixel = new UnityEngine.Color[transformWidth * transformHeight]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                var srcPixel = LocateLightedRedTex.GetPixels(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                Parallel.For(0, transformWidth, (x) => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                    for (int y = 0; y < transformHeight; y++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                        var index = y * transformWidth + x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                        var sampleCoord = pt.TransformRound(x, y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                        dstPixel[index] = srcPixel[sampleCoord.y * srcWidth + sampleCoord.x]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                transformTex.SetPixels(dstPixel); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                transformTex.Apply(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                //ScreenLocate.DebugTexture(1, transformTex); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//#if (!NDEBUG && DEBUG && ENABLE_LOG) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//                Console.WriteLine($"{TAG} ScreenLocate.DebugTexture 1:{transformTex.GetNativeTexturePtr()}"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-//#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                var srcWidth = LocateLightedRedTex.width; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                var transformWidth = (int)((quad.B.x - quad.A.x + quad.D.x - quad.C.x) / 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                var transformHeight = (int)((quad.C.y - quad.A.y + quad.D.y - quad.B.y) / 2); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                var transformTex = new Texture2D(transformWidth, transformHeight); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                var pt = new ZIMPerspectiveTransform(new OrdinalQuadrilateral(new Vector(0, 0), new Vector(transformWidth, 0), new Vector(0, transformHeight), new Vector(transformWidth, transformHeight)), quad); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                var dstPixel = new UnityEngine.Color[transformWidth * transformHeight]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                var srcPixel = LocateLightedRedTex.GetPixels(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                Parallel.For(0, transformWidth, (x) => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                    for (int y = 0; y < transformHeight; y++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                    { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                        var index = y * transformWidth + x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                        var sampleCoord = pt.TransformRound(x, y); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                        dstPixel[index] = srcPixel[sampleCoord.y * srcWidth + sampleCoord.x]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                }); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                transformTex.SetPixels(dstPixel); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                transformTex.Apply(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                //ScreenLocate.DebugTexture(1, transformTex); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //#if (!NDEBUG && DEBUG && ENABLE_LOG) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //                Console.WriteLine($"{TAG} ScreenLocate.DebugTexture 1:{transformTex.GetNativeTexturePtr()}"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                //#endif 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //times.Add(watch.ElapsedMilliseconds); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -669,7 +673,7 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             sw.Start(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             //读取数据 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (debugImages != null && debugImages.Count != 0)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (debugImages != null && debugImages.Count != 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 foreach (var i in debugImages) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -693,7 +697,7 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 var whitePixel = new UnityEngine.Color[Size.x * Size.y]; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 Parallel.For(0, Size.x, x => 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    for (int y = 0; y < Size.y; y++)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    for (int y = 0; y < Size.y; y++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         var i = y * Size.x + x; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         var d = ScreenWhiteTexture[i] - ScreenBlackTexture[i]; 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -754,7 +758,7 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             #region 半自动识别 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             List<LineIdentified> LineIdentifiedSemiAuto = new List<LineIdentified>();               // 线段顺序: 下、右、上、左 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            bool[] newLines = new bool[4] { true, true, true, true }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            LastQuadSemiAutoState = new bool[4] { true, true, true, true }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             for (int i = 0; i < 4; i++) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 if (quadLinesSemiAuto[i] != null) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -762,7 +766,7 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 else if (manualLines != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     LineIdentifiedSemiAuto.Add(manualLines[i]); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    newLines[i] = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    LastQuadSemiAutoState[i] = false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -788,7 +792,8 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 Debug.Log("<color=aqua>[ScreenIdentification] 识别到四边形</color>"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 quadTemp.Add(QuadSemiAuto.Quad); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            }else if (QuadAuto != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            else if (QuadAuto != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 Debug.Log("<color=aqua>[ScreenIdentification] 识别到四边形</color>"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 quadTemp.Add(QuadAuto.Quad); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -799,7 +804,7 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var ScreenQuadMap = new Matrix(Size, Tiling: true);     // 识别的到的屏幕四边形(半自动和自动在一张图上)  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             foreach (var i in LineIdentifiedSemiAuto.Index()) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (newLines[i]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (LastQuadSemiAutoState[i]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     o0Extension.DrawLine(ScreenQuadMap, LineIdentifiedSemiAuto[i].DrawLine, (x, y) => 2, new Geometry2D.Float.Vector(0, 10)); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 else 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     o0Extension.DrawLine(ScreenQuadMap, LineIdentifiedSemiAuto[i].DrawLine, (x, y) => 1, new Geometry2D.Float.Vector(0, 6), true); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -845,7 +850,7 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             log += $"\r\n屏幕四边形_手动识别{QuadManual != null}\r\n屏幕四边形_半自动识别{QuadSemiAuto != null}\r\n屏幕四边形_全自动识别{QuadAuto != null}"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             Debug.Log(log); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // 是否将图片保存到本地 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if (ScreenLocate.Main.SaveToggle.isOn && ScreenLocate.Main.DebugOnZIMDemo) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            if (ScreenLocate.Main.SaveToggle?.isOn ?? false && ScreenLocate.Main.DebugOnZIMDemo) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 var FileDirectory = $"Debug_屏幕定位/"; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 SaveImages(FileDirectory, log, ScreenLocateTexture, allLinesTex, ChoosableLineTex, ScreenQuad); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -996,24 +1001,26 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             var quadLinesSemiAuto = new List<(float, LineIdentified)>[4] { new List<(float, LineIdentified)>(), new List<(float, LineIdentified)>(), new List<(float, LineIdentified)>(), new List<(float, LineIdentified)>() }; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             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>(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            manualLines = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // 如果已有手动定位数据,根据现有数据筛选线条(半自动) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            manualLines = null; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (QuadManual != null) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 Debug.Log("[IdentifyLineLSD] 根据已有定位数据做筛选"); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                var calibration = ScreenLocate.Main.ReDoLocateCalibrationRatio * Size.y; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 manualLines = QuadManual.GetLines().Select((i) => new LineIdentified(0, i, 0, 0, true)).ToArray(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                var pedals = manualLines.Select((i) => o0Extension.PointPedal(i.Line, avgPoint, out _)).ToArray();     // 当前定位的垂足,下、右、上、左 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var calibration = ScreenLocate.Main.ReDoLocateCalibrationRatio * Size.y; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var avgPointCross = manualLines.Select((i) => i.Line.LineCrossWithPoint(avgPoint)).ToArray();     // 对于平均点的corss值 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                var avgPointPedal = manualLines.Select((i) => o0Extension.PointPedal(i.Line, avgPoint, out _)).ToArray();     // 当前定位的垂足,下、右、上、左 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 foreach (var line in innerLines) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    // 筛选条件:1-梯度方向匹配,2-垂足的距离足够近, 3-新的线段的中点,到旧线段的垂足,要在旧线段内 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                    // 筛选条件:1-梯度方向匹配,2-垂足的距离足够近, 3-线段的AB点均在旧线段外部, 4-新的线段的中点,到旧线段的垂足,要在旧线段内 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     if (isScreenLine(line, out int index)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        var distanceToOld = (o0Extension.PointPedal(line.Line, avgPoint, out _) - pedals[index]).Length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        if (distanceToOld < calibration) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        var distanceToOld = (o0Extension.PointPedal(line.Line, avgPoint, out _) - avgPointPedal[index]).Length; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                        if (distanceToOld < calibration && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            manualLines[index].Line.LineCrossWithPoint(line.Line.A) * avgPointCross[index] <= 0 && 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                            manualLines[index].Line.LineCrossWithPoint(line.Line.B) * avgPointCross[index] <= 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             var middleToOldLine = o0Extension.PointPedal(manualLines[index].Line, (line.Line.A + line.Line.B) / 2, out bool inLineSegment); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                             if (inLineSegment) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1029,7 +1036,7 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             // 全自动 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             foreach (var line in allLines) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                if (isScreenLine(line , out int index)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+                if (isScreenLine(line, out int index)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     if (line.Batch < 1)     // 全自动只处理第一张图,默认是色差图 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                     { 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1050,7 +1057,7 @@ namespace o0.Project 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return (resultSemiAuto.ToList(), resultAuto.ToList()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        void SaveImages(string FileDirectory, string log,  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        void SaveImages(string FileDirectory, string log, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             Texture2D ScreenLocateTex, Texture2D allLinesTex, Texture2D ChoosableLineTex, Texture2D ScreenQuadTex) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             if (!Directory.Exists(FileDirectory)) 
			 |