ScreenIdentification.cs 28 KB

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