PhaseExtractionIntent.cs 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032
  1. using OpenCvSharp;
  2. using PaintDotNet.Base;
  3. using PaintDotNet.Base.Enum;
  4. using PaintDotNet.Base.Functionodel;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Drawing;
  8. using System.Linq;
  9. namespace PaintDotNet.Adjust
  10. {
  11. /// <summary>
  12. /// 物相提取的处理程序
  13. /// </summary>
  14. public unsafe class PhaseExtractionIntent
  15. {
  16. /// <summary>
  17. /// 中间变量
  18. /// </summary>
  19. private static Mat phaseTemp;
  20. /// <summary>
  21. /// 中间变量
  22. /// </summary>
  23. private static Mat phaseTemp1;
  24. /// <summary>
  25. /// 中间变量
  26. /// </summary>
  27. private static Mat phaseTemp2;
  28. /// <summary>
  29. /// 视场Mat
  30. /// </summary>
  31. private static Mat viewMat;
  32. /// <summary>
  33. /// 相颜色
  34. /// </summary>
  35. private static Vec4b vec4B;
  36. /// <summary>
  37. /// 透明的颜色
  38. /// </summary>
  39. private static Vec4b vec4BTransparent = new Vec4b(0,0,0,0);
  40. /// <summary>
  41. /// RGB/HLS的范围值
  42. /// </summary>
  43. private static int item0L, item0R, item1L, item1R, item2L, item2R;
  44. /// <summary>
  45. /// 目标选择
  46. /// </summary>
  47. private static FieldOfViewParameters targetSelection;
  48. /// <summary>
  49. /// 定义物体
  50. /// </summary>
  51. private static DefineObjectsParameters defineObjects = DefineObjectsParameters.Click;
  52. /// <summary>
  53. /// 定义物体->点击->容许值
  54. /// </summary>
  55. private static int allowable = 0;
  56. /// <summary>
  57. /// 定义物体->点击->范围大小
  58. /// </summary>
  59. private static int scopeSize = 0;
  60. /// <summary>
  61. /// 定义物体->轮廓,默认多边形
  62. /// </summary>
  63. private static ContourParameters shape = ContourParameters.Polygon;
  64. /// <summary>
  65. /// 删除边界对象
  66. /// </summary>
  67. private static bool deleteBoundaryObject = false;
  68. /// <summary>
  69. /// 孔洞填充
  70. /// </summary>
  71. private static bool holeFilling = false;
  72. /// <summary>
  73. /// 碎屑删除
  74. /// </summary>
  75. private static bool debrisRemoval = false;
  76. /// <summary>
  77. /// 碎屑面积起
  78. /// </summary>
  79. private static int debrisAreaStart = 0;
  80. /// <summary>
  81. /// 碎屑面积止
  82. /// </summary>
  83. private static int debrisAreaEnd = 0;
  84. /// <summary>
  85. /// 二值样式
  86. /// </summary>
  87. private static StyleParameters binaryType;
  88. /// <summary>
  89. /// 目标选择
  90. /// </summary>
  91. private static ProcessingParameters targetProcess;
  92. /// <summary>
  93. /// RGB/HLS 默认0 rgb
  94. /// </summary>
  95. private static int rgborhls = 0;
  96. /// <summary>
  97. /// 单个目标,偏差
  98. /// </summary>
  99. private static int deviation = 0;
  100. #region 无视场
  101. /// <summary>
  102. /// 【无视场】二值操作-物相提取
  103. /// </summary>
  104. /// <param name="src">源图像</param>
  105. /// <param name="lists">参数集合</param>
  106. /// <returns></returns>
  107. public static Mat ImagePhaseExtraction(Mat src, PhaseModel phase, System.Drawing.Point point, List<Args> lists)
  108. {
  109. if (phase == null)
  110. return src;
  111. Mat returnValue = new Mat();
  112. Color color = Color.FromArgb(phase.color);
  113. vec4B = new Vec4b(color.B, color.G, color.R, 255);
  114. //整个图像的参数
  115. List<Args> whole = lists[0].choiseList[0].lists;
  116. //单个目标的参数
  117. List<Args> single = lists[0].choiseList[1].lists;
  118. //提取模式->整个图像
  119. bool wholeObject = (bool)(lists[0].choiseList[0].value);
  120. //提取模式->单个目标
  121. bool singleObject = (bool)(lists[0].choiseList[1].value);
  122. //目标选择
  123. targetSelection = (FieldOfViewParameters)lists[0].choiseList[2].Value;
  124. //二值样式
  125. binaryType = (StyleParameters)lists[0].choiseList[0].Lists[1].Value;
  126. //目标选择
  127. targetProcess = (ProcessingParameters)lists[0].choiseList[0].Lists[2].Value;
  128. //整个图像
  129. if (wholeObject)
  130. {
  131. //定义物体,点击或轮廓
  132. //bool click = (bool)lists[0].choiseList[0].lists.Find(a => a.Key.Equals("defineObject")).choiseList[0].Value;
  133. bool profile = (bool)lists[0].choiseList[0].lists.Find(a => a.Key.Equals("defineObject")).choiseList[1].Value;
  134. defineObjects = profile ? DefineObjectsParameters.Profile : DefineObjectsParameters.Click;
  135. //定义物体->点击->容许值
  136. allowable = (int)((lists[0].choiseList[0].Lists[0].choiseList[0].Lists[0])).Value;
  137. //定义物体->点击->范围大小
  138. scopeSize = (int)((lists[0].choiseList[0].Lists[0].choiseList[0].Lists[1])).Value;
  139. //定义物体->轮廓
  140. shape = (ContourParameters)lists[0].choiseList[0].Lists[0].choiseList[1].lists[0].Value;
  141. //删除边界对象
  142. deleteBoundaryObject = (bool)whole[3].Value;
  143. //孔洞填充
  144. holeFilling = (bool)whole[4].Value;
  145. //碎屑删除
  146. debrisRemoval = (bool)whole[5].Value;
  147. //碎屑面积
  148. debrisAreaStart = (int)(((List<double>)lists[0].choiseList[0].Lists[6].Value)[0]);
  149. debrisAreaEnd = (int)(((List<double>)lists[0].choiseList[0].Lists[6].Value)[1]);
  150. //rgb或hls
  151. rgborhls = ((bool)whole[7].choiseList[0].Value) ? 0 : 1;
  152. //RGB/HLS的值区间
  153. item2L = (int)(((List<double>)whole[7].choiseList[0].Lists[0].Value)[0]);
  154. item2R = (int)(((List<double>)whole[7].choiseList[0].Lists[0].Value)[1]);
  155. item1L = (int)(((List<double>)whole[7].choiseList[0].Lists[1].Value)[0]);
  156. item1R = (int)(((List<double>)whole[7].choiseList[0].Lists[1].Value)[1]);
  157. item0L = (int)(((List<double>)whole[7].choiseList[0].Lists[2].Value)[0]);
  158. item0R = (int)(((List<double>)whole[7].choiseList[0].Lists[2].Value)[1]);
  159. }
  160. //提取单个目标的参数列表
  161. if (singleObject)
  162. {
  163. deviation = (int)single[0].Value;
  164. }
  165. if (wholeObject)
  166. {
  167. returnValue = WholeExtract(src);
  168. }
  169. if (singleObject)
  170. {
  171. returnValue = SingleExtract(src, phase.mat, point);
  172. }
  173. return returnValue;
  174. }
  175. /// <summary>
  176. /// 点击时的整个提取
  177. /// </summary>
  178. /// <param name="source"></param>
  179. /// <returns></returns>
  180. public static Mat WholeExtract(Mat source)
  181. {
  182. //原始轮廓信息
  183. OpenCvSharp.Point[][] contours;
  184. //轮廓的拓扑信息
  185. HierarchyIndex[] hierachy;
  186. //删除的对象的索引
  187. List<int> deleteIndexs = new List<int>();
  188. //二值提取
  189. phaseTemp1 = new Mat(source.Rows, source.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
  190. //如果是rgb
  191. if (rgborhls == 0)
  192. {
  193. source.ForEachAsVec4b(ForeachFunctionByteForWhole4B);
  194. }
  195. else
  196. {
  197. source.ForEachAsVec3b(ForeachFunctionByteForWhole3B);
  198. }
  199. //寻找轮廓
  200. Cv2.FindContours(phaseTemp1.CvtColor(ColorConversionCodes.BGR2GRAY), out contours, out hierachy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone);
  201. //孔洞填充
  202. phaseTemp1 = HoleFilling(holeFilling, hierachy, contours, phaseTemp1);
  203. //寻找轮廓
  204. Cv2.FindContours(phaseTemp1.CvtColor(ColorConversionCodes.BGR2GRAY), out contours, out hierachy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone);
  205. //删除边界对象/碎屑删除
  206. DeleteContours(deleteBoundaryObject, debrisRemoval, contours, hierachy, debrisAreaStart, debrisAreaEnd, deleteIndexs, phaseTemp1);
  207. //过滤掉被删除的轮廓,对剩下的填充或绘制轮廓
  208. phaseTemp1 = FillOrDrawContours(phaseTemp1, contours, deleteIndexs, binaryType, vec4B, hierachy);
  209. return phaseTemp1;
  210. }
  211. /// <summary>
  212. /// 从全部轮廓中删除被移除的轮廓
  213. /// 根据条件绘制轮廓或填充轮廓
  214. /// </summary>
  215. /// <param name="src"></param>
  216. /// <param name="contours"></param>
  217. /// <param name="deleteIndexs"></param>
  218. /// <param name="binaryStyle"></param>
  219. /// <param name="phaseColor"></param>
  220. /// <param name="hierachy"></param>
  221. /// <returns></returns>
  222. private static Mat FillOrDrawContours(Mat src, OpenCvSharp.Point[][] contours,
  223. List<int> deleteIndexs, StyleParameters binaryStyle, OpenCvSharp.Vec4b phaseColor, HierarchyIndex[] hierachy)
  224. {
  225. //创建一个新mat
  226. src = new Mat(src.Size(), src.Type(), new Scalar(0, 0, 0, 0));
  227. //src.EmptyClone();
  228. //用于绘制的轮廓
  229. List<OpenCvSharp.Point[]> drawContours = contours.ToList<OpenCvSharp.Point[]>();
  230. //循环处理轮廓,过滤到被删除的轮廓及其子轮廓
  231. if (deleteIndexs.Count > 0)
  232. {
  233. drawContours.Clear();
  234. for (int i = 0; i < contours.Length; i++)
  235. {
  236. if (!deleteIndexs.Exists(a => a == i))// && !deleteIndexs.Exists(a => a == hierachy[i].Parent)
  237. {
  238. drawContours.Add(contours[i]);
  239. }
  240. }
  241. }
  242. //二值样式 1实心 2边线
  243. if (binaryStyle == StyleParameters.Solid)
  244. {
  245. Cv2.FillPoly(src, drawContours, new Scalar(phaseColor.Item0, phaseColor.Item1, phaseColor.Item2, 255), LineTypes.Link8);
  246. }
  247. else
  248. {
  249. Cv2.DrawContours(src, drawContours, -1, new Scalar(phaseColor.Item0, phaseColor.Item1, phaseColor.Item2, 255), 1);
  250. }
  251. return src;
  252. }
  253. public unsafe static void ForeachFunctionByteForWhole4B(Vec4b* t, int* position)
  254. {
  255. int y = position[0];
  256. int x = position[1];
  257. //如果是删除
  258. if (targetProcess == ProcessingParameters.Delete)
  259. {
  260. phaseTemp1.Set<Vec4b>(y, x, vec4BTransparent);
  261. }
  262. if ((t->Item0 >= item0L && t->Item0 <= item0R)
  263. && (t->Item1 >= item1L && t->Item1 <= item1R)
  264. && (t->Item2 >= item2L && t->Item2 <= item2R))
  265. {
  266. phaseTemp1.Set<Vec4b>(y, x, vec4B);
  267. }
  268. }
  269. public unsafe static void ForeachFunctionByteForWhole3B(Vec3b* t, int* position)
  270. {
  271. int y = position[0];
  272. int x = position[1];
  273. //如果是删除
  274. if (targetProcess == ProcessingParameters.Delete)
  275. {
  276. phaseTemp1.Set<Vec4b>(y, x, vec4BTransparent);
  277. }
  278. if ((t->Item0 >= item0L && t->Item0 <= item0R)
  279. && (t->Item1 >= item1L && t->Item1 <= item1R)
  280. && (t->Item2 >= item2L && t->Item2 <= item2R))
  281. {
  282. phaseTemp1.Set<Vec4b>(y, x, vec4B);
  283. }
  284. }
  285. /// <summary>
  286. /// 单个目标的提取
  287. /// </summary>
  288. /// <param name="source">源图像</param>
  289. /// <param name="point">鼠标点击位置</param>
  290. /// <param name="vec4b">相颜色</param>
  291. /// <returns></returns>
  292. public static Mat SingleExtract(Mat source, Mat phase, System.Drawing.Point point)
  293. {
  294. try
  295. {
  296. if (phase == null)
  297. {
  298. phaseTemp1 = new Mat(source.Rows, source.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
  299. }
  300. else
  301. {
  302. phase.CopyTo(phaseTemp1);
  303. }
  304. phaseTemp = new Mat(source.Rows + 2, source.Cols + 2, MatType.CV_8U, Scalar.All(0));
  305. Mat sourceTemp = new Mat();
  306. source.CopyTo(sourceTemp);
  307. sourceTemp = sourceTemp.CvtColor(ColorConversionCodes.BGRA2BGR);
  308. Rect rect = new Rect();
  309. Cv2.FloodFill(sourceTemp, phaseTemp, new OpenCvSharp.Point(point.X, point.Y), new Scalar(255), out rect, new Scalar(deviation, deviation, deviation), new Scalar(deviation, deviation, deviation), FloodFillFlags.Link8 | FloodFillFlags.FixedRange | FloodFillFlags.MaskOnly);
  310. //二值样式 1实心 2边线
  311. if (binaryType == StyleParameters.Sideline)
  312. {
  313. Mat nowTemp1 = new Mat(source.Rows, source.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
  314. //原始轮廓信息
  315. OpenCvSharp.Point[][] contours;
  316. //轮廓的拓扑信息
  317. HierarchyIndex[] hierachy;
  318. //去掉外边的2个像素
  319. //Mat roi = new Mat(phaseTemp, new Rect(1, 1, source.Width, source.Height));
  320. phaseTemp.ForEachAsByte(ForeachFunctionByteForChoise);
  321. Cv2.FindContours(phaseTemp1.CvtColor(ColorConversionCodes.BGRA2GRAY), out contours, out hierachy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone);
  322. Cv2.DrawContours(nowTemp1, contours, -1, new Scalar(vec4B.Item0, vec4B.Item1, vec4B.Item2, 255), 1);
  323. nowTemp1.CopyTo(phaseTemp1);
  324. }
  325. else
  326. {
  327. /*if(phase!=null)
  328. {
  329. //原始轮廓信息
  330. OpenCvSharp.Point[][] contours;
  331. //轮廓的拓扑信息
  332. HierarchyIndex[] hierachy;
  333. //寻找轮廓信息
  334. Cv2.FindContours(phase.CvtColor(ColorConversionCodes.BGR2GRAY), out contours, out hierachy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone);
  335. List<List<OpenCvSharp.Point>> lists = new List<List<OpenCvSharp.Point>>();
  336. foreach (OpenCvSharp.Point[] points in contours)
  337. {
  338. lists.Add(points.ToList<OpenCvSharp.Point>());
  339. }
  340. //填充轮廓
  341. Cv2.FillPoly(phaseTemp, lists, new Scalar(vec4B.Item0, vec4B.Item1, vec4B.Item2, 255), LineTypes.Link8);
  342. }*/
  343. phaseTemp.ForEachAsByte(ForeachFunctionByteForChoise);
  344. }
  345. }
  346. catch (Exception)
  347. {
  348. }
  349. finally
  350. {
  351. if (phaseTemp != null && !phaseTemp.IsDisposed) phaseTemp.Dispose();
  352. }
  353. return phaseTemp1;
  354. }
  355. /// <summary>
  356. /// 单个目标的提取
  357. /// </summary>
  358. /// <param name="value"></param>
  359. /// <param name="position"></param>
  360. public unsafe static void ForeachFunctionByteForChoise(byte* value, int* position)
  361. {
  362. int y = position[0];
  363. int x = position[1];
  364. byte intencity = *value;
  365. if (intencity == 1 && x > 0 && y > 0 && x < phaseTemp.Width - 1 && y < phaseTemp.Height - 1)
  366. {
  367. phaseTemp1.Set<Vec4b>(y - 1, x - 1, vec4B);
  368. }
  369. }
  370. /// <summary>
  371. /// 孔洞填充
  372. /// </summary>
  373. /// <param name="holeFilling"></param>
  374. /// <param name="hierachy"></param>
  375. /// <param name="contours"></param>
  376. /// <param name="src"></param>
  377. /// <returns></returns>
  378. private static Mat HoleFilling(bool holeFilling, HierarchyIndex[] hierachy,
  379. OpenCvSharp.Point[][] contours, Mat src)
  380. {
  381. if (holeFilling && hierachy != null)
  382. {
  383. for (int i = 0; i < hierachy.Length; i++)
  384. {
  385. //如果需要还可以判断面积范围
  386. if (hierachy[i].Parent > -1)
  387. {
  388. List<List<OpenCvSharp.Point>> ps = new List<List<OpenCvSharp.Point>>();
  389. ps.Add(contours[i].ToList());
  390. Cv2.FillPoly(src, ps, new Scalar(255, 0, 0, 255));
  391. }
  392. }
  393. }
  394. return src;
  395. }
  396. /// <summary>
  397. /// 删除边界对象 以及 碎屑删除
  398. /// </summary>
  399. /// <param name="deleteBoundaryObject">是否删除边界对象</param>
  400. /// <param name="debrisRemoval">是否删除碎屑</param>
  401. /// <param name="contours">轮廓</param>
  402. /// <param name="hierachy">结构</param>
  403. /// <param name="debrisAreaStart">碎屑面积</param>
  404. /// <param name="debrisAreaEnd">碎屑面积</param>
  405. /// <param name="deleteIndexs">被删除的轮廓的下标</param>
  406. /// <param name="src">源</param>
  407. public static void DeleteContours(bool deleteBoundaryObject, bool debrisRemoval,
  408. OpenCvSharp.Point[][] contours, HierarchyIndex[] hierachy,
  409. int debrisAreaStart, int debrisAreaEnd, List<int> deleteIndexs, Mat src)
  410. {
  411. if ((deleteBoundaryObject || debrisRemoval) && contours != null)
  412. {
  413. if (contours.Length > 0)
  414. {
  415. for (int i = 0; i < contours.Length; i++)
  416. {
  417. bool delete = false;
  418. if (debrisRemoval)
  419. {
  420. double area = Cv2.ContourArea(contours[i]);
  421. if (area >= debrisAreaStart && area <= debrisAreaEnd && hierachy[i].Parent == -1)
  422. {
  423. deleteIndexs.Add(i);
  424. List<OpenCvSharp.Point[]> pointsTemp = new List<OpenCvSharp.Point[]>();
  425. RecursiveFindChildContours(contours.ToList(), hierachy, i, deleteIndexs);
  426. delete = true;
  427. }
  428. }
  429. if (deleteBoundaryObject && !delete)
  430. {
  431. for (int y = 0; y < contours[i].Length; y++)
  432. {
  433. if (contours[i][y].X == 0 || contours[i][y].X == src.Width-1 || contours[i][y].Y == 0 || contours[i][y].Y == src.Height-1)
  434. {
  435. deleteIndexs.Add(i);
  436. List<OpenCvSharp.Point[]> pointsTemp = new List<OpenCvSharp.Point[]>();
  437. RecursiveFindChildContours(contours.ToList(), hierachy, i, deleteIndexs);
  438. break;
  439. }
  440. }
  441. }
  442. }
  443. }
  444. }
  445. }
  446. #endregion
  447. #region 有视场
  448. public static Mat ImagePhaseExtractionWithView(Mat hls, Mat rgb, Mat origin, PhaseModel phase, System.Drawing.Point point, List<Args> lists)
  449. {
  450. viewMat = hls;
  451. Mat returnValue = new Mat();
  452. Color color = Color.FromArgb(phase.color);
  453. vec4B = new Vec4b(color.B, color.G, color.R, 255);
  454. //整个图像的参数
  455. List<Args> whole = lists[0].choiseList[0].lists;
  456. //单个目标的参数
  457. List<Args> single = lists[0].choiseList[1].lists;
  458. //提取模式->整个图像
  459. bool wholeObject = (bool)(lists[0].choiseList[0].value);
  460. //提取模式->单个目标
  461. bool singleObject = (bool)(lists[0].choiseList[1].value);
  462. //目标选择
  463. targetSelection = (FieldOfViewParameters)lists[0].choiseList[2].Value;
  464. //二值样式
  465. binaryType = (StyleParameters)lists[0].choiseList[0].Lists[1].Value;
  466. //目标选择
  467. targetProcess = (ProcessingParameters)lists[0].choiseList[0].Lists[2].Value;
  468. //整个图像
  469. if (wholeObject)
  470. {
  471. //定义物体,点击或轮廓
  472. //bool click = (bool)lists[0].choiseList[0].lists.Find(a => a.Key.Equals("defineObject")).choiseList[0].Value;
  473. bool profile = (bool)lists[0].choiseList[0].lists.Find(a => a.Key.Equals("defineObject")).choiseList[1].Value;
  474. defineObjects = profile ? DefineObjectsParameters.Profile : DefineObjectsParameters.Click;
  475. //定义物体->点击->容许值
  476. allowable = (int)((lists[0].choiseList[0].Lists[0].choiseList[0].Lists[0])).Value;
  477. //定义物体->点击->范围大小
  478. scopeSize = (int)((lists[0].choiseList[0].Lists[0].choiseList[0].Lists[1])).Value;
  479. //定义物体->轮廓
  480. shape = (ContourParameters)lists[0].choiseList[0].Lists[0].choiseList[1].lists[0].Value;
  481. //删除边界对象
  482. deleteBoundaryObject = (bool)whole[3].Value;
  483. //孔洞填充
  484. holeFilling = (bool)whole[4].Value;
  485. //碎屑删除
  486. debrisRemoval = (bool)whole[5].Value;
  487. //碎屑面积
  488. debrisAreaStart = (int)(((List<double>)lists[0].choiseList[0].Lists[6].Value)[0]);
  489. debrisAreaEnd = (int)(((List<double>)lists[0].choiseList[0].Lists[6].Value)[1]);
  490. //rgb或hls
  491. rgborhls = ((bool)whole[7].choiseList[0].Value) ? 0 : 1;
  492. //RGB/HLS的值区间
  493. item2L = (int)(((List<double>)whole[7].choiseList[0].Lists[0].Value)[0]);
  494. item2R = (int)(((List<double>)whole[7].choiseList[0].Lists[0].Value)[1]);
  495. item1L = (int)(((List<double>)whole[7].choiseList[0].Lists[1].Value)[0]);
  496. item1R = (int)(((List<double>)whole[7].choiseList[0].Lists[1].Value)[1]);
  497. item0L = (int)(((List<double>)whole[7].choiseList[0].Lists[2].Value)[0]);
  498. item0R = (int)(((List<double>)whole[7].choiseList[0].Lists[2].Value)[1]);
  499. }
  500. //提取单个目标的参数列表
  501. if (singleObject)
  502. {
  503. deviation = (int)single[0].Value;
  504. }
  505. if (wholeObject)
  506. {
  507. returnValue = WholeExtractView(hls, phase.mat, rgb);
  508. }
  509. if (singleObject)
  510. {
  511. returnValue = SingleExtractView(hls, phase.mat, point);
  512. }
  513. return returnValue;
  514. }
  515. /// <summary>
  516. /// 点击时的整个提取
  517. /// </summary>
  518. /// <param name="view">视场mat,rgb或hls</param>
  519. /// <param name="matBin">if(rgb){ 原图的mat }else if(hls){ rgba视场的mat }</param>
  520. /// <returns></returns>
  521. public static Mat WholeExtractView(Mat hls, Mat rgb, Mat origin)
  522. {
  523. //原图内轮廓信息
  524. OpenCvSharp.Point[][] originContours;
  525. //原图内轮廓的拓扑信息
  526. HierarchyIndex[] originHierachy;
  527. //原始轮廓信息
  528. OpenCvSharp.Point[][] contours;
  529. //轮廓的拓扑信息
  530. HierarchyIndex[] hierachy;
  531. //删除的对象的索引
  532. List<int> deleteIndexs = new List<int>();
  533. //二值提取
  534. phaseTemp = new Mat(hls.Rows, hls.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
  535. phaseTemp1 = new Mat(hls.Rows, hls.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
  536. phaseTemp2 = origin;
  537. if (rgborhls==0)
  538. {
  539. origin.ForEachAsVec4b(ForeachFunctionByteForWholeWithView4B);
  540. }
  541. else
  542. {
  543. hls.ForEachAsVec3b(ForeachFunctionByteForWholeWithView3B);
  544. }
  545. //Cv2.ImShow("原", phaseTemp);
  546. //原图mat寻找轮廓
  547. Cv2.FindContours(phaseTemp.CvtColor(ColorConversionCodes.BGR2GRAY), out originContours, out originHierachy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone);
  548. //寻找轮廓
  549. Cv2.FindContours(phaseTemp1.CvtColor(ColorConversionCodes.BGR2GRAY), out contours, out hierachy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone);
  550. //孔洞填充
  551. phaseTemp1 = HoleFillingWithView(holeFilling, hierachy, contours, phaseTemp1, vec4B);
  552. //寻找轮廓
  553. Cv2.FindContours(phaseTemp1.CvtColor(ColorConversionCodes.BGR2GRAY), out contours, out hierachy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone);
  554. //删除边界对象/碎屑删除
  555. DeleteContoursWithView(deleteBoundaryObject, debrisRemoval, contours, hierachy, debrisAreaStart, debrisAreaEnd, deleteIndexs, phaseTemp1);
  556. //过滤掉被删除的轮廓,对剩下的填充或绘制轮廓
  557. phaseTemp1 = FillOrDrawContoursWithView(holeFilling, phaseTemp1, contours, originContours, deleteIndexs, binaryType, vec4B, hierachy, originHierachy, targetSelection);
  558. return phaseTemp1;
  559. }
  560. /// <summary>
  561. /// 单个目标的提取
  562. /// </summary>
  563. /// <param name="source">源图像</param>
  564. /// <param name="point">鼠标点击位置</param>
  565. /// <param name="vec4b">相颜色</param>
  566. /// <returns></returns>
  567. public static Mat SingleExtractView(Mat source, Mat phase, System.Drawing.Point point)
  568. {
  569. try
  570. {
  571. if (phase == null)
  572. {
  573. phaseTemp1 = new Mat(source.Rows, source.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
  574. }
  575. else
  576. {
  577. phase.CopyTo(phaseTemp1);
  578. }
  579. phaseTemp = new Mat(source.Rows + 2, source.Cols + 2, MatType.CV_8U, Scalar.All(0));
  580. Mat sourceTemp = new Mat();
  581. source.CopyTo(sourceTemp);
  582. sourceTemp = sourceTemp.CvtColor(ColorConversionCodes.BGRA2BGR);
  583. Rect rect = new Rect();
  584. Cv2.FloodFill(sourceTemp, phaseTemp, new OpenCvSharp.Point(point.X, point.Y), new Scalar(255), out rect, new Scalar(deviation, deviation, deviation), new Scalar(deviation, deviation, deviation), FloodFillFlags.Link8 | FloodFillFlags.FixedRange | FloodFillFlags.MaskOnly);
  585. phaseTemp.ForEachAsByte(ForeachFunctionByteForChoiseWithView);
  586. }
  587. catch (Exception)
  588. {
  589. }
  590. finally
  591. {
  592. if (phaseTemp != null && !phaseTemp.IsDisposed) phaseTemp.Dispose();
  593. }
  594. return phaseTemp1;
  595. }
  596. public unsafe static void ForeachFunctionByteForChoiseWithView(byte* value, int* position)
  597. {
  598. int y = position[0];
  599. int x = position[1];
  600. byte intencity = *value;
  601. if (intencity == 1 && x > 0 && y > 0 && x < phaseTemp.Width - 1 && y < phaseTemp.Height - 1)
  602. {
  603. if(viewMat.At<Vec4b>(y - 1, x - 1)[3]>0)
  604. phaseTemp1.Set<Vec4b>(y - 1, x - 1, vec4B);
  605. }
  606. }
  607. public unsafe static void ForeachFunctionByteForWholeWithView4B(Vec4b* t, int* position)
  608. {
  609. int y = position[0];
  610. int x = position[1];
  611. //如果是删除
  612. if (targetProcess == ProcessingParameters.Delete)
  613. {
  614. phaseTemp1.Set<Vec4b>(y, x, vec4BTransparent);
  615. }
  616. //如果不透明则进行处理
  617. //if (t->Item3 > 0)
  618. {
  619. if ((t->Item0 >= item0L && t->Item0 <= item0R)
  620. && (t->Item1 >= item1L && t->Item1 <= item1R)
  621. && (t->Item2 >= item2L && t->Item2 <= item2R))
  622. {
  623. phaseTemp.Set<Vec4b>(y, x, vec4B);
  624. if (t->Item3 > 0)
  625. phaseTemp1.Set<Vec4b>(y, x, vec4B);
  626. }
  627. }
  628. }
  629. public unsafe static void ForeachFunctionByteForWholeWithView3B(Vec3b* t, int* position)
  630. {
  631. int y = position[0];
  632. int x = position[1];
  633. //如果是删除
  634. if (targetProcess == ProcessingParameters.Delete)
  635. {
  636. phaseTemp1.Set<Vec4b>(y, x, vec4BTransparent);
  637. }
  638. Vec4b m4b = phaseTemp2.At<Vec4b>(y, x);
  639. //如果不透明则进行处理
  640. //if (m4b.Item3 > 0)
  641. {
  642. if ((t->Item0 >= item0L && t->Item0 <= item0R)
  643. && (t->Item1 >= item1L && t->Item1 <= item1R)
  644. && (t->Item2 >= item2L && t->Item2 <= item2R))
  645. {
  646. phaseTemp.Set<Vec4b>(y, x, vec4B);
  647. if (m4b.Item3 > 0)
  648. phaseTemp1.Set<Vec4b>(y, x, vec4B);
  649. }
  650. }
  651. }
  652. /// <summary>
  653. /// 孔洞填充
  654. /// </summary>
  655. /// <param name="holeFilling"></param>
  656. /// <param name="hierachy"></param>
  657. /// <param name="contours"></param>
  658. /// <param name="src"></param>
  659. /// <param name="phaseColor"></param>
  660. /// <returns></returns>
  661. private static Mat HoleFillingWithView(bool holeFilling, HierarchyIndex[] hierachy,
  662. OpenCvSharp.Point[][] contours, Mat src, Vec4b phaseColor)
  663. {
  664. if (holeFilling && hierachy != null)
  665. {
  666. for (int i = 0; i < hierachy.Length; i++)
  667. {
  668. //如果需要还可以判断面积范围
  669. if (hierachy[i].Parent > -1)
  670. {
  671. List<List<OpenCvSharp.Point>> ps = new List<List<OpenCvSharp.Point>>();
  672. ps.Add(contours[i].ToList());
  673. Cv2.FillPoly(src, ps, new Scalar(phaseColor.Item0, phaseColor.Item1, phaseColor.Item2, 255));
  674. }
  675. }
  676. }
  677. return src;
  678. }
  679. /// <summary>
  680. /// 删除边界对象 以及 碎屑删除
  681. /// </summary>
  682. /// <param name="deleteBoundaryObject">是否删除边界对象</param>
  683. /// <param name="debrisRemoval">是否删除碎屑</param>
  684. /// <param name="contours">轮廓</param>
  685. /// <param name="hierachy">结构</param>
  686. /// <param name="debrisAreaStart">碎屑面积</param>
  687. /// <param name="debrisAreaEnd">碎屑面积</param>
  688. /// <param name="deleteIndexs">被删除的轮廓的下标</param>
  689. /// <param name="src">源</param>
  690. public static void DeleteContoursWithView(bool deleteBoundaryObject, bool debrisRemoval,
  691. OpenCvSharp.Point[][] contours, HierarchyIndex[] hierachy,
  692. int debrisAreaStart, int debrisAreaEnd, List<int> deleteIndexs, Mat src)
  693. {
  694. if ((deleteBoundaryObject || debrisRemoval) && contours != null)
  695. {
  696. if (contours.Length > 0)
  697. {
  698. for (int i = 0; i < contours.Length; i++)
  699. {
  700. bool delete = false;
  701. if (debrisRemoval)
  702. {
  703. double area = Cv2.ContourArea(contours[i]);
  704. if (area > debrisAreaStart && area < debrisAreaEnd && hierachy[i].Parent == -1)
  705. {
  706. deleteIndexs.Add(i);
  707. RecursiveFindChildContours(contours.ToList(), hierachy, i, deleteIndexs);
  708. delete = true;
  709. }
  710. }
  711. if (deleteBoundaryObject && !delete)
  712. {
  713. for (int y = 0; y < contours[i].Length; y++)
  714. {
  715. if (contours[i][y].X == 0 || contours[i][y].X == src.Width-1 || contours[i][y].Y == 0 || contours[i][y].Y == src.Height-1)
  716. {
  717. deleteIndexs.Add(i);
  718. RecursiveFindChildContours(contours.ToList(), hierachy, i, deleteIndexs);
  719. break;
  720. }
  721. }
  722. }
  723. }
  724. }
  725. }
  726. }
  727. /// <summary>
  728. /// 从全部轮廓中删除被移除的轮廓
  729. /// 根据条件绘制轮廓或填充轮廓
  730. /// </summary>
  731. /// <param name="src"></param>
  732. /// <param name="contours">视场图轮廓</param>
  733. /// <param name="originContours">原图轮廓</param>
  734. /// <param name="deleteIndexs"></param>
  735. /// <param name="binaryStyle"></param>
  736. /// <param name="phaseColor"></param>
  737. /// <param name="hierachy"></param>
  738. /// <param name="targetSelection">目标选择</param>
  739. /// <returns></returns>
  740. private static Mat FillOrDrawContoursWithView(bool holeFilling, Mat src, OpenCvSharp.Point[][] contours, OpenCvSharp.Point[][] originContours,
  741. List<int> deleteIndexs, StyleParameters binaryStyle, Vec4b phaseColor, HierarchyIndex[] hierachy, HierarchyIndex[] originHierachy, FieldOfViewParameters targetSelection)
  742. {
  743. if(src==null)
  744. src = new Mat(phaseTemp1.Size(), phaseTemp1.Type(), new Scalar(0, 0, 0, 0));
  745. //创建一个新mat
  746. //Mat src = new Mat(temp.Size(), temp.Type(), new Scalar(0, 0, 0, 0));
  747. //用于绘制的轮廓
  748. List<OpenCvSharp.Point[]> drawContours = contours.ToList<OpenCvSharp.Point[]>();
  749. //用于绘制的轮廓对应的关系
  750. List<HierarchyIndex> hierachys = new List<HierarchyIndex>();
  751. //处理目标选择,以及过滤到被删除的轮廓及其子轮廓
  752. drawContours = CalcContoursByTargetSelection(holeFilling, deleteIndexs, drawContours, hierachy, originContours, originHierachy, targetSelection);
  753. if(drawContours.Count == 0) drawContours = contours.ToList<OpenCvSharp.Point[]>();
  754. //二值样式 1实心 2边线
  755. if (binaryStyle == StyleParameters.Solid)
  756. {
  757. Cv2.FillPoly(src, drawContours, new Scalar(phaseColor.Item0, phaseColor.Item1, phaseColor.Item2, 255));
  758. }
  759. else
  760. {
  761. Cv2.DrawContours(src, drawContours, -1, new Scalar(phaseColor.Item0, phaseColor.Item1, phaseColor.Item2, 255), 1);
  762. }
  763. return src;
  764. }
  765. /// <summary>
  766. /// 根据目标选择参数进行轮廓的筛选
  767. /// </summary>
  768. /// <param name="drawContours">经过筛选的视场图内的轮廓</param>
  769. /// <param name="originContours">原图二值化后的所有轮廓</param>
  770. /// <returns></returns>
  771. private static List<OpenCvSharp.Point[]> CalcContoursByTargetSelection(bool holeFilling, List<int> deleteIndexs, List<OpenCvSharp.Point[]> drawContours, HierarchyIndex[] hierachy, OpenCvSharp.Point[][] originContours, HierarchyIndex[] originHierachy, FieldOfViewParameters targetSelection)
  772. {
  773. List<OpenCvSharp.Point[]> points = new List<OpenCvSharp.Point[]>();
  774. List<OpenCvSharp.Point[]> originPoints = originContours.ToList<OpenCvSharp.Point[]>();
  775. if (targetSelection == FieldOfViewParameters.One)
  776. {
  777. int k = 0;
  778. foreach (OpenCvSharp.Point[] ps in drawContours)
  779. {
  780. if (deleteIndexs.Count > 0)
  781. {
  782. if (deleteIndexs.Exists(a => a == k))
  783. {
  784. k++;
  785. continue;
  786. }
  787. }
  788. foreach (OpenCvSharp.Point[] os in originPoints)
  789. {
  790. if (Cv2.PointPolygonTest(os, ps[0], false) >= 0)
  791. {
  792. if (Cv2.ContourArea(ps, false) == Cv2.ContourArea(os, false))
  793. {
  794. if (hierachy[k].Parent == -1)
  795. {
  796. points.Add(ps);
  797. List<OpenCvSharp.Point[]> pointsTemp = new List<OpenCvSharp.Point[]>();
  798. RecursiveFindChildContours(drawContours, hierachy, k, pointsTemp);
  799. points.AddRange(pointsTemp);
  800. }
  801. }
  802. }
  803. }
  804. k++;
  805. }
  806. }
  807. else if (targetSelection == FieldOfViewParameters.Two)
  808. {
  809. if (deleteIndexs.Count > 0)
  810. {
  811. for (int i = 0; i < drawContours.Count; i++)
  812. {
  813. if (!deleteIndexs.Exists(a => a == i) && !deleteIndexs.Exists(a => a == hierachy[i].Parent))
  814. {
  815. points.Add(drawContours[i]);
  816. }
  817. }
  818. }
  819. else
  820. {
  821. points = drawContours;
  822. }
  823. }
  824. else if (targetSelection == FieldOfViewParameters.Three)
  825. {
  826. List<int> smallInt = new List<int>();
  827. List<int> bigInt = new List<int>();
  828. int k = 0;
  829. foreach (OpenCvSharp.Point[] ps in drawContours)
  830. {
  831. int f = 0;
  832. if (deleteIndexs.Count > 0)
  833. {
  834. if (deleteIndexs.Exists(a => a == k))
  835. {
  836. k++;
  837. continue;
  838. }
  839. }
  840. foreach (OpenCvSharp.Point[] os in originPoints)
  841. {
  842. if (Cv2.PointPolygonTest(os, ps[0], false) >= 0 && hierachy[k].Parent == -1)
  843. {
  844. if (Cv2.ContourArea(ps, false) == Cv2.ContourArea(os, false))
  845. {
  846. if (originHierachy[f].Parent == -1)
  847. {
  848. if (!smallInt.Exists(a => a == k))
  849. {
  850. smallInt.Add(k);
  851. points.Add(ps);
  852. if (!holeFilling)
  853. {
  854. List<OpenCvSharp.Point[]> pointsTemp = new List<OpenCvSharp.Point[]>();
  855. RecursiveFindChildContours(drawContours, hierachy, k, pointsTemp);
  856. points.AddRange(pointsTemp);
  857. }
  858. }
  859. }
  860. }
  861. else
  862. {
  863. if (originHierachy[f].Parent == -1)
  864. {
  865. if (!bigInt.Exists(a => a == f))
  866. {
  867. bigInt.Add(f);
  868. points.Add(os);
  869. if (!holeFilling)
  870. {
  871. List<OpenCvSharp.Point[]> pointsTemp = new List<OpenCvSharp.Point[]>();
  872. RecursiveFindChildContours(originPoints, originHierachy, f, pointsTemp);
  873. points.AddRange(pointsTemp);
  874. }
  875. }
  876. }
  877. }
  878. }
  879. f++;
  880. }
  881. k++;
  882. }
  883. }
  884. return points;
  885. }
  886. #endregion
  887. #region 公共递归方法
  888. /// <summary>
  889. /// 递归处理
  890. /// </summary>
  891. /// <param name="drawContours"></param>
  892. /// <param name="hierachy"></param>
  893. /// <param name="position"></param>
  894. /// <param name="points"></param>
  895. private static void RecursiveFindChildContours(
  896. List<OpenCvSharp.Point[]> drawContours,
  897. HierarchyIndex[] hierachy,
  898. int position,
  899. List<OpenCvSharp.Point[]> points
  900. )
  901. {
  902. int m = 0;
  903. foreach (HierarchyIndex index in hierachy)
  904. {
  905. if (index.Parent == position)
  906. {
  907. points.Add(drawContours[m]);
  908. RecursiveFindChildContours(drawContours, hierachy, m, points);
  909. }
  910. m++;
  911. }
  912. }
  913. /// <summary>
  914. /// 递归处理
  915. /// </summary>
  916. /// <param name="drawContours"></param>
  917. /// <param name="hierachy"></param>
  918. /// <param name="position"></param>
  919. /// <param name="points"></param>
  920. private static void RecursiveFindChildContours(
  921. List<OpenCvSharp.Point[]> drawContours,
  922. HierarchyIndex[] hierachy,
  923. int position,
  924. List<int> points
  925. )
  926. {
  927. int m = 0;
  928. foreach (HierarchyIndex index in hierachy)
  929. {
  930. if (index.Parent == position)
  931. {
  932. points.Add(m);
  933. RecursiveFindChildContours(drawContours, hierachy, m, points);
  934. }
  935. m++;
  936. }
  937. }
  938. #endregion
  939. #region 无视场删除
  940. #endregion
  941. #region 有视场删除
  942. #endregion
  943. }
  944. }