o0IdentifyEdge.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Threading.Tasks;
  4. namespace o0.Project
  5. {
  6. public static partial class Extension
  7. {
  8. static private Matrix IdentifyEdgeVariance(this Matrix mat)
  9. {
  10. var conSize = 3;
  11. var conArea = conSize * conSize;
  12. var convolution = new Matrix(new Geometry2D.Vector<int>(mat.Size.x - (conSize - 1), mat.Size.y - (conSize - 1)), Tiling: true);
  13. var pixelC = convolution.Element;
  14. var convolutionWidth = convolution.Size.x;
  15. Parallel.For(0, convolution.Size.x * convolution.Size.y, i => {
  16. var iPx = i % convolutionWidth;
  17. var iPy = i / convolutionWidth;
  18. var mean = 0.0f;
  19. //var max = 0.0f;
  20. //var min = 1.0f;
  21. List<float> rList = new List<float>();
  22. for (var jX = 0; jX < conSize; ++jX)
  23. {
  24. for (var jY = 0; jY < conSize; ++jY)
  25. {
  26. var jIndex = (iPx + jX) + (iPy + jY) * mat.Size.x;
  27. var r = mat.Element[jIndex];
  28. mean += r;
  29. rList.Add(r);
  30. /*
  31. if (max < r)
  32. max = r;
  33. if (min > r)
  34. min = r;/**/
  35. }
  36. }
  37. mean /= conArea;
  38. var variance = 0.0f;
  39. foreach (var j in rList)
  40. {
  41. var d = (j - mean);// / mean;
  42. variance += d * d;
  43. }
  44. variance /= conArea;
  45. variance /= mean;
  46. /*
  47. foreach (var j in (Geometry2D.Vector<int>.One * 3).Range())
  48. {
  49. var jP = iP + j;
  50. var jIndex = jP.x + jP.y * Size.x;
  51. rList.Add(pixelLighted[jIndex].r);
  52. }/**/
  53. //pixelC[i] = new UnityEngine.Color(Num.Extension.Variance(rList), 0, 0);
  54. pixelC[i] = variance;
  55. });
  56. return convolution.Map(ignoreExtremum: 10);
  57. }
  58. static private Matrix IdentifyEdgeGradientX(this Matrix mat)
  59. {
  60. var conSize = 3;
  61. var conArea = conSize * conSize;
  62. var convolution = new Matrix(new Geometry2D.Vector<int>(mat.Size.x - (conSize - 1), mat.Size.y - (conSize - 1)), Tiling: true);
  63. var pixelC = convolution.Element;
  64. var convolutionWidth = convolution.Size.x;
  65. Parallel.For(0, convolution.Size.x * convolution.Size.y, i => {
  66. var iPx = i % convolutionWidth;
  67. var iPy = i / convolutionWidth;
  68. pixelC[i] = MathF.Abs(mat.Element[(iPx + 0) + (iPy + 1) * mat.Size.x] - mat.Element[(iPx + 2) + (iPy + 1) * mat.Size.x]);
  69. });
  70. return convolution.Map(ignoreExtremum: 10);
  71. }
  72. static private Matrix IdentifyEdgeGradientY(this Matrix mat)
  73. {
  74. var conSize = 3;
  75. var conArea = conSize * conSize;
  76. var convolution = new Matrix(new Geometry2D.Vector<int>(mat.Size.x - (conSize - 1), mat.Size.y - (conSize - 1)), Tiling: true);
  77. var pixelC = convolution.Element;
  78. var convolutionWidth = convolution.Size.x;
  79. Parallel.For(0, convolution.Size.x * convolution.Size.y, i => {
  80. var iPx = i % convolutionWidth;
  81. var iPy = i / convolutionWidth;
  82. pixelC[i] = MathF.Abs(mat.Element[(iPx + 1) + (iPy + 0) * mat.Size.x] - mat.Element[(iPx + 1) + (iPy + 2) * mat.Size.x]);
  83. });
  84. return convolution.Map(ignoreExtremum: 10);
  85. }
  86. static private Matrix IdentifyEdgeGradient(this Matrix mat)
  87. {
  88. var conSize = 3;
  89. var conArea = conSize * conSize;
  90. var convolution = new Matrix(new Geometry2D.Vector<int>(mat.Size.x - (conSize - 1), mat.Size.y - (conSize - 1)), Tiling: true);
  91. var pixelC = convolution.Element;
  92. var convolutionWidth = convolution.Size.x;
  93. Parallel.For(0, convolution.Size.x * convolution.Size.y, i => {
  94. var iPx = i % convolutionWidth;
  95. var iPy = i / convolutionWidth;
  96. var gX = mat.Element[(iPx + 2) + (iPy + 1) * mat.Size.x] * 2
  97. - mat.Element[(iPx + 0) + (iPy + 1) * mat.Size.x] * 2;
  98. var gY = mat.Element[(iPx + 1) + (iPy + 2) * mat.Size.x] * 2
  99. - mat.Element[(iPx + 1) + (iPy + 0) * mat.Size.x] * 2;
  100. float root2 = 1.4142135623730950488016887242097f;
  101. var gXY = //x0y0向x2y2方向的斜率
  102. mat.Element[(iPx + 2) + (iPy + 2) * mat.Size.x]
  103. - mat.Element[(iPx + 0) + (iPy + 0) * mat.Size.x];
  104. gXY *= root2;
  105. var gYX = //x2y0向x0y2方向的斜率
  106. + mat.Element[(iPx + 0) + (iPy + 2) * mat.Size.x]
  107. - mat.Element[(iPx + 2) + (iPy + 0) * mat.Size.x];
  108. gYX *= root2;
  109. pixelC[i] = o0.Max(MathF.Abs(gX), MathF.Abs(gY), MathF.Abs(gXY), MathF.Abs(gYX));
  110. });
  111. return convolution.Map(ignoreExtremum: 10);
  112. }
  113. ////////////////梯度大小图///梯度方向图 0-360度 数学4象限
  114. static public (Matrix, Matrix) IdentifyEdge(this Matrix mat)//这个效果最好
  115. {
  116. var conSize = 3;
  117. var conArea = conSize * conSize;
  118. var convolution = new Matrix(new Geometry2D.Vector<int>(mat.Size.x - (conSize - 1), mat.Size.y - (conSize - 1)), Tiling: true);
  119. var pixelC = convolution.Element;
  120. var dirMat = new Matrix(convolution.Size, Tiling: true);
  121. var pixelDir = dirMat.Element;
  122. var convolutionWidth = convolution.Size.x;
  123. Parallel.For(0, convolution.Size.x * convolution.Size.y, i => {
  124. var iPx = i % convolutionWidth;
  125. var iPy = i / convolutionWidth;
  126. var sum = 0.0f;
  127. //var max = 0.0f;
  128. //var min = 1.0f;
  129. for (var jX = 0; jX < conSize; ++jX)
  130. for (var jY = 0; jY < conSize; ++jY)
  131. {
  132. var v = mat.Element[(iPx + jX) + (iPy + jY) * mat.Size.x];
  133. sum += v;
  134. /*
  135. if (max < v)
  136. max = v;
  137. if (min > v)
  138. min = v;/**/
  139. }
  140. if (sum == 0.0f)
  141. return;
  142. /*
  143. if (min == 0.0f)
  144. return;/**/
  145. var gX = mat.Element[(iPx + 2) + (iPy + 0) * mat.Size.x]
  146. + mat.Element[(iPx + 2) + (iPy + 1) * mat.Size.x] * 2
  147. + mat.Element[(iPx + 2) + (iPy + 2) * mat.Size.x]
  148. - mat.Element[(iPx + 0) + (iPy + 0) * mat.Size.x]
  149. - mat.Element[(iPx + 0) + (iPy + 1) * mat.Size.x] * 2
  150. - mat.Element[(iPx + 0) + (iPy + 2) * mat.Size.x];
  151. var gY = mat.Element[(iPx + 0) + (iPy + 2) * mat.Size.x]
  152. + mat.Element[(iPx + 1) + (iPy + 2) * mat.Size.x] * 2
  153. + mat.Element[(iPx + 2) + (iPy + 2) * mat.Size.x]
  154. - mat.Element[(iPx + 0) + (iPy + 0) * mat.Size.x]
  155. - mat.Element[(iPx + 1) + (iPy + 0) * mat.Size.x] * 2
  156. - mat.Element[(iPx + 2) + (iPy + 0) * mat.Size.x];
  157. float root2 = 1.4142135623730950488016887242097f;
  158. var gXY = mat.Element[(iPx + 1) + (iPy + 2) * mat.Size.x] //x0y0向x2y2方向的斜率
  159. + mat.Element[(iPx + 2) + (iPy + 2) * mat.Size.x]
  160. + mat.Element[(iPx + 2) + (iPy + 1) * mat.Size.x]
  161. - mat.Element[(iPx + 1) + (iPy + 0) * mat.Size.x]
  162. - mat.Element[(iPx + 0) + (iPy + 0) * mat.Size.x]
  163. - mat.Element[(iPx + 0) + (iPy + 1) * mat.Size.x];
  164. gXY *= root2;
  165. var gYX = mat.Element[(iPx + 1) + (iPy + 2) * mat.Size.x] //x2y0向x0y2方向的斜率
  166. + mat.Element[(iPx + 0) + (iPy + 2) * mat.Size.x]
  167. + mat.Element[(iPx + 0) + (iPy + 1) * mat.Size.x]
  168. - mat.Element[(iPx + 1) + (iPy + 0) * mat.Size.x]
  169. - mat.Element[(iPx + 2) + (iPy + 0) * mat.Size.x]
  170. - mat.Element[(iPx + 2) + (iPy + 1) * mat.Size.x];
  171. gYX *= root2;
  172. float[] gra = new float[] { MathF.Abs(gX), MathF.Abs(gY), MathF.Abs(gXY), MathF.Abs(gYX) };
  173. var maxIndex = o0.MaxIndex(gra);
  174. pixelC[i] = gra[maxIndex];
  175. switch (maxIndex)
  176. {
  177. case 0:
  178. pixelDir[i] = gX > 0 ? 0 : 180;
  179. break;
  180. case 1:
  181. pixelDir[i] = gY > 0 ? 90 : 270;
  182. break;
  183. case 2:
  184. pixelDir[i] = gXY > 0 ? 45 : 225;
  185. break;
  186. case 3:
  187. pixelDir[i] = gYX > 0 ? 135 : 315;
  188. break;
  189. }
  190. //pixelC[i] = MathF.Abs(gX) + MathF.Abs(gY) + MathF.Abs(gXY) + MathF.Abs(gYX);
  191. /*
  192. if (pixelC[i] / 9f < 1.0f / 256f)
  193. {
  194. pixelC[i] = 0;
  195. return;
  196. }/**/
  197. /*
  198. if (sum < 100f/256f)
  199. {
  200. pixelC[i] = 0;
  201. return;
  202. }/**/
  203. //pixelC[i] = o0.Max(MathF.Abs(gX), MathF.Abs(gY), MathF.Abs(gXY), MathF.Abs(gYX));
  204. //pixelC[i] /= MathF.Pow(sum / 9, 0.1f);
  205. //pixelC[i] /= min + 0.5f;
  206. //pixelC[i] /= min + 0.1f;
  207. pixelC[i] /= sum / 9f + 1f;//+1是为了防止除数太小,结果不合理地过大
  208. });
  209. return (convolution.Map(ignoreExtremum: 10), dirMat);
  210. }
  211. static public (Matrix, Matrix) IdentifyEdge55GradientFull(this Matrix mat)
  212. {
  213. var conSize = 5;
  214. var conArea = conSize * conSize;
  215. var convolution = new Matrix(new Geometry2D.Vector<int>(mat.Size.x - (conSize - 1), mat.Size.y - (conSize - 1)), Tiling: true);
  216. var pixelC = convolution.Element;
  217. var dirMat = new Matrix(convolution.Size, Tiling: true);
  218. var pixelDir = dirMat.Element;
  219. var convolutionWidth = convolution.Size.x;
  220. Parallel.For(0, convolution.Size.x * convolution.Size.y, i => {
  221. var iPx = i % convolutionWidth;
  222. var iPy = i / convolutionWidth;
  223. var sum = 0.0f;
  224. for (var jX = 0; jX < conSize; ++jX)
  225. for (var jY = 0; jY < conSize; ++jY)
  226. sum += mat.Element[(iPx + jX) + (iPy + jY) * mat.Size.x];
  227. if (sum == 0.0f)
  228. return;
  229. var gX = mat.Element[(iPx + 4) + (iPy + 1) * mat.Size.x] //梯度0度
  230. + mat.Element[(iPx + 4) + (iPy + 2) * mat.Size.x] * 2
  231. + mat.Element[(iPx + 4) + (iPy + 3) * mat.Size.x]
  232. - mat.Element[(iPx + 0) + (iPy + 1) * mat.Size.x]
  233. - mat.Element[(iPx + 0) + (iPy + 2) * mat.Size.x] * 2
  234. - mat.Element[(iPx + 0) + (iPy + 3) * mat.Size.x];
  235. var gY = mat.Element[(iPx + 1) + (iPy + 4) * mat.Size.x] //梯度90度
  236. + mat.Element[(iPx + 2) + (iPy + 4) * mat.Size.x] * 2
  237. + mat.Element[(iPx + 3) + (iPy + 4) * mat.Size.x]
  238. - mat.Element[(iPx + 1) + (iPy + 0) * mat.Size.x]
  239. - mat.Element[(iPx + 2) + (iPy + 0) * mat.Size.x] * 2
  240. - mat.Element[(iPx + 3) + (iPy + 0) * mat.Size.x];
  241. float root2 = 1.4142135623730950488016887242097f;
  242. var gXY = mat.Element[(iPx + 3) + (iPy + 4) * mat.Size.x] //x0y0向x2y2方向的斜率, 45度
  243. + mat.Element[(iPx + 4) + (iPy + 4) * mat.Size.x]
  244. + mat.Element[(iPx + 4) + (iPy + 3) * mat.Size.x]
  245. - mat.Element[(iPx + 1) + (iPy + 0) * mat.Size.x]
  246. - mat.Element[(iPx + 0) + (iPy + 0) * mat.Size.x]
  247. - mat.Element[(iPx + 0) + (iPy + 1) * mat.Size.x];
  248. gXY *= root2;
  249. var gYX = mat.Element[(iPx + 1) + (iPy + 4) * mat.Size.x] //x2y0向x0y2方向的斜率, 135度
  250. + mat.Element[(iPx + 0) + (iPy + 4) * mat.Size.x]
  251. + mat.Element[(iPx + 0) + (iPy + 3) * mat.Size.x]
  252. - mat.Element[(iPx + 3) + (iPy + 0) * mat.Size.x]
  253. - mat.Element[(iPx + 4) + (iPy + 0) * mat.Size.x]
  254. - mat.Element[(iPx + 4) + (iPy + 1) * mat.Size.x];
  255. gYX *= root2;
  256. float[] gra = new float[] { MathF.Abs(gX), MathF.Abs(gY), MathF.Abs(gXY), MathF.Abs(gYX) };
  257. var maxIndex = o0.MaxIndex(gra);
  258. pixelC[i] = gra[maxIndex];
  259. switch (maxIndex)
  260. {
  261. case 0:
  262. pixelDir[i] = gX > 0 ? 0 : 180;
  263. break;
  264. case 1:
  265. pixelDir[i] = gY > 0 ? 90 : 270;
  266. break;
  267. case 2:
  268. pixelDir[i] = gXY > 0 ? 45 : 225;
  269. break;
  270. case 3:
  271. pixelDir[i] = gYX > 0 ? 135 : 315;
  272. break;
  273. }
  274. //pixelC[i] = MathF.Abs(gX) + MathF.Abs(gY) + MathF.Abs(gXY) + MathF.Abs(gYX);
  275. /*
  276. if (pixelC[i] / 9f < 1.0f / 256f)
  277. {
  278. pixelC[i] = 0;
  279. return;
  280. }/**/
  281. /*
  282. if (sum < 100f/256f)
  283. {
  284. pixelC[i] = 0;
  285. return;
  286. }/**/
  287. //pixelC[i] = o0.Max(MathF.Abs(gX), MathF.Abs(gY), MathF.Abs(gXY), MathF.Abs(gYX));
  288. //pixelC[i] /= MathF.Pow(sum / 9, 0.1f);
  289. //pixelC[i] /= min + 0.5f;
  290. //pixelC[i] /= min + 0.1f;
  291. pixelC[i] /= sum / 9f + 1f;//+1是为了防止除数太小,结果不合理地过大
  292. });
  293. return (convolution.Map(ignoreExtremum: 10), dirMat);
  294. }
  295. }
  296. }