FindSquaresTest.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.UI;
  5. //using OpenCVForUnity.ImgprocModule;
  6. //using OpenCVForUnity.CoreModule;
  7. //using OpenCVForUnity.UnityUtils;
  8. //using OpenCVForUnity.ImgcodecsModule;
  9. //using OpenCVForUnity.FaceModule;
  10. using System;
  11. using System.Linq;
  12. using o0.Geometry2D;
  13. using System.IO;
  14. using System.Threading.Tasks;
  15. using ZIM.Image;
  16. using o0;
  17. using o0.Project;
  18. using Color = UnityEngine.Color;
  19. //public class FindSquaresTest : MonoBehaviour
  20. //{
  21. // public List<RawImage> Images;
  22. // // Start is called before the first frame update
  23. // void Awake()
  24. // {
  25. // /*
  26. // var v0 = new Vector<float>(5, 0);
  27. // var v1 = new Vector<float>(0, 5);
  28. // var dir = v1 - v0;
  29. // var edgeP = new Vector<float>(dir.y, -dir.x);
  30. // Debug.Log(edgeP);
  31. // var p = new Vector<float>(1, 0.5f);
  32. // var ep = p;
  33. // var dot = ep.x * edgeP.y - ep.y * edgeP.x;
  34. // Debug.Log(dot);
  35. // var line = new Line<float>(v0, v1);
  36. // Debug.Log("distance: " + new Vector<float>(0, 0).DistanceTo(line));
  37. // //Debug.Log(new Vector<float>(0, 0).VerticalLineIntersect(line));
  38. // var line2 = new Line<float>(new Vector<float>(0,0), new Vector<float>(1,1));
  39. // var point = line.Intersect(line2, out float ta, out float tb, false);
  40. // {
  41. // Point p1 = new Point(0, 0);
  42. // Point p2 = new Point(3, 0);
  43. // Point p3 = new Point(3.1, 4);
  44. // Point p4 = new Point(3, 5);
  45. // Point p5 = new Point(0, 5);
  46. // Point p6 = new Point(0.1, 4);
  47. // var array = new Point[] { p1, p2, p3, p4, p5, p6 };
  48. // var mat = new MatOfPoint2f(array);
  49. // mat = PointReduce(mat, 4);
  50. // foreach (var i in mat.toArray())
  51. // Debug.Log(i);
  52. // }
  53. // /**/
  54. // GetComponent<Button>().onClick.AddListener(onClick);
  55. // }
  56. // // Update is called once per frame
  57. // void Update()
  58. // {
  59. // if (Input.GetKeyUp(KeyCode.Q))
  60. // {
  61. // onClick();
  62. // }
  63. // }
  64. // public void onClick()
  65. // {
  66. // var watch = new System.Diagnostics.Stopwatch();
  67. // watch.Start();
  68. // var times = new List<double>() { 0.0 };
  69. // foreach (var i in Images)
  70. // {
  71. // if (!i || !i.gameObject.activeSelf)
  72. // continue;
  73. // //cvFindSquare(i);
  74. // //cvHoughLines(i);
  75. // zimFindLines(i);
  76. // }
  77. // times.Add(watch.ElapsedMilliseconds);
  78. // UnityEngine.Debug.Log("time: " + (times[times.Count - 1] - times[times.Count - 2]));
  79. // }
  80. // string SavePath = "output/";
  81. // void cvFindSquare(RawImage rawImage, double threshold = 30, double maxCosineOfSquare = 0.75)
  82. // {
  83. // if (rawImage.texture == null)
  84. // return;
  85. // //if true, The error log of the Native side OpenCV will be displayed on the Unity Editor Console.
  86. // Utils.setDebugMode(true);
  87. // Mat src = new Mat(rawImage.texture.height, rawImage.texture.width, CvType.CV_8UC4);
  88. // Utils.texture2DToMat((Texture2D)rawImage.texture, src);
  89. // Imgcodecs.imwrite(SavePath + rawImage.name + "_opencv0.jpg", src);
  90. // // 图像二值化处理
  91. // Imgproc.GaussianBlur(src, src, new Size(3, 3), 0);
  92. // Mat gray = new Mat(src.size(), src.type());
  93. // Imgproc.cvtColor(src, gray, Imgproc.COLOR_BGR2GRAY);
  94. // Mat bin = new Mat(src.size(), src.type());
  95. // Imgproc.threshold(src, bin, threshold, 255, Imgproc.THRESH_BINARY);
  96. // Imgproc.cvtColor(bin, bin, Imgproc.COLOR_BGR2GRAY);
  97. // Imgcodecs.imwrite(SavePath + rawImage.name + "_opencv1.jpg", bin);
  98. // List<MatOfPoint> contours = new List<MatOfPoint>();
  99. // Mat hierarchy = new Mat(src.size(), src.type());
  100. // Imgproc.findContours(bin, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
  101. // // 查找四边形, 修改自opencv官方的find_squares例子
  102. // var squares = new SortedList<double, MatOfPoint>();
  103. // foreach (var cnt in contours)
  104. // {
  105. // var cntf = new MatOfPoint2f(cnt.toArray());
  106. // var cnt_len = Imgproc.arcLength(cntf, true);
  107. // Imgproc.approxPolyDP(cntf, cntf, 0.025 * cnt_len, true);
  108. // //Imgproc.drawContours(src, new List<MatOfPoint> { new MatOfPoint(cntf.toArray()) }, -1, new Scalar(255, 0, 0, 255), 4);
  109. // var area = Math.Abs(Imgproc.contourArea(cntf));
  110. // if (Math.Abs(cntf.rows() - 6) <= 2 && area > 10000) // && Imgproc.isContourConvex(cntf))
  111. // {
  112. // cntf = PointReduce(cntf, 4); // 删减顶点数至4个
  113. // double maxCosine = 0;
  114. // var cntfArray = cntf.toArray();
  115. // for (int j = 2; j < 5; j++)
  116. // {
  117. // // find the maximum cosine of the angle between joint edges
  118. // double cosine = Math.Abs(cvAngle2D(cntfArray[j % 4], cntfArray[j - 2], cntfArray[j - 1]));
  119. // maxCosine = Math.Max(maxCosine, cosine);
  120. // }
  121. // // if cosines of all angles are small
  122. // // (all angles are ~90 degree) then write quandrange
  123. // // vertices to resultant sequence
  124. // if (maxCosine < maxCosineOfSquare)
  125. // {
  126. // squares[area] = new MatOfPoint(cntf.toArray());
  127. // //Imgproc.drawContours(src, squares, -1, new Scalar(255, 0, 0, 255), 1);
  128. // foreach (var i in cntfArray)
  129. // Imgproc.circle(src, i, 5, new Scalar(255, 255, 255, 255), -1);
  130. // }
  131. // }
  132. // }
  133. // if (squares.Count != 0)
  134. // {
  135. // Debug.Log("查找到四边形: " + rawImage.name);
  136. // Imgproc.drawContours(src, new List<MatOfPoint> { squares.Last().Value }, -1, new Scalar(255, 0, 0, 255), 1);
  137. // Imgcodecs.imwrite(SavePath + rawImage.name + "_opencv2.jpg", src);
  138. // }
  139. // else
  140. // {
  141. // Debug.Log("不能查找到四边形: " + rawImage.name);
  142. // }
  143. // //Mat dst = new Mat(src.size(), src.type(), new Scalar(0, 0, 0, 255, 255));
  144. // Texture2D texture2 = new Texture2D(src.cols(), src.rows(), TextureFormat.RGBA32, false);
  145. // Utils.matToTexture2D(src, texture2);
  146. // rawImage.texture = texture2;
  147. // Utils.setDebugMode(false);
  148. // }
  149. // void cvHoughLines(RawImage rawImage)
  150. // {
  151. // //if true, The error log of the Native side OpenCV will be displayed on the Unity Editor Console.
  152. // Utils.setDebugMode(true);
  153. // Mat src = new Mat(rawImage.texture.height, rawImage.texture.width, CvType.CV_8UC4);
  154. // Utils.texture2DToMat((Texture2D)rawImage.texture, src);
  155. // Imgcodecs.imwrite(SavePath + rawImage.name + "_opencv0.jpg", src);
  156. // // 保留红通道
  157. // Mat red = new Mat();
  158. // Core.extractChannel(src, red, 0);
  159. // for (int i = 0; i < 5; i++)
  160. // {
  161. // Imgproc.GaussianBlur(red, red, new Size(5, 5), 3);
  162. // //Sobel算子
  163. // Mat x = new Mat(), y = new Mat();
  164. // Imgproc.Sobel(red, x, CvType.CV_16S, 1, 0);
  165. // Imgproc.Sobel(red, y, CvType.CV_16S, 0, 1);
  166. // Core.convertScaleAbs(x, x);
  167. // Core.convertScaleAbs(y, y);
  168. // Core.addWeighted(x, 0.5, y, 0.5, 0, red);
  169. // Imgcodecs.imwrite(SavePath + rawImage.name + $"_opencv1_{i}.jpg", red);
  170. // }
  171. // //// 计算Laplacian卷积结果
  172. // //Mat laplacian = new Mat();
  173. // //Imgproc.Laplacian(gray, laplacian, CvType.CV_16S);
  174. // ////数据进行转换成uint8形式
  175. // //Core.convertScaleAbs(laplacian, laplacian);
  176. // //Imgcodecs.imwrite(SavePath + rawImage.name + "_opencv1l.jpg", laplacian);
  177. // //// canny
  178. // //Imgproc.Canny(gray, gray, 0, 2);
  179. // //Imgcodecs.imwrite(SavePath + rawImage.name + "_opencv1c.jpg", gray);
  180. // Mat lines = new Mat();
  181. // Imgproc.HoughLinesP(red, lines, 3, Math.PI / 180, 30, 100, 10);
  182. // for (int i = 0; i < lines.rows(); i++)
  183. // {
  184. // int[] line = new int[4];
  185. // lines.get(i, 0, line);//将线对应的极点坐标存到line数组中
  186. // Imgproc.line(src, new Point(line[0], line[1]), new Point(line[2], line[3]), new Scalar(255, 0, 0, 255), 4, Imgproc.LINE_AA);
  187. // Debug.Log("线段" + i + ": " + new Point(line[0], line[1]) + ", " + new Point(line[2], line[3]));
  188. // }
  189. // Imgcodecs.imwrite(SavePath + rawImage.name + "_opencv2.jpg", src);
  190. // Texture2D texture2 = new Texture2D(src.cols(), src.rows(), TextureFormat.RGBA32, false);
  191. // Utils.matToTexture2D(src, texture2);
  192. // rawImage.texture = texture2;
  193. // Utils.setDebugMode(false);
  194. // }
  195. // void zimFindLines(RawImage rawImage)
  196. // {
  197. // //MatrixF2D mat = new MatrixF2D(result.w, result.p);
  198. // //var t = mat.IdentifyEdgeGradientFull().ToTex();
  199. // var pixels = ((Texture2D)rawImage.texture).GetPixels();
  200. // var brightness = new float[pixels.Length];
  201. // Parallel.For(0, pixels.Length, (i) =>
  202. // {
  203. // brightness[i] = getBrightness(pixels[i]);
  204. // });
  205. // ImgProcessGray imageGray = new ImgProcessGray(brightness, rawImage.texture.width, rawImage.texture.height);
  206. // var result = imageGray.FindLines();
  207. // var t = ArrayToTexture(result.p, result.w, result.h);
  208. // var bytes = t.EncodeToPNG();
  209. // File.WriteAllBytes($"output/Variance2.png", bytes);
  210. // rawImage.texture = t;
  211. // }
  212. // Texture2D ArrayToTexture(float[] pixels,int width, int height)
  213. // {
  214. // var color = new Color[pixels.Length];
  215. // Parallel.For(0, pixels.Length, (i) =>
  216. // {
  217. // color[i] = new Color(pixels[i], 0, 0);
  218. // });
  219. // var texture = new Texture2D(width, height);
  220. // texture.SetPixels(color);
  221. // texture.Apply();
  222. // return texture;
  223. // }
  224. // // finds a cosine of angle between vectors
  225. // // from pt0->pt1 and from pt0->pt2
  226. // double cvAngle2D(Point pt1, Point pt2, Point pt0)
  227. // {
  228. // double dx1 = pt1.x - pt0.x;
  229. // double dy1 = pt1.y - pt0.y;
  230. // double dx2 = pt2.x - pt0.x;
  231. // double dy2 = pt2.y - pt0.y;
  232. // return (dx1 * dx2 + dy1 * dy2) / Math.Sqrt((dx1 * dx1 + dy1 * dy1) * (dx2 * dx2 + dy2 * dy2) + 1e-10);
  233. // }
  234. // double cvArea(Point p1, Point p2, Point p3)
  235. // {
  236. // double _distance(Point p1, Point p2)
  237. // {
  238. // return Math.Sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y));
  239. // }
  240. // //计算三边长
  241. // double a = _distance(p1, p2);
  242. // double b = _distance(p2, p3);
  243. // double c = _distance(p3, p1);
  244. // //计算半周长
  245. // double s = (a + b + c) / 2;
  246. // //计算面积,注意处理退化情况
  247. // if (s == 0 || s * (s - a) * (s - b) * (s - c) < 0)
  248. // return 0;
  249. // else
  250. // return Math.Sqrt(s * (s - a) * (s - b) * (s - c));
  251. // }
  252. // public float getBrightness(Color c)
  253. // {
  254. // return 0.59f * c.r + 0.3f * c.g + 0.11f * c.b; // 红色为主
  255. // }
  256. // MatOfPoint2f PointReduce(MatOfPoint2f cnt, int dstCount) // 随手写的,还能优化
  257. // {
  258. // var array = cnt.toList();
  259. // if (array.Count <= dstCount)
  260. // return cnt;
  261. // while (array.Count > dstCount)
  262. // {
  263. // var areas = new SortedList<double, int>();
  264. // for (int j = 1; j < array.Count + 1; j++)
  265. // areas[cvArea(array[j - 1], array[j % array.Count], array[(j + 1) % array.Count])] = j % array.Count;
  266. // array.RemoveAt(areas.First().Value);
  267. // }
  268. // return new MatOfPoint2f(array.ToArray());
  269. // }
  270. //}