BinaryExtractionIntent.cs 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772
  1. using OpenCvSharp;
  2. using PaintDotNet.Adjust.BaseImage;
  3. using PaintDotNet.Base;
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Drawing;
  7. namespace PaintDotNet.Adjust
  8. {
  9. /// <summary>
  10. /// 二值提取的处理程序
  11. /// </summary>
  12. public unsafe class BinaryExtractionIntent
  13. {
  14. /// <summary>
  15. /// 全局中间变量
  16. /// 不带视场的时候就是原图/二值图
  17. /// 带视场的时候就是原图/二值图
  18. /// </summary>
  19. public static Mat temp, temp_view;
  20. /// <summary>
  21. /// 用来存储透明图
  22. /// </summary>
  23. public static Mat alpha;
  24. /// <summary>
  25. /// 1个颜色区间还是2个
  26. /// </summary>
  27. public static int colorInterval;
  28. /// <summary>
  29. /// 1个颜色区间时的起始值
  30. /// </summary>
  31. public static int colorOneStart;
  32. /// <summary>
  33. /// 1个颜色区间时的结止值
  34. /// </summary>
  35. public static int colorOneEnd;
  36. /// <summary>
  37. /// 2个颜色区间时的第1个区间的起始值
  38. /// </summary>
  39. public static int colorTwoStart = 0;
  40. /// <summary>
  41. /// 2个颜色区间时的第1个区间的结止值
  42. /// </summary>
  43. public static int colorTwoEnd = 0;
  44. /// <summary>
  45. /// 2个颜色区间时的第2个区间的起始值
  46. /// </summary>
  47. public static int colorThreeStart = 0;
  48. /// <summary>
  49. /// 2个颜色区间时的第2个区间的起始值
  50. /// </summary>
  51. public static int colorThreeEnd = 0;
  52. //碎屑删除面积起
  53. public static int debrisAreaStart = 0;
  54. //碎屑删除面积止
  55. public static int debrisAreaEnd = 0;
  56. /// <summary>
  57. /// 默认相颜色
  58. /// </summary>
  59. public static Vec4b vec4B = new Vec4b(255, 0, 0, 255);
  60. /// <summary>
  61. /// 新增的参数,用于FloodFill方法
  62. /// </summary>
  63. public static Rect rect;
  64. /// <summary>
  65. /// 各个连通域的代表点
  66. /// </summary>
  67. public static List<OpenCvSharp.Point> points;
  68. /// <summary>
  69. /// 用来记录需要删除的连通区域的编号
  70. /// </summary>
  71. public static Dictionary<int, int> keyValuePairs = new Dictionary<int, int>();
  72. public static Mat rgb_ap;
  73. public static Mat temp_ap;
  74. #region 无视场 二值提取
  75. /// <summary>
  76. /// 二值操作-二值提取-无视场
  77. /// </summary>
  78. /// <param name="src">源图像</param>
  79. /// <param name="lists">参数集合</param>
  80. /// <returns></returns>
  81. public static Mat ImageBinaryExtraction(Mat src, List<Args> lists, bool findContours = false)
  82. {
  83. //以下是参数信息---------------------
  84. ///1个颜色区间还是2个
  85. colorInterval = 1;
  86. //第一个二值区间
  87. colorOneStart = 0;
  88. colorOneEnd = 0;
  89. //第二个二值区间
  90. colorTwoStart = 0;
  91. colorTwoEnd = 0;
  92. //第三个二值区间
  93. colorThreeStart = 0;
  94. colorThreeEnd = 0;
  95. //处理细节
  96. //删除边界对象
  97. bool deleteBoundaryObject = false;
  98. //孔洞填充
  99. bool holeFilling = false;
  100. //碎屑删除
  101. bool debrisRemoval = false;
  102. //碎屑删除面积起
  103. debrisAreaStart = 0;
  104. //碎屑删除面积止
  105. debrisAreaEnd = 0;
  106. //二值样式
  107. //1实心 2边线
  108. int binaryStyle = 0;
  109. //相颜色
  110. Color phaseColor = Color.Red;
  111. //目标选择
  112. int targetSelection = 1;
  113. for (int i = 0; i < lists.Count; i++)
  114. {
  115. Args args = lists[i];
  116. switch (args.Key)
  117. {
  118. case "colorInterval":
  119. {
  120. if (args.Value is Boolean)
  121. colorInterval = (Boolean)args.Value ? 2 : 1;
  122. else
  123. colorInterval = (int)args.Value;
  124. }
  125. break;
  126. case "scope1":
  127. colorOneStart = (int)((List<double>)args.Value)[0];
  128. colorOneEnd = (int)((List<double>)args.Value)[1];
  129. break;
  130. case "scope2":
  131. colorTwoStart = (int)((List<double>)args.Value)[0];
  132. colorTwoEnd = (int)((List<double>)args.Value)[1];
  133. break;
  134. case "scope3":
  135. colorThreeStart = (int)((List<double>)args.Value)[0];
  136. colorThreeEnd = (int)((List<double>)args.Value)[1];
  137. break;
  138. case "deleteBoundaryObject":
  139. deleteBoundaryObject = (bool)args.Value;
  140. break;
  141. case "holeFilling":
  142. holeFilling = (bool)args.Value;
  143. break;
  144. case "debrisRemoval":
  145. debrisRemoval = (bool)args.Value;
  146. break;
  147. case "binaryStyle":
  148. binaryStyle = (int)args.Value;
  149. break;
  150. case "phaseColor":
  151. phaseColor = Color.FromArgb((int)args.Value);
  152. break;
  153. case "targetSelection":
  154. targetSelection = (int)args.Value;
  155. break;
  156. case "scope4":
  157. debrisAreaStart = (int)((List<double>)args.Value)[0];
  158. debrisAreaEnd = (int)((List<double>)args.Value)[1];
  159. findContours = true;
  160. break;
  161. default:
  162. break;
  163. }
  164. }
  165. if (phaseColor.A < 1)//#21321
  166. phaseColor = Color.FromArgb(1, phaseColor.R, phaseColor.G, phaseColor.B);
  167. vec4B.Item0 = phaseColor.B;
  168. vec4B.Item1 = phaseColor.G;
  169. vec4B.Item2 = phaseColor.R;
  170. vec4B.Item3 = phaseColor.A;
  171. //中值滤波
  172. //Cv2.MedianBlur(src, src, 3);
  173. //二值提取
  174. src = Binarization(src);
  175. //删除边界对象
  176. if (deleteBoundaryObject)
  177. src = DeleteContours_New(src);
  178. //碎屑删除,参考冈萨雷斯,414,9.5.3,连通分量提取
  179. if (debrisRemoval && debrisAreaEnd > 0)
  180. src = DebrisRemoval_New(src);
  181. //孔洞填充,参考冈萨雷斯,413,9.5.2
  182. if (holeFilling)
  183. src = HoleFilling_New(src);
  184. //实心/边线,参考冈萨雷斯,412,9.5.1,边界提取
  185. if (binaryStyle == 2)
  186. {
  187. Cv2.Erode(src, temp, null);
  188. src = src - temp;
  189. src = BaseTools.MergeMatFromMatArr(src, vec4B);
  190. }
  191. return src;
  192. }
  193. /// <summary>
  194. /// 二值提取
  195. /// </summary>
  196. /// <param name="source">源</param>
  197. /// <param name="colorInterval">1个或2个颜色区间</param>
  198. /// <param name="colorOneStart"></param>
  199. /// <param name="colorOneEnd"></param>
  200. /// <param name="colorTwoStart"></param>
  201. /// <param name="colorTwoEnd"></param>
  202. /// <param name="colorThreeStart"></param>
  203. /// <param name="colorThreeEnd"></param>
  204. /// <returns></returns>
  205. private static Mat Binarization(Mat source)
  206. {
  207. Mat srcGray;
  208. if (source.Type() == MatType.CV_8UC1)
  209. {
  210. srcGray = source;
  211. }
  212. else
  213. {
  214. srcGray = source.CvtColor(ColorConversionCodes.BGR2GRAY);
  215. }
  216. temp = new Mat(source.Rows, source.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
  217. srcGray.ForEachAsByte(GrayForEachAsByte);
  218. return temp.Clone();
  219. }
  220. /// <summary>
  221. /// 并行循环
  222. /// </summary>
  223. /// <param name="value"></param>
  224. /// <param name="position"></param>
  225. private static void GrayForEachAsByte(byte* value, int* position)
  226. {
  227. int y = position[0];
  228. int x = position[1];
  229. byte v = *value;
  230. if (colorInterval == 1)
  231. {
  232. if (v >= colorOneStart && v <= colorOneEnd)
  233. {
  234. temp.Set<Vec4b>(y, x, vec4B);
  235. }
  236. }
  237. else
  238. {
  239. if ((v >= colorTwoStart && v <= colorTwoEnd) || (v >= colorThreeStart && v <= colorThreeEnd))
  240. {
  241. temp.Set<Vec4b>(y, x, vec4B);
  242. }
  243. }
  244. }
  245. /// <summary>
  246. /// 新版本删除边界
  247. /// </summary>
  248. /// <param name="src"></param>
  249. /// <returns></returns>
  250. private static Mat DeleteContours_New(Mat src)
  251. {
  252. Mat[] arr = src.Split();
  253. Mat rgb = BaseTools.MergeMatFromMatArr(arr);
  254. Mat temp_1 = arr[3].Clone();
  255. for (int h = 0; h < temp_1.Width; h++)
  256. {
  257. byte vec4B_top = temp_1.At<byte>(0, h);
  258. if (vec4B_top > 0)
  259. {
  260. Cv2.FloodFill(rgb, new OpenCvSharp.Point(h, 0), new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
  261. Cv2.FloodFill(temp_1, new OpenCvSharp.Point(h, 0), new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
  262. }
  263. }
  264. for (int h = 0; h < temp_1.Width; h++)
  265. {
  266. byte vec4B_bottom = temp_1.At<byte>(temp_1.Height - 1, h);
  267. if (vec4B_bottom > 0)
  268. {
  269. Cv2.FloodFill(rgb, new OpenCvSharp.Point(h, temp_1.Height - 1), new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
  270. Cv2.FloodFill(temp_1, new OpenCvSharp.Point(h, temp_1.Height - 1), new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
  271. }
  272. }
  273. for (int y = 0; y < temp_1.Height; y++)
  274. {
  275. Vec4b vec4B_top = temp_1.At<Vec4b>(y, 0);
  276. if (vec4B_top.Item3 > 0)
  277. {
  278. Cv2.FloodFill(rgb, new OpenCvSharp.Point(0, y), new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
  279. Cv2.FloodFill(temp_1, new OpenCvSharp.Point(0, y), new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
  280. }
  281. }
  282. for (int y = 0; y < temp_1.Height; y++)
  283. {
  284. byte vec4B_top = temp_1.At<byte>(y, temp_1.Width - 1);
  285. if (vec4B_top > 0)
  286. {
  287. Cv2.FloodFill(rgb, new OpenCvSharp.Point(temp_1.Width - 1, y), new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
  288. Cv2.FloodFill(temp_1, new OpenCvSharp.Point(temp_1.Width - 1, y), new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
  289. }
  290. }
  291. Mat[] mats = rgb.Split();
  292. arr[0] = mats[0];
  293. arr[1] = mats[1];
  294. arr[2] = mats[2];
  295. arr[3] = temp_1;
  296. Cv2.Merge(arr, src);
  297. return src;
  298. }
  299. /// <summary>
  300. /// 新孔洞填充,采用形态学填充
  301. /// </summary>
  302. /// <param name="src"></param>
  303. /// <returns></returns>
  304. private static Mat HoleFilling_New(Mat src)
  305. {
  306. Mat[] arr2 = src.Split();
  307. Mat matc = arr2[3];
  308. //去掉透明层
  309. Mat mat = src.CvtColor(ColorConversionCodes.BGRA2BGR);
  310. //填充孔洞
  311. mat = BaseTools.FillHole(mat, new Scalar(255-vec4B.Item0, 255 - vec4B.Item1, 255 - vec4B.Item2));
  312. matc = BaseTools.FillHole(matc, new Scalar(255));
  313. //循环处理
  314. mat.ForEachAsVec3b(RGBForEachAsByteForHoleFillingNew);
  315. Mat[] arr1 = mat.Split();
  316. arr2[0] = arr1[0];
  317. arr2[1] = arr1[1];
  318. arr2[2] = arr1[2];
  319. arr2[3] = matc;
  320. Cv2.Merge(arr2, src);
  321. return src;
  322. }
  323. private static void RGBForEachAsByteForHoleFillingNew(Vec3b* value, int* position)
  324. {
  325. int y = position[0];
  326. int x = position[1];
  327. if (value->Item0==255 && value->Item1==255 && value->Item2==255)
  328. {
  329. value->Item0 = vec4B.Item0;
  330. value->Item1 = vec4B.Item1;
  331. value->Item2 = vec4B.Item2;
  332. }
  333. }
  334. /// <summary>
  335. /// 新碎屑删除,使用连通分量找寻碎屑
  336. /// </summary>
  337. /// <param name="src"></param>
  338. /// <returns></returns>
  339. private static Mat DebrisRemoval_New(Mat src)
  340. {
  341. Mat[] arr = src.Split();
  342. rgb_ap = BaseTools.MergeMatFromMatArr(arr);
  343. temp_ap = arr[3].Clone();
  344. //寻找连通分量
  345. Mat labelMat = new Mat();
  346. Mat stats = new Mat();
  347. Mat centroids = new Mat();
  348. int nonenum = Cv2.ConnectedComponentsWithStats(temp_ap, labelMat, stats, centroids, PixelConnectivity.Connectivity8);
  349. //寻找在范围内需要删除的碎屑
  350. keyValuePairs.Clear();
  351. for (int h = 1; h < centroids.Height; h++)
  352. {
  353. int areaField1 = stats.At<int>(h, 4);
  354. if (debrisAreaStart <= areaField1 && areaField1 <= debrisAreaEnd)
  355. {
  356. keyValuePairs.Add(h, 1);
  357. }
  358. }
  359. labelMat.ForEachAsInt32(CommonForEachForInt32);
  360. //合并rgb和透明度
  361. Mat[] mats = rgb_ap.Split();
  362. arr[0] = mats[0];
  363. arr[1] = mats[1];
  364. arr[2] = mats[2];
  365. arr[3] = temp_ap;
  366. Cv2.Merge(arr, src);
  367. return src;
  368. }
  369. #endregion
  370. #region 有视场 二值提取
  371. /// <summary>
  372. /// 二值操作-二值提取-有视场
  373. /// </summary>
  374. /// <param name="src">视场mat</param>
  375. /// <param name="mat">原图mat</param>
  376. /// <param name="lists">参数列表</param>
  377. /// <returns></returns>
  378. public static Mat ImageBinaryExtraction(Mat source, Mat mat, List<Args> lists, bool findContours = false)
  379. {
  380. //以下是参数信息---------------------
  381. ///1个颜色区间还是2个
  382. colorInterval = 1;
  383. //第一个二值区间
  384. colorOneStart = 0;
  385. colorOneEnd = 0;
  386. //第二个二值区间
  387. colorTwoStart = 0;
  388. colorTwoEnd = 0;
  389. //第三个二值区间
  390. colorThreeStart = 0;
  391. colorThreeEnd = 0;
  392. //处理细节
  393. //删除边界对象
  394. bool deleteBoundaryObject = false;
  395. //孔洞填充
  396. bool holeFilling = false;
  397. //碎屑删除
  398. bool debrisRemoval = false;
  399. //碎屑删除面积起
  400. debrisAreaStart = 0;
  401. //碎屑删除面积止
  402. debrisAreaEnd = 0;
  403. //二值样式
  404. //1实心 2边线
  405. int binaryStyle = 0;
  406. //相颜色
  407. Color phaseColor = Color.Red;
  408. //目标选择
  409. int targetSelection = 1;
  410. for (int i = 0; i < lists.Count; i++)
  411. {
  412. Args args = lists[i];
  413. switch (args.Key)
  414. {
  415. case "colorInterval":
  416. {
  417. if (args.Value is Boolean)
  418. colorInterval = (Boolean)args.Value ? 2 : 1;
  419. else
  420. colorInterval = (int)args.Value;
  421. }
  422. break;
  423. case "scope1":
  424. colorOneStart = (int)((List<double>)args.Value)[0];
  425. colorOneEnd = (int)((List<double>)args.Value)[1];
  426. break;
  427. case "scope2":
  428. colorTwoStart = (int)((List<double>)args.Value)[0];
  429. colorTwoEnd = (int)((List<double>)args.Value)[1];
  430. break;
  431. case "scope3":
  432. colorThreeStart = (int)((List<double>)args.Value)[0];
  433. colorThreeEnd = (int)((List<double>)args.Value)[1];
  434. break;
  435. case "deleteBoundaryObject":
  436. deleteBoundaryObject = (bool)args.Value;
  437. break;
  438. case "holeFilling":
  439. holeFilling = (bool)args.Value;
  440. break;
  441. case "debrisRemoval":
  442. debrisRemoval = (bool)args.Value;
  443. break;
  444. case "binaryStyle":
  445. binaryStyle = (int)args.Value;
  446. break;
  447. case "phaseColor":
  448. phaseColor = Color.FromArgb((int)args.Value);
  449. break;
  450. case "targetSelection":
  451. targetSelection = (int)args.Value;
  452. break;
  453. case "scope4":
  454. debrisAreaStart = (int)((List<double>)args.Value)[0];
  455. debrisAreaEnd = (int)((List<double>)args.Value)[1];
  456. break;
  457. default:
  458. break;
  459. }
  460. }
  461. vec4B.Item0 = phaseColor.B;
  462. vec4B.Item1 = phaseColor.G;
  463. vec4B.Item2 = phaseColor.R;
  464. vec4B.Item3 = phaseColor.A;
  465. //二值提取
  466. Mat src = BinarizationWithView(source);
  467. //目标选择
  468. if (targetSelection != 2)
  469. src = CalcContoursByTargetSelection_New(temp_view, targetSelection, source);
  470. //碎屑删除,参考冈萨雷斯,414,9.5.3,连通分量提取
  471. if (debrisRemoval && debrisAreaEnd > 0)
  472. src = DebrisRemoval_NewWithView(src);
  473. //孔洞填充,参考冈萨雷斯,413,9.5.2
  474. if (holeFilling)
  475. src = HoleFilling_NewWithView(src);
  476. //实心/边线,参考冈萨雷斯,412,9.5.1,边界提取
  477. if (binaryStyle == 2)
  478. {
  479. Cv2.Erode(src, temp, null);
  480. src = src - temp;
  481. src = BaseTools.MergeMatFromMatArr(src, vec4B);
  482. }
  483. return src;
  484. }
  485. /// <summary>
  486. /// 二值提取
  487. /// </summary>
  488. /// <param name="source">视场图像</param>
  489. /// <param name="mat">原图像</param>
  490. /// <param name="colorInterval">1个或2个颜色区间</param>
  491. /// <param name="colorOneStart"></param>
  492. /// <param name="colorOneEnd"></param>
  493. /// <param name="colorTwoStart"></param>
  494. /// <param name="colorTwoEnd"></param>
  495. /// <param name="colorThreeStart"></param>
  496. /// <param name="colorThreeEnd"></param>
  497. /// <param name="phaseColor">相颜色</param>
  498. /// <returns></returns>
  499. private static Mat BinarizationWithView(Mat source)
  500. {
  501. Mat[] arr = source.Split();
  502. alpha = arr[3];
  503. Mat srcGray;
  504. if (source.Type() == MatType.CV_8UC1)
  505. {
  506. srcGray = source;
  507. }
  508. else
  509. {
  510. srcGray = source.CvtColor(ColorConversionCodes.BGR2GRAY);
  511. }
  512. temp_view = new Mat(source.Rows, source.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
  513. temp = new Mat(source.Rows, source.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0));
  514. srcGray.ForEachAsByte(GrayForEachAsByteWithView);
  515. return temp.Clone();
  516. }
  517. /// <summary>
  518. /// 并行循环
  519. /// </summary>
  520. /// <param name="value"></param>
  521. /// <param name="position"></param>
  522. private static void GrayForEachAsByteWithView(byte* value, int* position)
  523. {
  524. int y = position[0];
  525. int x = position[1];
  526. byte v = *value;
  527. if (colorInterval == 1)
  528. {
  529. if (v >= colorOneStart && v <= colorOneEnd)
  530. {
  531. if(alpha.At<byte>(y, x) > 0)
  532. {
  533. temp.Set<Vec4b>(y, x, vec4B);
  534. temp_view.Set<Vec4b>(y, x, vec4B);
  535. }
  536. else
  537. {
  538. temp_view.Set<Vec4b>(y, x, new Vec4b(vec4B.Item0, vec4B.Item1, vec4B.Item2,0));
  539. }
  540. }
  541. }
  542. else
  543. {
  544. if (((v >= colorTwoStart && v <= colorTwoEnd) || (v >= colorThreeStart && v <= colorThreeEnd)))
  545. {
  546. if (alpha.At<byte>(y, x) > 0)
  547. {
  548. temp.Set<Vec4b>(y, x, vec4B);
  549. temp_view.Set<Vec4b>(y, x, vec4B);
  550. }
  551. else
  552. {
  553. temp_view.Set<Vec4b>(y, x, new Vec4b(vec4B.Item0, vec4B.Item1, vec4B.Item2, 0));
  554. }
  555. }
  556. }
  557. }
  558. /// <summary>
  559. /// 新碎屑删除,使用连通分量找寻碎屑
  560. /// </summary>
  561. /// <param name="src"></param>
  562. /// <returns></returns>
  563. private static Mat DebrisRemoval_NewWithView(Mat src)
  564. {
  565. Mat[] arr = src.Split();
  566. rgb_ap = BaseTools.MergeMatFromMatArr(arr);
  567. temp_ap = arr[3].Clone();
  568. //寻找连通分量
  569. Mat labelMat = new Mat();
  570. Mat stats = new Mat();
  571. Mat centroids = new Mat();
  572. int nonenum = Cv2.ConnectedComponentsWithStats(temp_ap, labelMat, stats, centroids, PixelConnectivity.Connectivity8);
  573. //寻找在范围内需要删除的碎屑
  574. keyValuePairs.Clear();
  575. for (int h = 1; h < centroids.Height; h++)
  576. {
  577. int areaField1 = stats.At<int>(h, 4);
  578. if (debrisAreaStart <= areaField1 && areaField1 <= debrisAreaEnd)
  579. {
  580. keyValuePairs.Add(h, 1);
  581. }
  582. }
  583. labelMat.ForEachAsInt32(CommonForEachForInt32);
  584. //合并rgb和透明度
  585. Mat[] mats = rgb_ap.Split();
  586. arr[0] = mats[0];
  587. arr[1] = mats[1];
  588. arr[2] = mats[2];
  589. arr[3] = temp_ap;
  590. Cv2.Merge(arr, src);
  591. return src;
  592. }
  593. /// <summary>
  594. /// 新孔洞填充,采用形态学填充
  595. /// </summary>
  596. /// <param name="src"></param>
  597. /// <returns></returns>
  598. private static Mat HoleFilling_NewWithView(Mat src)
  599. {
  600. Mat[] arr2 = src.Split();
  601. Mat tempc = arr2[3];
  602. //去掉透明层
  603. Mat mat = src.CvtColor(ColorConversionCodes.BGRA2BGR);
  604. //填充孔洞
  605. mat = BaseTools.FillHole(mat, new Scalar(255 - vec4B.Item0, 255 - vec4B.Item1, 255 - vec4B.Item2));
  606. tempc = BaseTools.FillHole(tempc, new Scalar(255));
  607. //循环处理
  608. mat.ForEachAsVec3b(RGBForEachAsByteForHoleFillingNewWithView);
  609. Mat[] arr1 = mat.Split();
  610. arr2[0] = arr1[0];
  611. arr2[1] = arr1[1];
  612. arr2[2] = arr1[2];
  613. arr2[3] = tempc;
  614. Cv2.Merge(arr2, src);
  615. return src;
  616. }
  617. private static void RGBForEachAsByteForHoleFillingNewWithView(Vec3b* value, int* position)
  618. {
  619. int y = position[0];
  620. int x = position[1];
  621. if (value->Item0 == 255 && value->Item1 == 255 && value->Item2 == 255)
  622. {
  623. value->Item0 = vec4B.Item0;
  624. value->Item1 = vec4B.Item1;
  625. value->Item2 = vec4B.Item2;
  626. }
  627. }
  628. /// <summary>
  629. /// 目标选择
  630. /// </summary>
  631. /// <param name="src"></param>
  632. /// <param name="mat"></param>
  633. /// <param name="targetSelection"></param>
  634. /// <param name="source"></param>
  635. /// <returns></returns>
  636. public static Mat CalcContoursByTargetSelection_New(Mat src, int targetSelection, Mat source)
  637. {
  638. Mat[] arr = src.Split();
  639. alpha = arr[3].Clone();
  640. Mat rgb = BaseTools.MergeMatFromMatArr(arr);
  641. Mat alphatemp = arr[3].Clone();
  642. Mat mask = Mat.Zeros(rgb.Rows + 2, rgb.Cols + 2, MatType.CV_8UC1);
  643. //考虑循环填充,填充视场的透明层和原图的透明层,然后比较填充区域的大小
  644. //但是循环的时候需要少循环像素,可以处理视场的透明层,减少循环量
  645. //同时记录种子点,然后根据targetSelection判断是填充透明还是不透明
  646. Mat rgbClone = rgb.Clone();
  647. List<OpenCvSharp.Point> points = new List<OpenCvSharp.Point>();
  648. for(int h=0; h< alphatemp.Height; h++)
  649. {
  650. for (int w = 0; w < alphatemp.Width; w++)
  651. {
  652. int v = alphatemp.At<byte>(h, w);
  653. if(v>0)
  654. {
  655. int a = Cv2.FloodFill(alphatemp, new OpenCvSharp.Point(w, h), new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
  656. int b = Cv2.FloodFill(rgbClone, new OpenCvSharp.Point(w, h), new Scalar(0, 0, 0), out rect, null, null, FloodFillFlags.Link8);
  657. if(a !=b)
  658. {
  659. points.Add(new OpenCvSharp.Point(w, h));
  660. }
  661. }
  662. }
  663. }
  664. if(points.Count>0)
  665. {
  666. foreach(OpenCvSharp.Point p in points)
  667. {
  668. if(targetSelection == 1)
  669. {
  670. Cv2.FloodFill(alpha, p, new Scalar(0), out rect, null, null, FloodFillFlags.Link8);
  671. }
  672. else if(targetSelection == 3)
  673. {
  674. Cv2.FloodFill(rgb, mask, p, new Scalar(vec4B.Item0, vec4B.Item1, vec4B.Item2), out rect, null, null, FloodFillFlags.Link8);
  675. }
  676. }
  677. }
  678. if (targetSelection == 3)
  679. {
  680. Mat t = new Mat(mask, new Rect(1, 1, rgb.Width, rgb.Height));
  681. alpha = alpha + t * 255;
  682. }
  683. //合并rgb和透明度
  684. Mat[] mats = rgb.Split();
  685. arr[0] = mats[0];
  686. arr[1] = mats[1];
  687. arr[2] = mats[2];
  688. arr[3] = alpha;
  689. Cv2.Merge(arr, src);
  690. return src;
  691. }
  692. #endregion
  693. private static void CommonForEachForInt32(int* value, int* position)
  694. {
  695. int y = position[0];
  696. int x = position[1];
  697. int v = *value;
  698. if (v > 0 && keyValuePairs.ContainsKey(v))
  699. {
  700. rgb_ap.Set<Vec3b>(y, x, new Vec3b(0, 0, 0));
  701. temp_ap.Set<int>(y, x, 0);
  702. }
  703. }
  704. }
  705. }