XiGaoTools.cs 45 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231
  1. using OpenCvSharp;
  2. using SmartCoalApplication.Base.AuxiliaryCalcModel;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Text;
  7. using System.Threading.Tasks;
  8. namespace SmartCoalApplication.Base.CommTool
  9. {
  10. public class XiGaoTools
  11. {
  12. public static Mat temp;
  13. public static int start, end;
  14. private static double threshold = 85;
  15. /// <summary>
  16. /// 寻找构件
  17. /// </summary>
  18. /// <returns></returns>
  19. public static List<XiGaoHModel> FindXiGaoHModels(Mat thresholdMat)
  20. {
  21. OpenCvSharp.Point[][] contours;
  22. HierarchyIndex[] hierarchy;
  23. Cv2.FindContours(thresholdMat, out contours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point());
  24. //List<OpenCvSharp.Point[]> contoursDraw = new List<Point[]>();
  25. List<XiGaoHModel> list = new List<XiGaoHModel>();
  26. for (int i = 0; i < contours.Length; i++)
  27. {
  28. if (hierarchy[i].Parent == -1 && contours[i].Length > 500)
  29. {
  30. XiGaoHModel model = new XiGaoHModel();
  31. model.SetPoints(contours[i]);
  32. list.Add(model);
  33. }
  34. }
  35. if (list.Count == 0 || list.Count == 1) return list;
  36. List<XiGaoHModel> list_final = new List<XiGaoHModel>();
  37. XiGaoHModel m = list[list.IndexOf(list.Find(b => b.topPoint.Y == list.Min(a => a.topPoint.Y)))];
  38. list.Remove(m);
  39. if (m.topPoint.Y == 0)
  40. {//过滤顶部的亮条
  41. m = list[list.IndexOf(list.Find(b => b.topPoint.Y == list.Min(a => a.topPoint.Y)))];
  42. list.Remove(m);
  43. }
  44. list_final.Add(m);
  45. list_final.Add(list[list.IndexOf(list.Find(b => b.topPoint.Y == list.Min(a => a.topPoint.Y)))]);
  46. //for (int i = 0; i < list_final.Count; i++)
  47. //{
  48. // XiGaoHModel mDraw = list_final[i];
  49. // contoursDraw.Add(mDraw.points);
  50. //}
  51. //Mat thresholdMatClone = thresholdMat.Clone();
  52. //Cv2.DrawContours(thresholdMatClone, contoursDraw.ToArray(), -1, new Scalar(127), 2);
  53. //Cv2.ImWrite(@"C:\Users\54434\Desktop\thresholdMatClone.jpg", thresholdMatClone);
  54. return list_final;
  55. }
  56. /// <summary>
  57. /// 处理连接在一起的构件
  58. /// </summary>
  59. /// <param name="thresholdMat"></param>
  60. /// <param name="list_final"></param>
  61. /// <returns></returns>
  62. public static List<XiGaoHModel> FindXiGaoHModelsForConnState(Mat thresholdMat, List<XiGaoHModel> list_final)
  63. {
  64. int index = 0, y = 0;
  65. if (list_final[1].topPoint.Y < list_final[0].topPoint.Y)
  66. {
  67. index = 1;
  68. y = list_final[0].topPoint.Y;
  69. }
  70. if (list_final[index].topPoint.X > thresholdMat.Width / 2)
  71. {
  72. thresholdMat.Col[list_final[index].topPoint.X - 399] *= 0;
  73. thresholdMat.Col[list_final[index].topPoint.X - 400] *= 0;
  74. thresholdMat.Col[list_final[index].topPoint.X - 401] *= 0;
  75. }
  76. else
  77. {
  78. thresholdMat.Col[list_final[index].topPoint.X + 399] *= 0;
  79. thresholdMat.Col[list_final[index].topPoint.X + 400] *= 0;
  80. thresholdMat.Col[list_final[index].topPoint.X + 401] *= 0;
  81. }
  82. return FindXiGaoHModels(thresholdMat);
  83. }
  84. /// <summary>
  85. /// 移除小的联通区域 锡膏
  86. /// </summary>
  87. /// <param name="mat"></param>
  88. /// <returns></returns>
  89. public static Mat RemoveSmallConn(Mat mat, int area = 50)
  90. {
  91. Mat labels_left = new Mat();
  92. Mat stats_left = new Mat();
  93. Mat centroids_left = new Mat();
  94. Cv2.ConnectedComponentsWithStats(mat, labels_left, stats_left, centroids_left, PixelConnectivity.Connectivity8);
  95. Dictionary<int, int> keyValuePairs_left = new Dictionary<int, int>();
  96. for (int h = 1; h < centroids_left.Height; h++)
  97. {
  98. int width = stats_left.At<int>(h, 2);
  99. int areaField1 = stats_left.At<int>(h, 4);
  100. if ((0 <= areaField1 && areaField1 <= area))
  101. {
  102. keyValuePairs_left.Add(h, 1);
  103. }
  104. }
  105. for (int h = 1; h < labels_left.Height; h++)
  106. {
  107. for (int w = 1; w < labels_left.Width; w++)
  108. {
  109. byte v = labels_left.At<byte>(h, w);
  110. if (v > 0 && keyValuePairs_left.ContainsKey(v))
  111. {
  112. mat.Set<byte>(h, w, 0);
  113. }
  114. }
  115. }
  116. return mat;
  117. }
  118. /// <summary>
  119. /// 移除小的联通区域 锡膏Z
  120. /// </summary>
  121. /// <param name="mat"></param>
  122. /// <returns></returns>
  123. public static Mat RemoveSmallConnZ(Mat mat, int area = 50)
  124. {
  125. for(int h=0; h< mat.Height-1; h++)
  126. {
  127. for (int w = 0; w < mat.Width-1; w++)
  128. {
  129. int v = mat.At<byte>(h, w);
  130. if(v>128) mat.Set<byte>(h, w, 255);
  131. else mat.Set<byte>(h, w, 0);
  132. }
  133. }
  134. mat = mat.Dilate(null, null, 1);
  135. OpenCvSharp.Point[][] contours;
  136. HierarchyIndex[] hierarchy;
  137. Cv2.FindContours(mat, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point());
  138. Mat temp = new Mat(mat.Size(), mat.Type());
  139. Cv2.DrawContours(temp, contours, -1, new Scalar(255), 1, LineTypes.Link8);
  140. Mat aaa = new Mat(temp.Size(), MatType.CV_8UC3);
  141. for(int i=0; i< contours.Length; i++)
  142. {
  143. if(hierarchy[i].Parent==-1 && Cv2.ContourArea(contours[i]) <=30)
  144. {
  145. Cv2.FloodFill(mat, contours[i][0], new Scalar(0));
  146. }
  147. }
  148. /*
  149. Mat labels_left = new Mat();
  150. Mat stats_left = new Mat();
  151. Mat centroids_left = new Mat();
  152. Cv2.ConnectedComponentsWithStats(mat, labels_left, stats_left, centroids_left, PixelConnectivity.Connectivity8);
  153. Dictionary<int, int> keyValuePairs_left = new Dictionary<int, int>();
  154. for (int h = 1; h < centroids_left.Height; h++)
  155. {
  156. int width = stats_left.At<int>(h, 2);
  157. int areaField1 = stats_left.At<int>(h, 4);
  158. if ((0 <= areaField1 && areaField1 <= area))
  159. {
  160. keyValuePairs_left.Add(h, 1);
  161. }
  162. }
  163. for (int h = 1; h < labels_left.Height; h++)
  164. {
  165. for (int w = 1; w < labels_left.Width; w++)
  166. {
  167. byte v = labels_left.At<byte>(h, w);
  168. if (v > 0 && keyValuePairs_left.ContainsKey(v))
  169. {
  170. mat.Set<byte>(h, w, 0);
  171. }
  172. }
  173. }*/
  174. return mat;
  175. }
  176. /// <summary>
  177. /// 二值化寻找直线
  178. /// </summary>
  179. /// <param name="mat"></param>
  180. /// <returns></returns>
  181. public unsafe static List<int> FindLinesInThreshold(Mat mat, int topy, int topx, int type, XiGaoHModel model)
  182. {
  183. List<int> lines = new List<int>();
  184. for (int i = 100; i < 255; i += 3)
  185. {
  186. start = 100;
  187. end = i;
  188. temp = new Mat(mat.Size(), mat.Type(), Scalar.All(0));
  189. mat.ForEachAsByte(FindLinesInThreshold_For);
  190. foreach (int p in lines)
  191. {
  192. for (int a = 0; a < temp.Width; a++)
  193. {
  194. if (temp.At<byte>(p, a) > 0)
  195. Cv2.FloodFill(temp, new Point(a, p), Scalar.All(0));
  196. }
  197. }
  198. if (temp.CountNonZero() > 0)
  199. {
  200. Mat labels = new Mat();
  201. for (int h = topy; h < mat.Height - 2; h += 2)
  202. {
  203. if (type == 1)
  204. {
  205. Mat temp1 = new Mat(temp, new OpenCvSharp.Rect(topx - 400, h, 400, 3));
  206. int v = temp1.CountNonZero();
  207. if (v > 200 && temp1.ConnectedComponents(labels, PixelConnectivity.Connectivity8) < 10)
  208. {
  209. if (model.lowY - h > 9)
  210. {
  211. lines.Add(h);
  212. h += 8;
  213. }
  214. }
  215. }
  216. else
  217. {
  218. Mat temp1 = new Mat(temp, new OpenCvSharp.Rect(topx, h, 400, 3));
  219. int v = temp1.CountNonZero();
  220. if (v > 200 && temp1.ConnectedComponents(labels, PixelConnectivity.Connectivity8) < 10)
  221. {
  222. if (model.lowY - h > 9)
  223. {
  224. lines.Add(h);
  225. h += 8;
  226. }
  227. }
  228. }
  229. }
  230. }
  231. }
  232. return lines;
  233. }
  234. private static unsafe void FindLinesInThreshold_For(byte* value, int* position)
  235. {
  236. int y = position[0];
  237. int x = position[1];
  238. byte v = *value;
  239. if (v > 85 && v <= end)
  240. temp.Set<byte>(y, x, 255);
  241. else
  242. temp.Set<byte>(y, x, 0);
  243. }
  244. public static void SamplePic1(Mat koutu_left, Mat koutu_right, XiGaoHModel left, XiGaoHModel right, int threshold, out Mat mask_left, out Mat mask_right)
  245. {
  246. for (int i = left.topPoint.X; i < koutu_left.Width; i++)
  247. koutu_left.Col[i] *= 0;
  248. for (int i = 0; i < left.topPoint.Y + 150; i++)
  249. koutu_left.Row[i] *= 0;
  250. for (int i = 0; i < right.topPoint.X; i++)
  251. koutu_right.Col[i] *= 0;
  252. for (int i = 0; i < right.topPoint.Y + 150; i++)
  253. koutu_right.Row[i] *= 0;
  254. mask_left = koutu_left.Threshold(threshold, 255, ThresholdTypes.Binary);
  255. mask_right = koutu_right.Threshold(threshold, 255, ThresholdTypes.Binary);
  256. mask_left = null;
  257. mask_right = null;
  258. }
  259. public unsafe static Mat SamplePic1(Mat gray, double thres = 85)
  260. {
  261. threshold = thres;
  262. Mat clone = gray.Clone();
  263. clone.ForEachAsByte(CommFillHoleEach);
  264. return clone;
  265. }
  266. public unsafe static Mat SamplePicZ(Mat gray, double thres = 85)
  267. {
  268. threshold = thres;
  269. Mat clone = gray.Clone();
  270. clone.ForEachAsByte(CommFillHoleEachZ);
  271. return clone;
  272. }
  273. /// <summary>
  274. /// 第二次裁剪图片
  275. /// </summary>
  276. /// <param name="koutu_left"></param>
  277. /// <param name="koutu_right"></param>
  278. /// <param name="left"></param>
  279. /// <param name="right"></param>
  280. /// <param name="threshold"></param>
  281. /// <param name="mask_left"></param>
  282. /// <param name="mask_right"></param>
  283. public unsafe static void SamplePic2(Mat koutu_left, Mat koutu_right, XiGaoHModel left, XiGaoHModel right, int threshold, out Mat mask_left, out Mat mask_right)
  284. {
  285. //二值提取
  286. mask_left = koutu_left.Threshold(0, 255, ThresholdTypes.Binary);
  287. mask_right = koutu_right.Threshold(0, 255, ThresholdTypes.Binary);
  288. //Cv2.ImWrite(@"C:\Users\zyh\Desktop\left_1.jpg", koutu_left);
  289. //Cv2.ImWrite(@"C:\Users\zyh\Desktop\right_1.jpg", koutu_right);
  290. //左侧
  291. OpenCvSharp.Point[][] contours;
  292. HierarchyIndex[] hierarchy;
  293. Cv2.FindContours(mask_left, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point());
  294. List<OpenCvSharp.Point[]> list_left = contours.ToList();
  295. Mat mask_l_1 = new Mat(mask_left.Size(), MatType.CV_8UC1);
  296. Cv2.DrawContours(mask_l_1, contours, -1, new Scalar(255), 1, LineTypes.Link8);
  297. int left_y = -1;
  298. for (int i = left.topPoint.Y + 150; i < mask_left.Height; i++)
  299. {
  300. if (mask_l_1.Row[i].CountNonZero() == 2)
  301. {
  302. left_y = i;
  303. break;
  304. }
  305. }
  306. if (left_y == -1) left_y = left.topPoint.Y + 200;
  307. Cv2.FindContours(mask_right, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point());
  308. List<OpenCvSharp.Point[]> list_right = contours.ToList();
  309. Mat mask_r_1 = new Mat(mask_left.Size(), MatType.CV_8UC1);
  310. Cv2.DrawContours(mask_r_1, contours, -1, new Scalar(255), 1, LineTypes.Link8);
  311. int right_y = -1;
  312. for (int i = right.topPoint.Y + 150; i < mask_right.Height; i++)
  313. {
  314. if (mask_r_1.Row[i].CountNonZero() == 2)
  315. {
  316. right_y = i;
  317. break;
  318. }
  319. }
  320. if (right_y == -1) right_y = right.topPoint.Y + 200;
  321. for (int i = 0; i < right_y; i++)
  322. {
  323. koutu_right.Row[i] *= 0;
  324. mask_right.Row[i] *= 0;
  325. }
  326. for (int i = 0; i < left_y; i++)
  327. {
  328. koutu_left.Row[i] *= 0;
  329. mask_left.Row[i] *= 0;
  330. }
  331. for (int i = 0; i < right.topPoint.X; i++)
  332. {
  333. koutu_right.Col[i] *= 0;
  334. mask_right.Col[i] *= 0;
  335. }
  336. for (int i = right.topPoint.X + 450; i < koutu_right.Width; i++)
  337. {
  338. koutu_right.Col[i] *= 0;
  339. mask_right.Col[i] *= 0;
  340. }
  341. for (int i = 0; i < left.topPoint.X - 450; i++)
  342. {
  343. koutu_left.Col[i] *= 0;
  344. mask_left.Col[i] *= 0;
  345. }
  346. for (int i = left.topPoint.X; i < koutu_left.Width; i++)
  347. {
  348. koutu_left.Col[i] *= 0;
  349. mask_left.Col[i] *= 0;
  350. }
  351. OpenCvSharp.Point small = new Point(-1, -1);
  352. Cv2.FindContours(koutu_left, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point());
  353. list_left = contours.ToList();
  354. if (contours.Length >= 2)
  355. {
  356. for (int i = list_left.Count - 1; i >= 0; i--)
  357. {
  358. if (list_left[i].Count() < 50 || list_left[i].ToList().FindAll(a => a.Y < left.topPoint.Y + 10).Count > 0)
  359. {
  360. Cv2.FloodFill(mask_left, list_left[i][0], new Scalar(0));
  361. list_left.RemoveAt(i);
  362. }
  363. }
  364. }
  365. contours = list_left.ToArray();
  366. if (contours.Length >= 2)
  367. {
  368. int maxy = 0;
  369. for (int i = list_left.Count - 1; i >= 0; i--)
  370. {
  371. if (maxy == 0)
  372. {
  373. maxy = list_left[i].Max(a => a.Y);
  374. }
  375. else
  376. {
  377. if (maxy < list_left[i].Max(a => a.Y))
  378. {
  379. maxy = list_left[i].Max(a => a.Y);
  380. mask_left.FloodFill(list_left[i][0], new Scalar(0));
  381. list_left.RemoveAt(i);
  382. }
  383. }
  384. }
  385. }
  386. contours = list_left.ToArray();
  387. if (contours.Length == 0) return;
  388. if (contours.Length >= 2)
  389. {
  390. int countPoints = 0;
  391. if (contours.Length > 2)
  392. {
  393. countPoints = contours.ToList().Min(a => a.Length);
  394. }
  395. foreach (OpenCvSharp.Point[] p in contours)
  396. {
  397. if (contours.Length > 2)
  398. {
  399. if (p.Length == countPoints)
  400. {
  401. mask_left.FloodFill(p[0], new Scalar(0));
  402. break;
  403. }
  404. }
  405. List<OpenCvSharp.Point> ps = p.ToList();
  406. if (left.lowY == 0)
  407. {
  408. left.lowY = ps.Max(a => a.Y);
  409. }
  410. else
  411. {
  412. if (left.lowY < ps.Max(a => a.Y))
  413. left.lowY = ps.Max(a => a.Y);
  414. }
  415. if (left.highY == 0)
  416. {
  417. left.highY = ps.Min(a => a.Y);
  418. left.highX = ps.ToList().Find(a => a.Y == left.highY).X;
  419. }
  420. else
  421. {
  422. if (left.highY > ps.Min(a => a.Y))
  423. {
  424. left.highY = ps.Min(a => a.Y);
  425. left.highX = ps.ToList().Find(a => a.Y == left.highY).X;
  426. }
  427. }
  428. if (small.X == -1)
  429. {
  430. small = ps.Find(b => b.Y == ps.Min(a => a.Y));
  431. }
  432. else
  433. {
  434. OpenCvSharp.Point t = ps.Find(b => b.Y == ps.Min(a => a.Y));
  435. if (t.Y < small.Y)
  436. {
  437. small = t;
  438. }
  439. }
  440. left.centerX = (ps.Min(a => a.X) + ps.Max(a => a.X)) / 2;
  441. if (left.centerX < left.highX)
  442. {
  443. left.centerOffSetHighY = ps.Where(a => a.X < left.centerX - 110).ToList().Min(b => b.Y);
  444. left.centerOffSetHighX = ps.Where(a => a.X < left.centerX - 110).ToList().Find(b => b.Y == left.centerOffSetHighY).X;
  445. }
  446. }
  447. mask_left.FloodFill(small, new Scalar(0));
  448. }
  449. else
  450. {
  451. left.lowY = contours[0].Max(a => a.Y);
  452. left.highY = contours[0].Min(a => a.Y);
  453. left.highX = contours[0].ToList().Find(a => a.Y == left.highY).X;
  454. left.centerX = (contours[0].Min(a => a.X) + contours[0].Max(a => a.X)) / 2;
  455. if (left.centerX < left.highX)
  456. {
  457. left.centerOffSetHighY = contours[0].ToList().Where(a => a.X < left.centerX - 110).ToList().Min(b => b.Y);
  458. left.centerOffSetHighX = contours[0].Where(a => a.X < left.centerX - 110).ToList().Find(b => b.Y == left.centerOffSetHighY).X;
  459. }
  460. }
  461. small = new Point(-1, -1);
  462. Cv2.FindContours(mask_right, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point());
  463. list_right = contours.ToList();
  464. if (contours.Length >= 2)
  465. {
  466. for (int i = list_right.Count - 1; i >= 0; i--)
  467. {
  468. if (list_right[i].Count() < 50 || list_right[i].ToList().FindAll(a => a.Y < right.topPoint.Y + 10).Count > 0)
  469. {
  470. Cv2.FloodFill(mask_right, list_right[i][0], new Scalar(0));
  471. list_right.RemoveAt(i);
  472. }
  473. }
  474. }
  475. contours = list_right.ToArray();
  476. if (contours.Length == 0) return;
  477. if (contours.Length >= 2)
  478. {
  479. int maxy = 0;
  480. for (int i = list_right.Count - 1; i >= 0; i--)
  481. {
  482. if (maxy == 0)
  483. {
  484. maxy = list_right[i].Max(a => a.Y);
  485. }
  486. else
  487. {
  488. if (maxy < list_right[i].Max(a => a.Y))
  489. {
  490. maxy = list_right[i].Max(a => a.Y);
  491. mask_right.FloodFill(list_right[i][0], new Scalar(0));
  492. list_right.RemoveAt(i);
  493. }
  494. }
  495. }
  496. }
  497. contours = list_right.ToArray();
  498. if (contours.Length >= 2)
  499. {
  500. int countPoints = 0;
  501. if (contours.Length > 2)
  502. {
  503. countPoints = contours.ToList().Min(a => a.Length);
  504. }
  505. int k = 0;
  506. foreach (OpenCvSharp.Point[] p in contours)
  507. {
  508. if (hierarchy[k].Parent > -1)
  509. {
  510. break;
  511. }
  512. if (contours.Length > 2)
  513. {
  514. if (p.Length == countPoints)
  515. {
  516. mask_right.FloodFill(p[0], new Scalar(0));
  517. break;
  518. }
  519. }
  520. List<OpenCvSharp.Point> ps = p.ToList();
  521. if (right.lowY == 0)
  522. {
  523. right.lowY = ps.Max(a => a.Y);
  524. }
  525. else
  526. {
  527. if (right.lowY < ps.Max(a => a.Y))
  528. right.lowY = ps.Max(a => a.Y);
  529. }
  530. if (right.highY == 0)
  531. {
  532. right.highY = ps.Min(a => a.Y);
  533. right.highX = ps.ToList().Find(a => a.Y == right.highY).X;
  534. }
  535. else
  536. {
  537. if (right.highY > ps.Min(a => a.Y))
  538. {
  539. right.highY = ps.Min(a => a.Y);
  540. right.highX = ps.ToList().Find(a => a.Y == right.highY).X;
  541. }
  542. }
  543. if (small.X == -1)
  544. {
  545. small = ps.Find(b => b.Y == ps.Min(a => a.Y));
  546. }
  547. else
  548. {
  549. OpenCvSharp.Point t = ps.Find(b => b.Y == ps.Min(a => a.Y));
  550. if (t.Y < small.Y)
  551. {
  552. small = t;
  553. }
  554. }
  555. right.centerX = (ps.Min(a => a.X) + ps.Max(a => a.X)) / 2;
  556. if (right.centerX > right.highX)
  557. {
  558. right.centerOffSetHighY = ps.Where(a => a.X > right.centerX + 110).ToList().Min(b => b.Y);
  559. right.centerOffSetHighX = ps.Where(a => a.X > right.centerX + 110).ToList().Find(b => b.Y == right.centerOffSetHighY).X;
  560. }
  561. }
  562. mask_right.FloodFill(small, new Scalar(0));
  563. }
  564. else
  565. {
  566. right.lowY = contours[0].Max(a => a.Y);
  567. right.highY = contours[0].Min(a => a.Y);
  568. right.highX = contours[0].ToList().Find(a => a.Y == right.highY).X;
  569. right.centerX = (contours[0].Min(a => a.X) + contours[0].Max(a => a.X)) / 2;
  570. if (right.centerX > right.highX)
  571. {
  572. right.centerOffSetHighY = contours[0].ToList().Where(a => a.X > right.centerX + 110).ToList().Min(b => b.Y);
  573. right.centerOffSetHighX = contours[0].Where(a => a.X > right.centerX + 110).ToList().Find(b => b.Y == right.centerOffSetHighY).X;
  574. }
  575. }
  576. }
  577. private static unsafe void CommFillHoleEach(byte* value, int* position)
  578. {
  579. int y = position[0];
  580. int x = position[1];
  581. byte v = *value;
  582. if (v < 85 && v > 0)
  583. *value = 255;
  584. }
  585. private static unsafe void CommFillHoleEachZ(byte* value, int* position)
  586. {
  587. int y = position[0];
  588. int x = position[1];
  589. byte v = *value;
  590. if (v < threshold && v > 0)
  591. *value = 255;
  592. if (v==0)
  593. *value = 255;
  594. }
  595. /// <summary>
  596. ///
  597. /// </summary>
  598. /// <param name="mat"></param>
  599. /// <param name="type">1左 2右</param>
  600. /// <returns></returns>
  601. public static List<int> FindLastLine(List<int> list/*, List<int> prevList*/, Mat mat, int type, int width = 0, int times = 1)
  602. {
  603. int now_l = (width == 0) ? mat.Width - 1 : width;
  604. int now_r = width;
  605. if (type == 1)
  606. {
  607. int xleft = 0;
  608. for (int i = now_l; i >= 0; i--)
  609. {
  610. if (mat.Col[i].CountNonZero() == 4)
  611. {
  612. xleft = i;
  613. break;
  614. }
  615. }
  616. for (int i = 0; i < mat.Height - 1; i++)
  617. {
  618. if (mat.At<byte>(i, xleft) > 0)
  619. list.Add(i);
  620. }
  621. bool pass = true;
  622. if (list.Count == 4)
  623. {
  624. if (list[1] - list[0] <= 5 || list[2] - list[1] <= 5 || list[3] - list[2] <= 5)
  625. {
  626. pass = false;
  627. }
  628. }
  629. else
  630. {
  631. pass = false;
  632. }
  633. if (pass || times > 20)
  634. return list;// list.Count == 4 ? list : prevList;
  635. if (!pass)
  636. {
  637. //if (list.Count == 4)
  638. //{
  639. // prevList.Clear();
  640. // prevList.AddRange(list);
  641. //}
  642. list.Clear();
  643. FindLastLine(list/*, prevList*/, mat, 1, xleft - 1, ++times);
  644. }
  645. }
  646. else
  647. {
  648. int xright = 0;
  649. for (int i = now_r; i < mat.Width; i++)
  650. {
  651. if (mat.Col[i].CountNonZero() == 4)
  652. {
  653. xright = i;
  654. break;
  655. }
  656. }
  657. for (int i = 0; i < mat.Height - 1; i++)
  658. {
  659. if (mat.At<byte>(i, xright) > 0)
  660. list.Add(i);
  661. }
  662. bool pass = true;
  663. if (list.Count == 4)
  664. {
  665. if (list[1] - list[0] <= 5 || list[2] - list[1] <= 5 || list[3] - list[2] <= 5)
  666. {
  667. pass = false;
  668. }
  669. }
  670. else
  671. {
  672. pass = false;
  673. }
  674. if (pass || times > 20)
  675. return list;// list.Count == 4 ? list : prevList;// return list;
  676. if (!pass)
  677. {
  678. //if (list.Count == 4)
  679. //{
  680. // prevList.Clear();
  681. // prevList.AddRange(list);
  682. //}
  683. list.Clear();
  684. FindLastLine(list/*, prevList*/, mat, 2, xright + 1, ++times);
  685. }
  686. }
  687. //if (list.Count == 0 && prevList.Count == 4)
  688. // list.AddRange(prevList);
  689. return list;
  690. }
  691. /// <summary>
  692. ///
  693. /// </summary>
  694. /// <param name="mat"></param>
  695. /// <param name="type">1左 2右</param>
  696. /// <returns></returns>
  697. public static List<int> FindLastLine(List<int> list, List<int> prevList, Mat mat, int type, int width = 0, int times = 1)
  698. {
  699. int now_l = (width == 0) ? mat.Width - 1 : width;
  700. int now_r = width;
  701. if (type == 1)
  702. {
  703. int xleft = 0;
  704. for (int i = now_l; i >= 0; i--)
  705. {
  706. if (mat.Col[i].CountNonZero() == 4)
  707. {
  708. xleft = i;
  709. break;
  710. }
  711. }
  712. for (int i = 0; i < mat.Height - 1; i++)
  713. {
  714. if (mat.At<byte>(i, xleft) > 0)
  715. list.Add(i);
  716. }
  717. bool pass = true;
  718. if (list.Count == 4)
  719. {
  720. if (list[1] - list[0] <= 5 || list[2] - list[1] <= 5 || list[3] - list[2] <= 5)
  721. {
  722. pass = false;
  723. }
  724. }
  725. else
  726. {
  727. pass = false;
  728. }
  729. if (pass || times > 20)
  730. return list.Count == 4 ? list : prevList;// list;//
  731. if (!pass)
  732. {
  733. if (list.Count == 4)
  734. {
  735. prevList.Clear();
  736. prevList.AddRange(list);
  737. }
  738. list.Clear();
  739. FindLastLine(list, prevList, mat, 1, xleft - 1, ++times);
  740. }
  741. }
  742. else
  743. {
  744. int xright = 0;
  745. for (int i = now_r; i < mat.Width; i++)
  746. {
  747. if (mat.Col[i].CountNonZero() == 4)
  748. {
  749. xright = i;
  750. break;
  751. }
  752. }
  753. for (int i = 0; i < mat.Height - 1; i++)
  754. {
  755. if (mat.At<byte>(i, xright) > 0)
  756. list.Add(i);
  757. }
  758. bool pass = true;
  759. if (list.Count == 4)
  760. {
  761. if (list[1] - list[0] <= 5 || list[2] - list[1] <= 5 || list[3] - list[2] <= 5)
  762. {
  763. pass = false;
  764. }
  765. }
  766. else
  767. {
  768. pass = false;
  769. }
  770. if (pass || times > 20)
  771. return list.Count == 4 ? list : prevList;// return list;// list;//
  772. if (!pass)
  773. {
  774. if (list.Count == 4)
  775. {
  776. prevList.Clear();
  777. prevList.AddRange(list);
  778. }
  779. list.Clear();
  780. FindLastLine(list, prevList, mat, 2, xright + 1, ++times);
  781. }
  782. }
  783. if (list.Count == 0 && prevList.Count == 4)
  784. list.AddRange(prevList);
  785. return list;
  786. }
  787. public static void CClearDirtyData(Mat mat)
  788. {
  789. for (int i = mat.Height - 1; i >= 0; i--)
  790. {
  791. if (mat.Row[i].CountNonZero() > 0 && mat.Row[i].CountNonZero() < 20)
  792. {
  793. mat.Row[i] *= 0;
  794. }
  795. }
  796. }
  797. public unsafe static Mat ReverseNoneZeroPixel(Mat mat)
  798. {
  799. mat.ForEachAsByte(ReverseNoneZeroPixel_AsByte);
  800. mat = mat.Erode(null, null, 1);
  801. return mat;
  802. }
  803. private unsafe static void ReverseNoneZeroPixel_AsByte(byte* value, int* position)
  804. {
  805. int y = position[0];
  806. int x = position[1];
  807. byte v = *value;
  808. if (v > 0)
  809. {
  810. *value = (byte)(255 - v);
  811. /* byte j = (byte)(255 - v);
  812. if(j>150)
  813. *value = 0;
  814. else if (j < 47)
  815. *value = 0;*/
  816. }
  817. }
  818. public static List<int> FindAllLine(Mat koutu_left_canny, XiGaoHModel model, int lastLine, int offsetY = 23)
  819. {
  820. List<int> final = new List<int>();
  821. List<int> xs = new List<int>();
  822. List<int> ys0 = new List<int>();
  823. //Dictionary<int, int> dict = new Dictionary<int, int>();
  824. //Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\canny_left_3T.jpg", koutu_left_canny);
  825. for (int i = lastLine - offsetY; i > model.topPoint.Y + 200; i--)
  826. {
  827. int v = koutu_left_canny.Row[i].CountNonZero();
  828. //if (v>0)
  829. {
  830. //dict.Add(i, v);
  831. xs.Add(i);
  832. ys0.Add(v);
  833. }
  834. }
  835. int[] hist_int = ys0.ToArray(); // HistTools.Smooth(ys.ToArray(), 10, ys.Count);
  836. List<int> temps = hist_int.ToList();
  837. int max = temps.Max(a => a);
  838. int max_index = temps.FindIndex(a => a == max);
  839. int h = 0;
  840. ////过滤3(11).jpg的强干扰
  841. //int ensureTimes = 0;
  842. ////int max_next = -1;// temps.FindIndex(a => a == max);
  843. ////for (int i = max_index + 15; i < temps.Count; i++)
  844. ////{
  845. //// if (temps[i] > 0)
  846. //// {
  847. //// max_next = i;
  848. //// break;
  849. //// }
  850. ////}
  851. //while (max_index > 20/*max_next == -1*/ && ++ensureTimes < 10)
  852. //{
  853. // hist_int[max_index] = 0;
  854. // temps[max_index] = 0;
  855. // max = temps.Max(a => a);
  856. // max_index = temps.FindIndex(a => a == max);
  857. // //max_next = -1;// temps.FindIndex(a => a == max);
  858. // //for (int i = max_index + 15; i < temps.Count; i++)
  859. // //{
  860. // // if (temps[i] > 0)
  861. // // {
  862. // // max_next = i;
  863. // // break;
  864. // // }
  865. // //}
  866. //}
  867. Console.WriteLine("max_index:" + max_index + "...offsetY:" + offsetY);
  868. for (int i = max_index; i >= 0; i--)
  869. {
  870. if (h > 10) break;
  871. h++;
  872. if (hist_int[i] > 0)
  873. {
  874. hist_int[i] = 0;
  875. }
  876. /*else
  877. {
  878. break;
  879. }*/
  880. }
  881. int g = 0;
  882. for (int i = max_index + 1; i < hist_int.Length - 1; i++)
  883. {
  884. if (g > 10) break;
  885. g++;
  886. if (hist_int[i] > 0)
  887. {
  888. hist_int[i] = 0;
  889. }
  890. /*else
  891. {
  892. break;
  893. }*/
  894. }
  895. if (max > 30 && Math.Abs(xs[max_index] - model.highY) >= 14)
  896. final.Add(xs[max_index]);
  897. temps = hist_int.ToList();
  898. max = temps.Max(a => a);
  899. max_index = temps.FindIndex(a => a == max);
  900. if (max > 30 && Math.Abs(xs[max_index] - model.highY) >= 14)
  901. final.Add(xs[max_index]);
  902. return final;
  903. }
  904. public static void DisposeMat(Mat mat)
  905. {
  906. if (mat != null && !mat.IsDisposed) mat.Dispose();
  907. }
  908. /// <summary>
  909. /// 处理旋转的图像
  910. /// </summary>
  911. /// <param name="thresholdMat"></param>
  912. /// <returns></returns>
  913. public static Mat ActioSpinXiGao(Mat gray)
  914. {
  915. Mat gray1 = gray.Clone();
  916. int left_top = Cv2.FloodFill(gray1, new Point(0, 0), new Scalar(0));
  917. int right_top = Cv2.FloodFill(gray1, new Point(gray.Width-1, 0), new Scalar(0));
  918. int right_bottom = Cv2.FloodFill(gray1, new Point(gray.Width - 1, gray.Height-1), new Scalar(0));
  919. int left_bottom = Cv2.FloodFill(gray1, new Point(0, gray.Height - 1), new Scalar(0));
  920. if (right_top == right_bottom && right_bottom == left_bottom)
  921. return gray1;
  922. return gray;
  923. }
  924. public static int FineTuningLastLine(int lineY, Mat gray)
  925. {
  926. int topY = lineY - 5;
  927. int bottomY = lineY + 1;
  928. List<int> means = new List<int>();
  929. List<int> ys = new List<int>();
  930. for (int i=topY; i< bottomY; i++)
  931. {
  932. means.Add((int)(gray.Row[i].Mean()));
  933. ys.Add(i);
  934. }
  935. int minY = lineY;
  936. int minV = means[5];
  937. for(int i=0; i< means.Count; i++)
  938. {
  939. if(Math.Abs(means[i] - minV) <13)
  940. {
  941. if (means[i] < minV)
  942. {
  943. minV = means[i];
  944. minY = ys[i];
  945. }
  946. }
  947. }
  948. return minY;
  949. }
  950. /// <summary>
  951. /// 寻找相似的轮廓
  952. /// </summary>
  953. /// <param name="lineY"></param>
  954. /// <param name="gray"></param>
  955. /// <returns></returns>
  956. public static Mat FindSimilarContour(Mat gray)
  957. {
  958. Mat mask = new Mat(gray.Size(), gray.Type());
  959. //计算直方图
  960. float[] hist_float = HistTools.CalcHist(gray);
  961. //直方图平滑
  962. int[] hist_int = HistTools.Smooth(hist_float, 25);
  963. //计算最佳阈值
  964. List<int> mountainsList = new List<int>();
  965. List<int[]> mountainsArrList = new List<int[]>();
  966. List<int[]> mountainsArrListBackUp = new List<int[]>();
  967. Tools.FindTopAndBetweenWithOutWT123(hist_int, 0, 255, mountainsList, mountainsArrList, mountainsArrListBackUp, new List<string>(), 15);
  968. int threshold = mountainsArrList[mountainsList.IndexOf(mountainsList.Min())][1] - 20;
  969. int thresholdValue = threshold < 100 ? 130 : threshold;
  970. //Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\grayMat.jpg", gray);
  971. //二值化
  972. Mat thresholdMat = gray.Threshold(thresholdValue/*-15*/, 255, ThresholdTypes.Binary);
  973. //Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\thresholdMat.jpg", thresholdMat);
  974. //碎屑删除
  975. thresholdMat = thresholdMat.Dilate(null, null, 3);
  976. //Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\thresholdMat_1.jpg", thresholdMat);
  977. thresholdMat = BinaryTools.DebrisRemoval_New(thresholdMat.CvtColor(ColorConversionCodes.GRAY2BGR), 200).CvtColor(ColorConversionCodes.BGR2GRAY);
  978. //Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\thresholdMat_2.jpg", thresholdMat);
  979. //寻找需要处理的内容
  980. OpenCvSharp.Point[][] contours;
  981. HierarchyIndex[] hierarchy;
  982. List<XiGaoZModel> models = new List<XiGaoZModel>();
  983. Cv2.FindContours(thresholdMat, out contours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxNone, new OpenCvSharp.Point());
  984. Mat temp = new Mat(thresholdMat.Size(), thresholdMat.Type(), Scalar.All(0));
  985. Cv2.DrawContours(temp, contours, -1, new Scalar(255), 3, LineTypes.Link8);
  986. //Cv2.ImWrite(@"C:\Users\zyh\Desktop\temp.jpg", temp);
  987. for (int i = 0; i < contours.Length; i++)
  988. {
  989. int height = contours[i].Max(a => a.Y) - contours[i].Min(a => a.Y);
  990. int width = contours[i].Max(a => a.X) - contours[i].Min(a => a.X);
  991. float ratio = height * 1f / width;
  992. if (contours[i].Length > 150 && Cv2.ContourArea(contours[i])>5000
  993. && height > 90
  994. && width < gray.Width - 50
  995. && (ratio>0.5 && ratio<0.9))
  996. {//筛选用于分析的锡膏
  997. XiGaoZModel model = new XiGaoZModel();
  998. model.SetPoints(contours[i]);
  999. models.Add(model);
  1000. }
  1001. }
  1002. //List<XiGaoZModel> models_toCal = new List<XiGaoZModel>();
  1003. //for (int i = 0; i < models.Count; i++)
  1004. // if (models[i].points.Length > 100 && models[i].points.Length < 1000)
  1005. // {//筛选用于分析的锡膏
  1006. // XiGaoZModel model = new XiGaoZModel();
  1007. // model.SetPoints(models[i].points);
  1008. // models_toCal.Add(model);
  1009. // }
  1010. //if (models_toCal.Count < 2)
  1011. //{
  1012. // models_toCal.Clear();
  1013. // for (int i = 0; i < models.Count; i++)
  1014. // if (models[i].points.Length > 100)
  1015. // {//筛选用于分析的锡膏
  1016. // XiGaoZModel model = new XiGaoZModel();
  1017. // model.SetPoints(models[i].points);
  1018. // models_toCal.Add(model);
  1019. // }
  1020. //}
  1021. int maxV = 0;
  1022. int now_y = 0;
  1023. for (int i = gray.Height - 1; i >0; i-=10)
  1024. {
  1025. int count = models/*models_toCal*//*models*/.Count(a => a.topY < i && a.bottomY > i);
  1026. if (maxV == 0)
  1027. {//筛选用于分析的锡膏
  1028. now_y = i;
  1029. maxV = count;
  1030. }
  1031. else
  1032. {
  1033. if(count > maxV)
  1034. {
  1035. maxV = count;
  1036. now_y = i;
  1037. }
  1038. }
  1039. }
  1040. //筛选用于分析的锡膏
  1041. List<XiGaoZModel> temps = models/*models_toCal*//*models*/.FindAll(a => a.topY < now_y && a.bottomY > now_y);
  1042. var array = temps.Select(a => a.points).ToArray();
  1043. Cv2.DrawContours(mask, array, -1, new Scalar(255), -1, LineTypes.Link8);
  1044. //Mat mask222 = new Mat(gray.Size(), gray.Type());
  1045. //Cv2.DrawContours(mask222, array, -1, new Scalar(255), 5, LineTypes.Link8);
  1046. //Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\mask222.jpg", mask222);
  1047. return mask;
  1048. }
  1049. public static List<int> FindAllLineZ(Mat src, XiGaoZModel model, int offsetY = 23)
  1050. {
  1051. Mat mat = 255 - src;
  1052. //去碎屑
  1053. mat = RemoveSmallConnZ(mat.Erode(null, null, 1), src.Width>300 ? 30 : 10);
  1054. int hs = 5;
  1055. if(mat.Width<300)
  1056. {
  1057. mat = mat.Erode(null, null, 1);
  1058. }
  1059. List<int> final = new List<int>();
  1060. List<int> xs = new List<int>();
  1061. List<float> ys = new List<float>();
  1062. Dictionary<int, int> dict = new Dictionary<int, int>();
  1063. for (int i = (int)(mat.Height*0.92); i >= hs; i--)
  1064. {
  1065. int sum = (int)(mat[i, i + 1, 0, mat.Width].Sum());
  1066. int noneZeroCount = mat[i - hs, i, 0, mat.Width].CountNonZero();
  1067. if(noneZeroCount > src.Width)
  1068. {
  1069. final.Add(i);
  1070. i -= 2;// 5;// 2;// 5;
  1071. }
  1072. }
  1073. final.Sort();
  1074. while (final.Count > 2 && final[final.Count - 1] - final[final.Count - 1 - 1] < 10)
  1075. {
  1076. final.RemoveAt(final.Count - 1 - 1);
  1077. }
  1078. if (final.Count>2)
  1079. {
  1080. for(int i= final.Count-1; i>0; i--)
  1081. {
  1082. if(final[i] - final[i-1]<10)
  1083. {
  1084. if (i == 1 && Math.Max(final[i - 1], final[i]) < 20)
  1085. {
  1086. final.RemoveAt(i - 1);
  1087. break;
  1088. }
  1089. else
  1090. final.RemoveAt(i);
  1091. }
  1092. }
  1093. }
  1094. else if(final.Count == 1)
  1095. {
  1096. final.Clear();
  1097. final.Add((int)(src.Height * 0.9) - 3);
  1098. final.Add((int)(src.Height / 2) + 1);
  1099. }
  1100. else if(final.Count==0)
  1101. {
  1102. final.Add((int)(src.Height * 0.9) - 3);
  1103. final.Add((int)(src.Height /2 ) + 1);
  1104. }
  1105. if (final.Count == 2)
  1106. {
  1107. if (final[1] - final[0] > mat.Height / 2)
  1108. {
  1109. final.Insert(1, mat.Height / 2 + 20);
  1110. }
  1111. }
  1112. //顶部校验
  1113. if(final.Count == 3)
  1114. {
  1115. }
  1116. int v = mat.Row[final.Count - 1].CountNonZero();
  1117. for (int i= final[final.Count-1]; i> final[final.Count - 1] - 6; i--)
  1118. {
  1119. int d = mat.Row[i].CountNonZero();
  1120. if(d>v)
  1121. {
  1122. v = d;
  1123. final[final.Count - 1] = i;
  1124. }
  1125. }
  1126. return final;
  1127. }
  1128. }
  1129. }