using OpenCvSharp; using PaintDotNet.Base; using PaintDotNet.Base.Enum; using PaintDotNet.Base.Functionodel; using System; using System.Collections.Generic; using System.Drawing; using System.Linq; namespace PaintDotNet.Adjust { /// /// 物相提取的处理程序 /// public unsafe class PhaseExtractionIntent { /// /// 中间变量 /// private static Mat phaseTemp; /// /// 中间变量 /// private static Mat phaseTemp1; /// /// 中间变量 /// private static Mat phaseTemp2; /// /// 视场Mat /// private static Mat viewMat; /// /// 相颜色 /// private static Vec4b vec4B; /// /// 透明的颜色 /// private static Vec4b vec4BTransparent = new Vec4b(0,0,0,0); /// /// RGB/HLS的范围值 /// private static int item0L, item0R, item1L, item1R, item2L, item2R; /// /// 目标选择 /// private static FieldOfViewParameters targetSelection; /// /// 定义物体 /// private static DefineObjectsParameters defineObjects = DefineObjectsParameters.Click; /// /// 定义物体->点击->容许值 /// private static int allowable = 0; /// /// 定义物体->点击->范围大小 /// private static int scopeSize = 0; /// /// 定义物体->轮廓,默认多边形 /// private static ContourParameters shape = ContourParameters.Polygon; /// /// 删除边界对象 /// private static bool deleteBoundaryObject = false; /// /// 孔洞填充 /// private static bool holeFilling = false; /// /// 碎屑删除 /// private static bool debrisRemoval = false; /// /// 碎屑面积起 /// private static int debrisAreaStart = 0; /// /// 碎屑面积止 /// private static int debrisAreaEnd = 0; /// /// 二值样式 /// private static StyleParameters binaryType; /// /// 目标选择 /// private static ProcessingParameters targetProcess; /// /// RGB/HLS 默认0 rgb /// private static int rgborhls = 0; /// /// 单个目标,偏差 /// private static int deviation = 0; #region 无视场 /// /// 【无视场】二值操作-物相提取 /// /// 源图像 /// 参数集合 /// public static Mat ImagePhaseExtraction(Mat src, PhaseModel phase, System.Drawing.Point point, List lists) { if (phase == null) return src; Mat returnValue = new Mat(); Color color = Color.FromArgb(phase.color); vec4B = new Vec4b(color.B, color.G, color.R, 255); //整个图像的参数 List whole = lists[0].choiseList[0].lists; //单个目标的参数 List single = lists[0].choiseList[1].lists; //提取模式->整个图像 bool wholeObject = (bool)(lists[0].choiseList[0].value); //提取模式->单个目标 bool singleObject = (bool)(lists[0].choiseList[1].value); //目标选择 targetSelection = (FieldOfViewParameters)lists[0].choiseList[2].Value; //二值样式 binaryType = (StyleParameters)lists[0].choiseList[0].Lists[1].Value; //目标选择 targetProcess = (ProcessingParameters)lists[0].choiseList[0].Lists[2].Value; //整个图像 if (wholeObject) { //定义物体,点击或轮廓 //bool click = (bool)lists[0].choiseList[0].lists.Find(a => a.Key.Equals("defineObject")).choiseList[0].Value; bool profile = (bool)lists[0].choiseList[0].lists.Find(a => a.Key.Equals("defineObject")).choiseList[1].Value; defineObjects = profile ? DefineObjectsParameters.Profile : DefineObjectsParameters.Click; //定义物体->点击->容许值 allowable = (int)((lists[0].choiseList[0].Lists[0].choiseList[0].Lists[0])).Value; //定义物体->点击->范围大小 scopeSize = (int)((lists[0].choiseList[0].Lists[0].choiseList[0].Lists[1])).Value; //定义物体->轮廓 shape = (ContourParameters)lists[0].choiseList[0].Lists[0].choiseList[1].lists[0].Value; //删除边界对象 deleteBoundaryObject = (bool)whole[3].Value; //孔洞填充 holeFilling = (bool)whole[4].Value; //碎屑删除 debrisRemoval = (bool)whole[5].Value; //碎屑面积 debrisAreaStart = (int)(((List)lists[0].choiseList[0].Lists[6].Value)[0]); debrisAreaEnd = (int)(((List)lists[0].choiseList[0].Lists[6].Value)[1]); //rgb或hls rgborhls = ((bool)whole[7].choiseList[0].Value) ? 0 : 1; //RGB/HLS的值区间 item2L = (int)(((List)whole[7].choiseList[0].Lists[0].Value)[0]); item2R = (int)(((List)whole[7].choiseList[0].Lists[0].Value)[1]); item1L = (int)(((List)whole[7].choiseList[0].Lists[1].Value)[0]); item1R = (int)(((List)whole[7].choiseList[0].Lists[1].Value)[1]); item0L = (int)(((List)whole[7].choiseList[0].Lists[2].Value)[0]); item0R = (int)(((List)whole[7].choiseList[0].Lists[2].Value)[1]); } //提取单个目标的参数列表 if (singleObject) { deviation = (int)single[0].Value; } if (wholeObject) { returnValue = WholeExtract(src); } if (singleObject) { returnValue = SingleExtract(src, phase.mat, point); } return returnValue; } /// /// 点击时的整个提取 /// /// /// public static Mat WholeExtract(Mat source) { //原始轮廓信息 OpenCvSharp.Point[][] contours; //轮廓的拓扑信息 HierarchyIndex[] hierachy; //删除的对象的索引 List deleteIndexs = new List(); //二值提取 phaseTemp1 = new Mat(source.Rows, source.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0)); //如果是rgb if (rgborhls == 0) { source.ForEachAsVec4b(ForeachFunctionByteForWhole4B); } else { source.ForEachAsVec3b(ForeachFunctionByteForWhole3B); } //寻找轮廓 Cv2.FindContours(phaseTemp1.CvtColor(ColorConversionCodes.BGR2GRAY), out contours, out hierachy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone); //孔洞填充 phaseTemp1 = HoleFilling(holeFilling, hierachy, contours, phaseTemp1); //寻找轮廓 Cv2.FindContours(phaseTemp1.CvtColor(ColorConversionCodes.BGR2GRAY), out contours, out hierachy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone); //删除边界对象/碎屑删除 DeleteContours(deleteBoundaryObject, debrisRemoval, contours, hierachy, debrisAreaStart, debrisAreaEnd, deleteIndexs, phaseTemp1); //过滤掉被删除的轮廓,对剩下的填充或绘制轮廓 phaseTemp1 = FillOrDrawContours(phaseTemp1, contours, deleteIndexs, binaryType, vec4B, hierachy); return phaseTemp1; } /// /// 从全部轮廓中删除被移除的轮廓 /// 根据条件绘制轮廓或填充轮廓 /// /// /// /// /// /// /// /// private static Mat FillOrDrawContours(Mat src, OpenCvSharp.Point[][] contours, List deleteIndexs, StyleParameters binaryStyle, OpenCvSharp.Vec4b phaseColor, HierarchyIndex[] hierachy) { //创建一个新mat src = new Mat(src.Size(), src.Type(), new Scalar(0, 0, 0, 0)); //src.EmptyClone(); //用于绘制的轮廓 List drawContours = contours.ToList(); //循环处理轮廓,过滤到被删除的轮廓及其子轮廓 if (deleteIndexs.Count > 0) { drawContours.Clear(); for (int i = 0; i < contours.Length; i++) { if (!deleteIndexs.Exists(a => a == i))// && !deleteIndexs.Exists(a => a == hierachy[i].Parent) { drawContours.Add(contours[i]); } } } //二值样式 1实心 2边线 if (binaryStyle == StyleParameters.Solid) { Cv2.FillPoly(src, drawContours, new Scalar(phaseColor.Item0, phaseColor.Item1, phaseColor.Item2, 255), LineTypes.Link8); } else { Cv2.DrawContours(src, drawContours, -1, new Scalar(phaseColor.Item0, phaseColor.Item1, phaseColor.Item2, 255), 1); } return src; } public unsafe static void ForeachFunctionByteForWhole4B(Vec4b* t, int* position) { int y = position[0]; int x = position[1]; //如果是删除 if (targetProcess == ProcessingParameters.Delete) { phaseTemp1.Set(y, x, vec4BTransparent); } if ((t->Item0 >= item0L && t->Item0 <= item0R) && (t->Item1 >= item1L && t->Item1 <= item1R) && (t->Item2 >= item2L && t->Item2 <= item2R)) { phaseTemp1.Set(y, x, vec4B); } } public unsafe static void ForeachFunctionByteForWhole3B(Vec3b* t, int* position) { int y = position[0]; int x = position[1]; //如果是删除 if (targetProcess == ProcessingParameters.Delete) { phaseTemp1.Set(y, x, vec4BTransparent); } if ((t->Item0 >= item0L && t->Item0 <= item0R) && (t->Item1 >= item1L && t->Item1 <= item1R) && (t->Item2 >= item2L && t->Item2 <= item2R)) { phaseTemp1.Set(y, x, vec4B); } } /// /// 单个目标的提取 /// /// 源图像 /// 鼠标点击位置 /// 相颜色 /// public static Mat SingleExtract(Mat source, Mat phase, System.Drawing.Point point) { try { if (phase == null) { phaseTemp1 = new Mat(source.Rows, source.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0)); } else { phase.CopyTo(phaseTemp1); } phaseTemp = new Mat(source.Rows + 2, source.Cols + 2, MatType.CV_8U, Scalar.All(0)); Mat sourceTemp = new Mat(); source.CopyTo(sourceTemp); sourceTemp = sourceTemp.CvtColor(ColorConversionCodes.BGRA2BGR); Rect rect = new Rect(); 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); //二值样式 1实心 2边线 if (binaryType == StyleParameters.Sideline) { Mat nowTemp1 = new Mat(source.Rows, source.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0)); //原始轮廓信息 OpenCvSharp.Point[][] contours; //轮廓的拓扑信息 HierarchyIndex[] hierachy; //去掉外边的2个像素 //Mat roi = new Mat(phaseTemp, new Rect(1, 1, source.Width, source.Height)); phaseTemp.ForEachAsByte(ForeachFunctionByteForChoise); Cv2.FindContours(phaseTemp1.CvtColor(ColorConversionCodes.BGRA2GRAY), out contours, out hierachy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone); Cv2.DrawContours(nowTemp1, contours, -1, new Scalar(vec4B.Item0, vec4B.Item1, vec4B.Item2, 255), 1); nowTemp1.CopyTo(phaseTemp1); } else { /*if(phase!=null) { //原始轮廓信息 OpenCvSharp.Point[][] contours; //轮廓的拓扑信息 HierarchyIndex[] hierachy; //寻找轮廓信息 Cv2.FindContours(phase.CvtColor(ColorConversionCodes.BGR2GRAY), out contours, out hierachy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone); List> lists = new List>(); foreach (OpenCvSharp.Point[] points in contours) { lists.Add(points.ToList()); } //填充轮廓 Cv2.FillPoly(phaseTemp, lists, new Scalar(vec4B.Item0, vec4B.Item1, vec4B.Item2, 255), LineTypes.Link8); }*/ phaseTemp.ForEachAsByte(ForeachFunctionByteForChoise); } } catch (Exception) { } finally { if (phaseTemp != null && !phaseTemp.IsDisposed) phaseTemp.Dispose(); } return phaseTemp1; } /// /// 单个目标的提取 /// /// /// public unsafe static void ForeachFunctionByteForChoise(byte* value, int* position) { int y = position[0]; int x = position[1]; byte intencity = *value; if (intencity == 1 && x > 0 && y > 0 && x < phaseTemp.Width - 1 && y < phaseTemp.Height - 1) { phaseTemp1.Set(y - 1, x - 1, vec4B); } } /// /// 孔洞填充 /// /// /// /// /// /// private static Mat HoleFilling(bool holeFilling, HierarchyIndex[] hierachy, OpenCvSharp.Point[][] contours, Mat src) { if (holeFilling && hierachy != null) { for (int i = 0; i < hierachy.Length; i++) { //如果需要还可以判断面积范围 if (hierachy[i].Parent > -1) { List> ps = new List>(); ps.Add(contours[i].ToList()); Cv2.FillPoly(src, ps, new Scalar(255, 0, 0, 255)); } } } return src; } /// /// 删除边界对象 以及 碎屑删除 /// /// 是否删除边界对象 /// 是否删除碎屑 /// 轮廓 /// 结构 /// 碎屑面积 /// 碎屑面积 /// 被删除的轮廓的下标 /// 源 public static void DeleteContours(bool deleteBoundaryObject, bool debrisRemoval, OpenCvSharp.Point[][] contours, HierarchyIndex[] hierachy, int debrisAreaStart, int debrisAreaEnd, List deleteIndexs, Mat src) { if ((deleteBoundaryObject || debrisRemoval) && contours != null) { if (contours.Length > 0) { for (int i = 0; i < contours.Length; i++) { bool delete = false; if (debrisRemoval) { double area = Cv2.ContourArea(contours[i]); if (area >= debrisAreaStart && area <= debrisAreaEnd && hierachy[i].Parent == -1) { deleteIndexs.Add(i); List pointsTemp = new List(); RecursiveFindChildContours(contours.ToList(), hierachy, i, deleteIndexs); delete = true; } } if (deleteBoundaryObject && !delete) { for (int y = 0; y < contours[i].Length; y++) { 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) { deleteIndexs.Add(i); List pointsTemp = new List(); RecursiveFindChildContours(contours.ToList(), hierachy, i, deleteIndexs); break; } } } } } } } #endregion #region 有视场 public static Mat ImagePhaseExtractionWithView(Mat hls, Mat rgb, Mat origin, PhaseModel phase, System.Drawing.Point point, List lists) { viewMat = hls; Mat returnValue = new Mat(); Color color = Color.FromArgb(phase.color); vec4B = new Vec4b(color.B, color.G, color.R, 255); //整个图像的参数 List whole = lists[0].choiseList[0].lists; //单个目标的参数 List single = lists[0].choiseList[1].lists; //提取模式->整个图像 bool wholeObject = (bool)(lists[0].choiseList[0].value); //提取模式->单个目标 bool singleObject = (bool)(lists[0].choiseList[1].value); //目标选择 targetSelection = (FieldOfViewParameters)lists[0].choiseList[2].Value; //二值样式 binaryType = (StyleParameters)lists[0].choiseList[0].Lists[1].Value; //目标选择 targetProcess = (ProcessingParameters)lists[0].choiseList[0].Lists[2].Value; //整个图像 if (wholeObject) { //定义物体,点击或轮廓 //bool click = (bool)lists[0].choiseList[0].lists.Find(a => a.Key.Equals("defineObject")).choiseList[0].Value; bool profile = (bool)lists[0].choiseList[0].lists.Find(a => a.Key.Equals("defineObject")).choiseList[1].Value; defineObjects = profile ? DefineObjectsParameters.Profile : DefineObjectsParameters.Click; //定义物体->点击->容许值 allowable = (int)((lists[0].choiseList[0].Lists[0].choiseList[0].Lists[0])).Value; //定义物体->点击->范围大小 scopeSize = (int)((lists[0].choiseList[0].Lists[0].choiseList[0].Lists[1])).Value; //定义物体->轮廓 shape = (ContourParameters)lists[0].choiseList[0].Lists[0].choiseList[1].lists[0].Value; //删除边界对象 deleteBoundaryObject = (bool)whole[3].Value; //孔洞填充 holeFilling = (bool)whole[4].Value; //碎屑删除 debrisRemoval = (bool)whole[5].Value; //碎屑面积 debrisAreaStart = (int)(((List)lists[0].choiseList[0].Lists[6].Value)[0]); debrisAreaEnd = (int)(((List)lists[0].choiseList[0].Lists[6].Value)[1]); //rgb或hls rgborhls = ((bool)whole[7].choiseList[0].Value) ? 0 : 1; //RGB/HLS的值区间 item2L = (int)(((List)whole[7].choiseList[0].Lists[0].Value)[0]); item2R = (int)(((List)whole[7].choiseList[0].Lists[0].Value)[1]); item1L = (int)(((List)whole[7].choiseList[0].Lists[1].Value)[0]); item1R = (int)(((List)whole[7].choiseList[0].Lists[1].Value)[1]); item0L = (int)(((List)whole[7].choiseList[0].Lists[2].Value)[0]); item0R = (int)(((List)whole[7].choiseList[0].Lists[2].Value)[1]); } //提取单个目标的参数列表 if (singleObject) { deviation = (int)single[0].Value; } if (wholeObject) { returnValue = WholeExtractView(hls, phase.mat, rgb); } if (singleObject) { returnValue = SingleExtractView(hls, phase.mat, point); } return returnValue; } /// /// 点击时的整个提取 /// /// 视场mat,rgb或hls /// if(rgb){ 原图的mat }else if(hls){ rgba视场的mat } /// public static Mat WholeExtractView(Mat hls, Mat rgb, Mat origin) { //原图内轮廓信息 OpenCvSharp.Point[][] originContours; //原图内轮廓的拓扑信息 HierarchyIndex[] originHierachy; //原始轮廓信息 OpenCvSharp.Point[][] contours; //轮廓的拓扑信息 HierarchyIndex[] hierachy; //删除的对象的索引 List deleteIndexs = new List(); //二值提取 phaseTemp = new Mat(hls.Rows, hls.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0)); phaseTemp1 = new Mat(hls.Rows, hls.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0)); phaseTemp2 = origin; if (rgborhls==0) { origin.ForEachAsVec4b(ForeachFunctionByteForWholeWithView4B); } else { hls.ForEachAsVec3b(ForeachFunctionByteForWholeWithView3B); } //Cv2.ImShow("原", phaseTemp); //原图mat寻找轮廓 Cv2.FindContours(phaseTemp.CvtColor(ColorConversionCodes.BGR2GRAY), out originContours, out originHierachy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone); //寻找轮廓 Cv2.FindContours(phaseTemp1.CvtColor(ColorConversionCodes.BGR2GRAY), out contours, out hierachy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone); //孔洞填充 phaseTemp1 = HoleFillingWithView(holeFilling, hierachy, contours, phaseTemp1, vec4B); //寻找轮廓 Cv2.FindContours(phaseTemp1.CvtColor(ColorConversionCodes.BGR2GRAY), out contours, out hierachy, RetrievalModes.Tree, ContourApproximationModes.ApproxNone); //删除边界对象/碎屑删除 DeleteContoursWithView(deleteBoundaryObject, debrisRemoval, contours, hierachy, debrisAreaStart, debrisAreaEnd, deleteIndexs, phaseTemp1); //过滤掉被删除的轮廓,对剩下的填充或绘制轮廓 phaseTemp1 = FillOrDrawContoursWithView(holeFilling, phaseTemp1, contours, originContours, deleteIndexs, binaryType, vec4B, hierachy, originHierachy, targetSelection); return phaseTemp1; } /// /// 单个目标的提取 /// /// 源图像 /// 鼠标点击位置 /// 相颜色 /// public static Mat SingleExtractView(Mat source, Mat phase, System.Drawing.Point point) { try { if (phase == null) { phaseTemp1 = new Mat(source.Rows, source.Cols, MatType.CV_8UC4, new Scalar(0, 0, 0, 0)); } else { phase.CopyTo(phaseTemp1); } phaseTemp = new Mat(source.Rows + 2, source.Cols + 2, MatType.CV_8U, Scalar.All(0)); Mat sourceTemp = new Mat(); source.CopyTo(sourceTemp); sourceTemp = sourceTemp.CvtColor(ColorConversionCodes.BGRA2BGR); Rect rect = new Rect(); 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); phaseTemp.ForEachAsByte(ForeachFunctionByteForChoiseWithView); } catch (Exception) { } finally { if (phaseTemp != null && !phaseTemp.IsDisposed) phaseTemp.Dispose(); } return phaseTemp1; } public unsafe static void ForeachFunctionByteForChoiseWithView(byte* value, int* position) { int y = position[0]; int x = position[1]; byte intencity = *value; if (intencity == 1 && x > 0 && y > 0 && x < phaseTemp.Width - 1 && y < phaseTemp.Height - 1) { if(viewMat.At(y - 1, x - 1)[3]>0) phaseTemp1.Set(y - 1, x - 1, vec4B); } } public unsafe static void ForeachFunctionByteForWholeWithView4B(Vec4b* t, int* position) { int y = position[0]; int x = position[1]; //如果是删除 if (targetProcess == ProcessingParameters.Delete) { phaseTemp1.Set(y, x, vec4BTransparent); } //如果不透明则进行处理 //if (t->Item3 > 0) { if ((t->Item0 >= item0L && t->Item0 <= item0R) && (t->Item1 >= item1L && t->Item1 <= item1R) && (t->Item2 >= item2L && t->Item2 <= item2R)) { phaseTemp.Set(y, x, vec4B); if (t->Item3 > 0) phaseTemp1.Set(y, x, vec4B); } } } public unsafe static void ForeachFunctionByteForWholeWithView3B(Vec3b* t, int* position) { int y = position[0]; int x = position[1]; //如果是删除 if (targetProcess == ProcessingParameters.Delete) { phaseTemp1.Set(y, x, vec4BTransparent); } Vec4b m4b = phaseTemp2.At(y, x); //如果不透明则进行处理 //if (m4b.Item3 > 0) { if ((t->Item0 >= item0L && t->Item0 <= item0R) && (t->Item1 >= item1L && t->Item1 <= item1R) && (t->Item2 >= item2L && t->Item2 <= item2R)) { phaseTemp.Set(y, x, vec4B); if (m4b.Item3 > 0) phaseTemp1.Set(y, x, vec4B); } } } /// /// 孔洞填充 /// /// /// /// /// /// /// private static Mat HoleFillingWithView(bool holeFilling, HierarchyIndex[] hierachy, OpenCvSharp.Point[][] contours, Mat src, Vec4b phaseColor) { if (holeFilling && hierachy != null) { for (int i = 0; i < hierachy.Length; i++) { //如果需要还可以判断面积范围 if (hierachy[i].Parent > -1) { List> ps = new List>(); ps.Add(contours[i].ToList()); Cv2.FillPoly(src, ps, new Scalar(phaseColor.Item0, phaseColor.Item1, phaseColor.Item2, 255)); } } } return src; } /// /// 删除边界对象 以及 碎屑删除 /// /// 是否删除边界对象 /// 是否删除碎屑 /// 轮廓 /// 结构 /// 碎屑面积 /// 碎屑面积 /// 被删除的轮廓的下标 /// 源 public static void DeleteContoursWithView(bool deleteBoundaryObject, bool debrisRemoval, OpenCvSharp.Point[][] contours, HierarchyIndex[] hierachy, int debrisAreaStart, int debrisAreaEnd, List deleteIndexs, Mat src) { if ((deleteBoundaryObject || debrisRemoval) && contours != null) { if (contours.Length > 0) { for (int i = 0; i < contours.Length; i++) { bool delete = false; if (debrisRemoval) { double area = Cv2.ContourArea(contours[i]); if (area > debrisAreaStart && area < debrisAreaEnd && hierachy[i].Parent == -1) { deleteIndexs.Add(i); RecursiveFindChildContours(contours.ToList(), hierachy, i, deleteIndexs); delete = true; } } if (deleteBoundaryObject && !delete) { for (int y = 0; y < contours[i].Length; y++) { 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) { deleteIndexs.Add(i); RecursiveFindChildContours(contours.ToList(), hierachy, i, deleteIndexs); break; } } } } } } } /// /// 从全部轮廓中删除被移除的轮廓 /// 根据条件绘制轮廓或填充轮廓 /// /// /// 视场图轮廓 /// 原图轮廓 /// /// /// /// /// 目标选择 /// private static Mat FillOrDrawContoursWithView(bool holeFilling, Mat src, OpenCvSharp.Point[][] contours, OpenCvSharp.Point[][] originContours, List deleteIndexs, StyleParameters binaryStyle, Vec4b phaseColor, HierarchyIndex[] hierachy, HierarchyIndex[] originHierachy, FieldOfViewParameters targetSelection) { if(src==null) src = new Mat(phaseTemp1.Size(), phaseTemp1.Type(), new Scalar(0, 0, 0, 0)); //创建一个新mat //Mat src = new Mat(temp.Size(), temp.Type(), new Scalar(0, 0, 0, 0)); //用于绘制的轮廓 List drawContours = contours.ToList(); //用于绘制的轮廓对应的关系 List hierachys = new List(); //处理目标选择,以及过滤到被删除的轮廓及其子轮廓 drawContours = CalcContoursByTargetSelection(holeFilling, deleteIndexs, drawContours, hierachy, originContours, originHierachy, targetSelection); if(drawContours.Count == 0) drawContours = contours.ToList(); //二值样式 1实心 2边线 if (binaryStyle == StyleParameters.Solid) { Cv2.FillPoly(src, drawContours, new Scalar(phaseColor.Item0, phaseColor.Item1, phaseColor.Item2, 255)); } else { Cv2.DrawContours(src, drawContours, -1, new Scalar(phaseColor.Item0, phaseColor.Item1, phaseColor.Item2, 255), 1); } return src; } /// /// 根据目标选择参数进行轮廓的筛选 /// /// 经过筛选的视场图内的轮廓 /// 原图二值化后的所有轮廓 /// private static List CalcContoursByTargetSelection(bool holeFilling, List deleteIndexs, List drawContours, HierarchyIndex[] hierachy, OpenCvSharp.Point[][] originContours, HierarchyIndex[] originHierachy, FieldOfViewParameters targetSelection) { List points = new List(); List originPoints = originContours.ToList(); if (targetSelection == FieldOfViewParameters.One) { int k = 0; foreach (OpenCvSharp.Point[] ps in drawContours) { if (deleteIndexs.Count > 0) { if (deleteIndexs.Exists(a => a == k)) { k++; continue; } } foreach (OpenCvSharp.Point[] os in originPoints) { if (Cv2.PointPolygonTest(os, ps[0], false) >= 0) { if (Cv2.ContourArea(ps, false) == Cv2.ContourArea(os, false)) { if (hierachy[k].Parent == -1) { points.Add(ps); List pointsTemp = new List(); RecursiveFindChildContours(drawContours, hierachy, k, pointsTemp); points.AddRange(pointsTemp); } } } } k++; } } else if (targetSelection == FieldOfViewParameters.Two) { if (deleteIndexs.Count > 0) { for (int i = 0; i < drawContours.Count; i++) { if (!deleteIndexs.Exists(a => a == i) && !deleteIndexs.Exists(a => a == hierachy[i].Parent)) { points.Add(drawContours[i]); } } } else { points = drawContours; } } else if (targetSelection == FieldOfViewParameters.Three) { List smallInt = new List(); List bigInt = new List(); int k = 0; foreach (OpenCvSharp.Point[] ps in drawContours) { int f = 0; if (deleteIndexs.Count > 0) { if (deleteIndexs.Exists(a => a == k)) { k++; continue; } } foreach (OpenCvSharp.Point[] os in originPoints) { if (Cv2.PointPolygonTest(os, ps[0], false) >= 0 && hierachy[k].Parent == -1) { if (Cv2.ContourArea(ps, false) == Cv2.ContourArea(os, false)) { if (originHierachy[f].Parent == -1) { if (!smallInt.Exists(a => a == k)) { smallInt.Add(k); points.Add(ps); if (!holeFilling) { List pointsTemp = new List(); RecursiveFindChildContours(drawContours, hierachy, k, pointsTemp); points.AddRange(pointsTemp); } } } } else { if (originHierachy[f].Parent == -1) { if (!bigInt.Exists(a => a == f)) { bigInt.Add(f); points.Add(os); if (!holeFilling) { List pointsTemp = new List(); RecursiveFindChildContours(originPoints, originHierachy, f, pointsTemp); points.AddRange(pointsTemp); } } } } } f++; } k++; } } return points; } #endregion #region 公共递归方法 /// /// 递归处理 /// /// /// /// /// private static void RecursiveFindChildContours( List drawContours, HierarchyIndex[] hierachy, int position, List points ) { int m = 0; foreach (HierarchyIndex index in hierachy) { if (index.Parent == position) { points.Add(drawContours[m]); RecursiveFindChildContours(drawContours, hierachy, m, points); } m++; } } /// /// 递归处理 /// /// /// /// /// private static void RecursiveFindChildContours( List drawContours, HierarchyIndex[] hierachy, int position, List points ) { int m = 0; foreach (HierarchyIndex index in hierachy) { if (index.Parent == position) { points.Add(m); RecursiveFindChildContours(drawContours, hierachy, m, points); } m++; } } #endregion #region 无视场删除 #endregion #region 有视场删除 #endregion } }