ScreenIdentification.cs 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. using o0.Geometry;
  2. using o0.Geometry2D.Float;
  3. using Org.BouncyCastle.Utilities;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. using UnityEngine;
  11. using UnityEngine.UI;
  12. using ZIM;
  13. using ZIM.Unity;
  14. namespace o0.Project
  15. {
  16. public partial class ScreenIdentification
  17. {
  18. //static Rect[][] LocateAreaData = new Rect[][] {
  19. // new Rect[] { new Rect(0f, 0f, 0.3f, 0.3f), new Rect(0f, 0f, 0.4f, 0.4f), new Rect(0f, 0f, 0.5f, 0.5f), new Rect(0f, 0f, 0.6f, 0.6f) },
  20. // new Rect[] { new Rect(0.7f, 0f, 0.3f, 0.3f), new Rect(0.6f, 0f, 0.4f, 0.4f), new Rect(0.5f, 0f, 0.5f, 0.5f), new Rect(0.4f, 0f, 0.6f, 0.6f) },
  21. // new Rect[] { new Rect(0f, 0.7f, 0.3f, 0.3f), new Rect(0f, 0.6f, 0.4f, 0.4f), new Rect(0f, 0.5f, 0.5f, 0.5f), new Rect(0f, 0.4f, 0.6f, 0.6f) },
  22. // new Rect[] { new Rect(0.7f, 0.7f, 0.3f, 0.3f), new Rect(0.6f, 0.6f, 0.4f, 0.4f), new Rect(0.5f, 0.5f, 0.5f, 0.5f), new Rect(0.4f, 0.4f, 0.6f, 0.6f) }
  23. //};
  24. static Rect[][] LocateAreaData = new Rect[][] {
  25. new Rect[] { new Rect(0f, 0f, 0.3f, 0.3f), new Rect(0f, 0f, 0.4f, 0.4f), new Rect(0f, 0f, 0.5f, 0.5f) },
  26. new Rect[] { new Rect(0.7f, 0f, 0.3f, 0.3f), new Rect(0.6f, 0f, 0.4f, 0.4f), new Rect(0.5f, 0f, 0.5f, 0.5f) },
  27. new Rect[] { new Rect(0f, 0.7f, 0.3f, 0.3f), new Rect(0f, 0.6f, 0.4f, 0.4f), new Rect(0f, 0.5f, 0.5f, 0.5f) },
  28. new Rect[] { new Rect(0.7f, 0.7f, 0.3f, 0.3f), new Rect(0.6f, 0.6f, 0.4f, 0.4f), new Rect(0.5f, 0.5f, 0.5f, 0.5f) }
  29. };
  30. //static bool LocateDebug = false;
  31. static bool LocateDebug = true;
  32. public Geometry2D.Vector<int> Size { get; private set; }
  33. public ScreenMap Screen; // 识别到的屏幕,用于执行透视变换
  34. int capture = 0;
  35. int delay = 0;
  36. int maxCapture;
  37. int maxDelay;
  38. Geometry.Vector<float>[] ScreenBlackTexture;
  39. Geometry.Vector<float>[] ScreenWhiteTexture;
  40. int locateIndex = -1;
  41. List<Rect> locateArea = new List<Rect> {
  42. new Rect(0f, 0f, 0.5f, 0.5f), new Rect(0.5f, 0f, 0.5f, 0.5f), new Rect(0f, 0.5f, 0.5f, 0.5f), new Rect(0.5f, 0.5f, 0.5f, 0.5f)
  43. }; // 屏幕显示白色的区域大小
  44. float areaPercent => locateArea[locateIndex].size.x; // 当前白色区域的占比
  45. int areaSelected = -1; // 选择哪个区域,顺序与Quadrilateral对应
  46. List<float> sumTemp = new List<float>();
  47. List<Quadrilateral> quadTemp = new List<Quadrilateral>();
  48. public ScreenIdentification(WebCamTexture texture)
  49. {
  50. Size = new Geometry2D.Vector<int>(texture.width, texture.height);
  51. Screen = new ScreenMap();
  52. }
  53. public ScreenIdentification(Geometry2D.Vector<int> size)
  54. {
  55. Size = size;
  56. Screen = new ScreenMap();
  57. }
  58. public void LocateScreenManual(Quadrilateral quad) => Screen.Quad = quad;
  59. public void LocateScreen(int Capture = 30, int Delay = 30)//frame
  60. {
  61. if (ScreenLocate.Main.DebugScreenImage != null) // 测试图片
  62. {
  63. DebugImage(ScreenLocate.Main.DebugScreenImage);
  64. return;
  65. }
  66. delay = Delay;
  67. capture = Capture;
  68. maxDelay = Delay;
  69. maxCapture = Capture;
  70. ScreenLocate.SetScreen(new Rect(0f, 0f, 1f, 1f), UnityEngine.Color.black);
  71. //ScreenLocate.SetScreen(new Rect(0f, 0f, 0.6f, 0.6f), UnityEngine.Color.white);
  72. }
  73. void DebugImage(Texture2D image)
  74. {
  75. QuadrilateralFit(out Texture2D LocateTex, out Texture2D DrawLineTex, image);
  76. ScreenLocate.DebugTexture(2, LocateTex);
  77. ScreenLocate.DebugTexture(3, DrawLineTex);
  78. //Debug.Log(quadTemp[0]);
  79. //var watch = new System.Diagnostics.Stopwatch();
  80. //watch.Start();
  81. //var times = new List<double>() { 0.0 };
  82. // 透视变换
  83. var quad = quadTemp[0];
  84. var srcWidth = LocateTex.width;
  85. var transformWidth = (int)((quad.B.x - quad.A.x + quad.D.x - quad.C.x) / 2);
  86. var transformHeight = (int)((quad.C.y - quad.A.y + quad.D.y - quad.B.y) / 2);
  87. var transformTex = new Texture2D(transformWidth, transformHeight);
  88. var pt = new PerspectiveTransform(new Quadrilateral(new Vector(0, 0), new Vector(transformWidth, 0), new Vector(0, transformHeight), new Vector(transformWidth, transformHeight)), quad);
  89. var dstPixel = new UnityEngine.Color[transformWidth * transformHeight];
  90. var srcPixel = LocateTex.GetPixels();
  91. Parallel.For(0, transformWidth, (x) =>
  92. {
  93. for (int y = 0; y < transformHeight; y++)
  94. {
  95. var index = y * transformWidth + x;
  96. var sampleCoord = pt.TransformRound(x, y);
  97. dstPixel[index] = srcPixel[sampleCoord.y * srcWidth + sampleCoord.x];
  98. }
  99. });
  100. transformTex.SetPixels(dstPixel);
  101. transformTex.Apply();
  102. ScreenLocate.DebugTexture(1, transformTex);
  103. //times.Add(watch.ElapsedMilliseconds);
  104. //UnityEngine.Debug.Log("time: " + (times[times.Count - 1] - times[times.Count - 2]));
  105. }
  106. public void NextScreen()
  107. {
  108. // 测试用
  109. if (LocateDebug && areaSelected == -1)
  110. {
  111. LocateAreaData = new Rect[][] { new Rect[] { new Rect(0, 0, 1f, 1f) } };
  112. locateIndex = 3;
  113. areaSelected = 0;
  114. locateArea.AddRange(LocateAreaData[0]);
  115. }
  116. // index从-1开始
  117. locateIndex++;
  118. if (locateIndex < locateArea.Count) // 依次点亮屏幕区域
  119. {
  120. ScreenLocate.SetScreen(locateArea[locateIndex], UnityEngine.Color.white);
  121. delay = maxDelay;
  122. capture = maxCapture;
  123. }
  124. else // 退出屏幕黑白控制
  125. {
  126. ScreenLocate.SetScreen(null);
  127. ScreenLocate.Main.ShowScreen(Screen.Quad);
  128. Reset();
  129. }
  130. }
  131. void Reset()
  132. {
  133. delay = 0;
  134. capture = 0;
  135. ScreenWhiteTexture = null;
  136. ScreenBlackTexture = null;
  137. locateIndex = -1;
  138. areaSelected = -1;
  139. locateArea.RemoveRange(4, LocateAreaData[0].Length);
  140. quadTemp.Clear();
  141. sumTemp.Clear();
  142. }
  143. public void CaptureBlack(WebCamTexture cam)
  144. {
  145. if (ScreenBlackTexture == null)
  146. ScreenBlackTexture = new Geometry.Vector<float>[Size.x * Size.y];
  147. var pixel = cam.GetPixels();
  148. Parallel.For(0, Size.x * Size.y, i =>
  149. {
  150. var ip = pixel[i];
  151. ScreenBlackTexture[i] += new Geometry.Vector<float>(ip.r / maxCapture, ip.g / maxCapture, ip.b / maxCapture);
  152. });
  153. }
  154. public void CaptureWhite(WebCamTexture cam)
  155. {
  156. if (ScreenWhiteTexture == null)
  157. ScreenWhiteTexture = new Geometry.Vector<float>[Size.x * Size.y];
  158. var pixel = cam.GetPixels();
  159. Parallel.For(0, Size.x * Size.y, i =>
  160. {
  161. var ip = pixel[i];
  162. ScreenWhiteTexture[i] += new Geometry.Vector<float>(ip.r / maxCapture, ip.g / maxCapture, ip.b / maxCapture);
  163. });
  164. }
  165. public void CaptureStay(WebCamTexture cam)
  166. {
  167. if (locateIndex == -1) // 屏幕黑色
  168. {
  169. CaptureBlack(cam);
  170. }
  171. else // 屏幕部分为白色
  172. {
  173. CaptureWhite(cam);
  174. }
  175. }
  176. public void CaptureEnd()
  177. {
  178. //Debug.Log("locateIndex: " + locateIndex + ", quad: " + quadTemp.Count);
  179. if (locateIndex == -1)
  180. return;
  181. if (locateIndex < 4)
  182. {
  183. sumTemp.Add(GetBrightness());
  184. ScreenWhiteTexture = null;
  185. // 选择亮度差最大的区域
  186. if (locateIndex == 3)
  187. {
  188. areaSelected = sumTemp.MaxIndex();
  189. locateArea.AddRange(LocateAreaData[areaSelected]);
  190. }
  191. }
  192. else if (locateIndex >= 4 && locateIndex < locateArea.Count - 1)
  193. {
  194. QuadrilateralFit(out _,out _);
  195. ScreenWhiteTexture = null;
  196. }
  197. else
  198. {
  199. QuadrilateralFit(out Texture2D LocateTex, out Texture2D DrawLineTex);
  200. ScreenLocate.DebugTexture(2, LocateTex);
  201. ScreenLocate.DebugTexture(3, DrawLineTex);
  202. if (quadTemp.Count != LocateAreaData[0].Length)
  203. {
  204. Debug.Log($"拟合四边形失败, quadTemp.Count: {quadTemp.Count}");
  205. }
  206. else if (quadTemp.Count == 1)
  207. {
  208. Screen.Quad = quadTemp[0];
  209. }
  210. else
  211. {
  212. // 线性拟合
  213. var xValue = new List<float>() { 0 };
  214. var predicts = new List<Vector>();
  215. foreach (var i in LocateAreaData[0])
  216. xValue.Add(i.size.x);
  217. Vector baseVertex = Vector.Zero; // x==0 时的点
  218. {
  219. foreach (var q in quadTemp)
  220. {
  221. baseVertex += q[areaSelected];
  222. }
  223. baseVertex /= quadTemp.Count;
  224. }
  225. double rs = 0.0;
  226. for (int i = 0; i < 4; i++)
  227. {
  228. if (i == areaSelected)
  229. {
  230. predicts.Add(baseVertex);
  231. }
  232. else
  233. {
  234. var yValue = new List<Vector>() { baseVertex };
  235. foreach (var q in quadTemp)
  236. {
  237. yValue.Add(q[i]);
  238. }
  239. var lr = LinerRegression1D.Fit(2, xValue.ToArray(), yValue.ToArray());
  240. rs += lr.RSquared / 3;
  241. predicts.Add(lr.Predict<Vector>(1));
  242. }
  243. }
  244. Screen.Quad = new Quadrilateral(predicts);
  245. Debug.Log($"[InfraredIdentification2拟合结果] RSquared: {rs}, Quad: {Screen.Quad}");
  246. if (rs < 0.8) Screen.Quad = null;
  247. }
  248. }
  249. }
  250. public bool Update(WebCamTexture cam)
  251. {
  252. if (delay != 0)
  253. {
  254. delay--;
  255. return true;
  256. }
  257. if (capture != 0)
  258. {
  259. CaptureStay(cam);
  260. capture--;
  261. if (capture == 0)
  262. {
  263. CaptureEnd();
  264. NextScreen();
  265. }
  266. return true;
  267. }
  268. return false;
  269. #region Old
  270. /*
  271. if (delay != 0)
  272. {
  273. delay--;
  274. return true;
  275. }
  276. if (capture != 0)
  277. {
  278. capture--;
  279. if (ScreenBlackTexture == null)
  280. ScreenBlackTexture = new Geometry.Vector<float>[Size.x * Size.y];
  281. var pixel = cam.GetPixels();
  282. Parallel.For(0, Size.x * Size.y, i =>
  283. {
  284. var ip = pixel[i];
  285. ScreenBlackTexture[i] += new Geometry.Vector<float>(ip.r, ip.g, ip.b);
  286. });
  287. if (capture == 0)
  288. ScreenLocate.SetScreen(UnityEngine.Color.black);
  289. return true;
  290. }
  291. if (delay != 0)
  292. {
  293. delay--;
  294. return true;
  295. }
  296. if (capture != 0)
  297. {
  298. capture--;
  299. if (ScreenWhiteTexture == null)
  300. ScreenWhiteTexture = new Geometry.Vector<float>[Size.x * Size.y];
  301. var pixel = cam.GetPixels();
  302. Parallel.For(0, Size.x * Size.y, i =>
  303. {
  304. var ip = pixel[i];
  305. ScreenWhiteTexture[i] += new Geometry.Vector<float>(ip.r, ip.g, ip.b);
  306. });
  307. if (capture == 0)
  308. ScreenLocate.SetScreen(UnityEngine.Color.black);
  309. return true;
  310. }
  311. if (delay != 0)
  312. {
  313. delay--;
  314. return true;
  315. }
  316. if (capture != 0)
  317. {
  318. capture--;
  319. var pixel = cam.GetPixels();
  320. Parallel.For(0, Size.x * Size.y, i =>
  321. {
  322. var ip = pixel[i];
  323. ScreenWhiteTexture[i] -= new Geometry.Vector<float>(ip.r, ip.g, ip.b);
  324. });
  325. if (capture == 0)
  326. {
  327. ScreenLocate.SetScreen(null);
  328. UnityEngine.Color[] newPixel = new UnityEngine.Color[Size.x * Size.y];
  329. Parallel.For(0, Size.x * Size.y, i => {
  330. var pi = ScreenWhiteTexture[i] /= capture;
  331. newPixel[i] = new UnityEngine.Color(pi.x, pi.y, pi.z);
  332. });
  333. //读取数据
  334. //{
  335. // var fileName = "3.bin";
  336. // ScreenLocateTexture = $"2023 04 16 厦门测试数据/{fileName}".FileReadByte<Vector<float>[]>();
  337. // Debug.Log($"Read {fileName}");
  338. // Parallel.For(0, Size.x * Size.y, i =>
  339. // {
  340. // var pi = ScreenLocateTexture[i];
  341. // newPixel[i] = new UnityEngine.Color(pi.x, pi.y, pi.z);
  342. // });
  343. //}
  344. var ScreenLocateTex = new Texture2D(Size.x, Size.y);
  345. ScreenLocateTex.SetPixels(newPixel);
  346. ScreenLocateTex.Apply();
  347. //ScreenLocate.DebugTexture(2, ScreenLocateTex);
  348. var ScreenLocateTexLighted = ScreenLocateTex.AutoLight(10);
  349. //ScreenLocate.DebugTexture(2, ScreenLocateTexLighted);
  350. //var FileSavePath = Application.persistentDataPath + "/ScreenLocateTexture.bin";
  351. bool Save = ScreenLocate.Main.SaveToggle.isOn;
  352. string time;
  353. if (Save)
  354. {
  355. time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
  356. var FileSavePath = $"屏幕定位数据{time}.bin";
  357. FileSavePath.FileWriteByte(ScreenWhiteTexture);
  358. var bytes = ScreenLocateTexLighted.EncodeToPNG();
  359. File.WriteAllBytes($"屏幕定位数据{time}.png", bytes);
  360. Debug.Log("ScreenLocateTexture Saved To: " + FileSavePath);
  361. }
  362. var ScreenLocateTexR = ScreenLocateTexLighted.ToRGB(ColorChannel.Red);
  363. var ScreenLocateTexG = ScreenLocateTexLighted.ToRGB(ColorChannel.Green);
  364. var ScreenLocateTexB = ScreenLocateTexLighted.ToRGB(ColorChannel.Blue);
  365. ScreenLocate.DebugTexture(2, ScreenLocateTexR);
  366. //ScreenLocate.DebugTexture(4, ScreenLocateTexG);
  367. //ScreenLocate.DebugTexture(5, ScreenLocateTexB);
  368. var watch = new System.Diagnostics.Stopwatch();
  369. watch.Start();
  370. var times = new List<double>() { 0.0 };
  371. var ScreenLocateTexLightedMat = ScreenLocateTexLighted.Too0Mat();
  372. //var ScreenLocateTexLightedMat = texture.Too0Mat();
  373. //var (edge, edgeDir) = ScreenLocateTexLightedMat.IdentifyEdge();
  374. var (edge, edgeDir) = ScreenLocateTexLightedMat.zimIdentifyEdgeGradientAny(15);
  375. //ScreenLocate.DebugTexture(4, ScreenLocateTexLighted.Too0Mat().IdentifyEdgeGradient().ToTex());
  376. //ScreenLocate.DebugTexture(4, edge.ToTex());
  377. var quadLines = ScreenLocateTexLightedMat.IdentifyQuadLSD(edge, edgeDir, out List<Line> lightLines, 30);
  378. var drawLineMap = new MatrixF2D(edge.Width, edge.Height);
  379. int lineCount = 0;
  380. foreach (var l in quadLines)
  381. {
  382. if (l != null)
  383. {
  384. drawLineMap.DrawLine(l, (x, y) => 1, new Geometry2D.Float.Vector(0, 10));
  385. lineCount++;
  386. }
  387. }
  388. if (lineCount == 4)
  389. {
  390. var a = quadLines[0].Intersect(quadLines[3], false).Value;
  391. var b = quadLines[0].Intersect(quadLines[1], false).Value;
  392. var c = quadLines[2].Intersect(quadLines[3], false).Value;
  393. var d = quadLines[1].Intersect(quadLines[2], false).Value;
  394. Quad = new Quadrilateral(a, b, c, d);
  395. if (!Quad.IsInScreen(ScreenLocate.Main.WebCamera.Size))
  396. Quad = null;
  397. }
  398. ScreenLocate.Main.ShowScreen(Quad);
  399. //var lines = edge.IdentifyLineLSD(edgeDir, 100);
  400. ////var lines = ScreenLocateTexLightedMat.IdentifyLineLSD();
  401. //var drawLineMap = new MatrixF2D(edge.Width, edge.Height);
  402. //var returnMaxLines = lines.Sub(0, 10);
  403. //foreach (var (line, sum, gradient) in returnMaxLines)
  404. // drawLineMap.DrawLine(line, (x, y) => 1, new Geometry2D.Float.Vector(0, 10));
  405. ScreenLocate.DebugTexture(3, drawLineMap.ToTex());
  406. //{
  407. // var bytes = drawLineMap.ToTex().EncodeToPNG();
  408. // File.WriteAllBytes($"屏幕定位数据DrawLineMap.png", bytes);
  409. //}
  410. times.Add(watch.ElapsedMilliseconds);
  411. UnityEngine.Debug.Log("time: " + (times[times.Count - 1] - times[times.Count - 2]));
  412. //ScreenLocate.DebugTexture(5, edge.IdentifyLine(edgeDir).ToTex());
  413. //ScreenLocate.DebugTexture(4, ScreenLocateTexLighted.Too0Mat().IdentifyEdgeGradientX().ToTex());
  414. //ScreenLocate.DebugTexture(5, ScreenLocateTexLighted.Too0Mat().IdentifyEdgeGradientY().ToTex());
  415. //var convolutionLighted2 = ScreenLocateTexLighted.Too0Mat().IdentifyEdgeVariance().ToTex();
  416. // opecncv处理
  417. // zim
  418. {
  419. //var cvLines = edge.cvHoughLinesP();
  420. //ScreenLocate.DebugTexture(5, cvLines);
  421. //var myLines = Hough.Transform(edgeMat);
  422. //var cvLines = edge.cvLine(myLines);
  423. //ScreenLocate.DebugTexture(5, cvLines);
  424. }
  425. UnityEngine.Object.Destroy(ScreenLocateTex);
  426. //ScreenLocate.DebugTexture(4, convolutionLighted2);
  427. }
  428. return true;
  429. }
  430. /*
  431. var avg = new Geometry4D.Vector<float>();
  432. var pixel = texture.GetPixels();
  433. foreach(var i in pixel.Index())
  434. {
  435. var iP = pixel[i];
  436. avg += new Geometry4D.Vector<float>(iP.r, iP.g, iP.b, iP.a);
  437. }
  438. avg /= pixel.Count();
  439. /*
  440. var (texLightedR, texLightedG, texLightedB) = ToRGB(newTex);
  441. ScreenLocate.DebugTexture(3, texLightedR);
  442. ScreenLocate.DebugTexture(4, texLightedG);
  443. ScreenLocate.DebugTexture(5, texLightedB);
  444. //Debug.Log(avg);
  445. return false;
  446. /**/
  447. #endregion
  448. }
  449. float GetBrightness()
  450. {
  451. UnityEngine.Color[] differPixel = new UnityEngine.Color[Size.x * Size.y];
  452. Parallel.For(0, Size.x * Size.y, i => {
  453. var pi = ScreenWhiteTexture[i] - ScreenBlackTexture[i];
  454. differPixel[i] = new UnityEngine.Color(pi.x, pi.y, pi.z);
  455. });
  456. var sum = 0f;
  457. foreach (var i in differPixel)
  458. {
  459. sum += i.Brightness();
  460. }
  461. sum /= differPixel.Length;
  462. //Debug.Log(sum);
  463. return sum;
  464. }
  465. void QuadrilateralFit(out Texture2D LocateTex, out Texture2D DrawLineTex, Texture2D debugImage = null)
  466. {
  467. Quadrilateral quad = null;
  468. UnityEngine.Color[] differPixel = new UnityEngine.Color[Size.x * Size.y];
  469. //读取数据
  470. if (debugImage != null)
  471. {
  472. Debug.Log($"Debug {debugImage.name}");
  473. differPixel = debugImage.GetPixels();
  474. }
  475. else // 获得屏幕差值
  476. {
  477. Parallel.For(0, Size.x * Size.y, i => {
  478. var pi = ScreenWhiteTexture[i] - ScreenBlackTexture[i];
  479. differPixel[i] = new UnityEngine.Color(pi.x, pi.y, pi.z);
  480. });
  481. }
  482. var ScreenLocateTex = new Texture2D(Size.x, Size.y);
  483. ScreenLocateTex.SetPixels(differPixel);
  484. ScreenLocateTex.Apply();
  485. //ScreenLocate.DebugTexture(2, ScreenLocateTex);
  486. var ScreenLocateTexLighted = ScreenLocateTex.AutoLight(10);
  487. //ScreenLocate.DebugTexture(2, ScreenLocateTexLighted);
  488. var ScreenLocateTexR = ScreenLocateTexLighted.ToRGB(ColorChannel.Red);
  489. var ScreenLocateTexG = ScreenLocateTexLighted.ToRGB(ColorChannel.Green);
  490. var ScreenLocateTexB = ScreenLocateTexLighted.ToRGB(ColorChannel.Blue);
  491. LocateTex = ScreenLocateTexR;
  492. //ScreenLocate.DebugTexture(2, ScreenLocateTexR);
  493. //ScreenLocate.DebugTexture(4, ScreenLocateTexG);
  494. //ScreenLocate.DebugTexture(5, ScreenLocateTexB);
  495. //var watch = new System.Diagnostics.Stopwatch();
  496. //watch.Start();
  497. //var times = new List<double>() { 0.0 };
  498. var ScreenLocateTexLightedMat = ScreenLocateTexLighted.Too0Mat();
  499. //var ScreenLocateTexLightedMat = texture.Too0Mat();
  500. //var (edge, edgeDir) = ScreenLocateTexLightedMat.IdentifyEdge();
  501. int conSize = 15;
  502. var (edge, edgeDir) = ScreenLocateTexLightedMat.zimIdentifyEdgeGradientAny(conSize);
  503. //ScreenLocate.DebugTexture(4, ScreenLocateTexLighted.Too0Mat().IdentifyEdgeGradient().ToTex());
  504. //ScreenLocate.DebugTexture(4, edge.ToTex());
  505. var minLength = locateIndex == -1 ? 50 : 50 * areaPercent;
  506. var quadLines = ScreenLocateTexLightedMat.IdentifyQuadLSD(edge, edgeDir, out List<Line> lightLines, conSize, minLength);
  507. var drawLineMap = new MatrixF2D(edge.Width, edge.Height);
  508. int lineCount = 0;
  509. foreach (var l in quadLines)
  510. {
  511. if (l != null)
  512. {
  513. drawLineMap.DrawLine(l, (x, y) => 1, new Geometry2D.Float.Vector(0, 10));
  514. lineCount++;
  515. }
  516. }
  517. //foreach (var l in lightLines)
  518. //{
  519. // if (l != null)
  520. // {
  521. // if (quadLines.Contains(l))
  522. // {
  523. // drawLineMap.DrawLine(l, (x, y) => 1, new Geometry2D.Float.Vector(0, 10));
  524. // lineCount++;
  525. // }
  526. // else
  527. // {
  528. // drawLineMap.DrawLine(l, (x, y) => 1, new Geometry2D.Float.Vector(0, 2));
  529. // }
  530. // }
  531. //}
  532. if (lineCount == 4)
  533. {
  534. var a = quadLines[0].Intersect(quadLines[3], false).Value;
  535. var b = quadLines[0].Intersect(quadLines[1], false).Value;
  536. var c = quadLines[2].Intersect(quadLines[3], false).Value;
  537. var d = quadLines[1].Intersect(quadLines[2], false).Value;
  538. quad = new Quadrilateral(a, b, c, d);
  539. if (!quad.IsInScreen(ScreenLocate.Main.WebCamera.Size))
  540. quad = null;
  541. }
  542. //if (quad != null && debugImage == null)
  543. if (quad != null)
  544. quadTemp.Add(quad);
  545. //var lines = edge.IdentifyLineLSD(edgeDir, 100);
  546. ////var lines = ScreenLocateTexLightedMat.IdentifyLineLSD();
  547. //var drawLineMap = new MatrixF2D(edge.Width, edge.Height);
  548. //var returnMaxLines = lines.Sub(0, 10);
  549. //foreach (var (line, sum, gradient) in returnMaxLines)
  550. // drawLineMap.DrawLine(line, (x, y) => 1, new Geometry2D.Float.Vector(0, 10));
  551. DrawLineTex = drawLineMap.ToTex();
  552. //ScreenLocate.DebugTexture(3, drawLineMap.ToTex());
  553. //var FileSavePath = Application.persistentDataPath + "/ScreenLocateTexture.bin";
  554. bool Save = ScreenLocate.Main.SaveToggle.isOn;
  555. string time;
  556. if (Save)
  557. {
  558. time = DateTime.Now.ToString("yyyyMMdd_HHmmss");
  559. var FileSavePath = $"{time}屏幕定位数据.bin";
  560. FileSavePath.FileWriteByte(ScreenWhiteTexture);
  561. var bytes = ScreenLocateTexLighted.EncodeToPNG();
  562. File.WriteAllBytes($"{time}屏幕.png", bytes);
  563. bytes = DrawLineTex.EncodeToPNG();
  564. File.WriteAllBytes($"{time}屏幕边框识别.png", bytes);
  565. Debug.Log("ScreenLocateTexture Saved To: " + FileSavePath);
  566. }
  567. //times.Add(watch.ElapsedMilliseconds);
  568. //UnityEngine.Debug.Log("time: " + (times[times.Count - 1] - times[times.Count - 2]));
  569. //ScreenLocate.DebugTexture(5, edge.IdentifyLine(edgeDir).ToTex());
  570. //ScreenLocate.DebugTexture(4, ScreenLocateTexLighted.Too0Mat().IdentifyEdgeGradientX().ToTex());
  571. //ScreenLocate.DebugTexture(5, ScreenLocateTexLighted.Too0Mat().IdentifyEdgeGradientY().ToTex());
  572. //var convolutionLighted2 = ScreenLocateTexLighted.Too0Mat().IdentifyEdgeVariance().ToTex();
  573. // opecncv处理
  574. // zim
  575. {
  576. //var cvLines = edge.cvHoughLinesP();
  577. //ScreenLocate.DebugTexture(5, cvLines);
  578. //var myLines = Hough.Transform(edgeMat);
  579. //var cvLines = edge.cvLine(myLines);
  580. //ScreenLocate.DebugTexture(5, cvLines);
  581. }
  582. UnityEngine.Object.Destroy(ScreenLocateTex);
  583. }
  584. }
  585. }