using OpenCvSharp; using SmartCoalApplication.Base.AuxiliaryCalcModel; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace SmartCoalApplication.Base.CommTool { public class XiGaoTools { public static Mat temp; public static int start, end; private static double threshold = 85; /// /// 寻找构件 /// /// public static List FindXiGaoHModels(Mat thresholdMat) { OpenCvSharp.Point[][] contours; HierarchyIndex[] hierarchy; Cv2.FindContours(thresholdMat, out contours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point()); //List contoursDraw = new List(); List list = new List(); for (int i = 0; i < contours.Length; i++) { if (hierarchy[i].Parent == -1 && contours[i].Length > 500) { XiGaoHModel model = new XiGaoHModel(); model.SetPoints(contours[i]); list.Add(model); } } if (list.Count == 0 || list.Count == 1) return list; List list_final = new List(); XiGaoHModel m = list[list.IndexOf(list.Find(b => b.topPoint.Y == list.Min(a => a.topPoint.Y)))]; list.Remove(m); if (m.topPoint.Y == 0) {//过滤顶部的亮条 m = list[list.IndexOf(list.Find(b => b.topPoint.Y == list.Min(a => a.topPoint.Y)))]; list.Remove(m); } list_final.Add(m); list_final.Add(list[list.IndexOf(list.Find(b => b.topPoint.Y == list.Min(a => a.topPoint.Y)))]); //for (int i = 0; i < list_final.Count; i++) //{ // XiGaoHModel mDraw = list_final[i]; // contoursDraw.Add(mDraw.points); //} //Mat thresholdMatClone = thresholdMat.Clone(); //Cv2.DrawContours(thresholdMatClone, contoursDraw.ToArray(), -1, new Scalar(127), 2); //Cv2.ImWrite(@"C:\Users\54434\Desktop\thresholdMatClone.jpg", thresholdMatClone); return list_final; } /// /// 处理连接在一起的构件 /// /// /// /// public static List FindXiGaoHModelsForConnState(Mat thresholdMat, List list_final) { int index = 0, y = 0; if (list_final[1].topPoint.Y < list_final[0].topPoint.Y) { index = 1; y = list_final[0].topPoint.Y; } if (list_final[index].topPoint.X > thresholdMat.Width / 2) { thresholdMat.Col[list_final[index].topPoint.X - 399] *= 0; thresholdMat.Col[list_final[index].topPoint.X - 400] *= 0; thresholdMat.Col[list_final[index].topPoint.X - 401] *= 0; } else { thresholdMat.Col[list_final[index].topPoint.X + 399] *= 0; thresholdMat.Col[list_final[index].topPoint.X + 400] *= 0; thresholdMat.Col[list_final[index].topPoint.X + 401] *= 0; } return FindXiGaoHModels(thresholdMat); } /// /// 移除小的联通区域 锡膏 /// /// /// public static Mat RemoveSmallConn(Mat mat, int area = 50) { Mat labels_left = new Mat(); Mat stats_left = new Mat(); Mat centroids_left = new Mat(); Cv2.ConnectedComponentsWithStats(mat, labels_left, stats_left, centroids_left, PixelConnectivity.Connectivity8); Dictionary keyValuePairs_left = new Dictionary(); for (int h = 1; h < centroids_left.Height; h++) { int width = stats_left.At(h, 2); int areaField1 = stats_left.At(h, 4); if ((0 <= areaField1 && areaField1 <= area)) { keyValuePairs_left.Add(h, 1); } } for (int h = 1; h < labels_left.Height; h++) { for (int w = 1; w < labels_left.Width; w++) { byte v = labels_left.At(h, w); if (v > 0 && keyValuePairs_left.ContainsKey(v)) { mat.Set(h, w, 0); } } } return mat; } /// /// 移除小的联通区域 锡膏Z /// /// /// public static Mat RemoveSmallConnZ(Mat mat, int area = 50) { for(int h=0; h< mat.Height-1; h++) { for (int w = 0; w < mat.Width-1; w++) { int v = mat.At(h, w); if(v>128) mat.Set(h, w, 255); else mat.Set(h, w, 0); } } mat = mat.Dilate(null, null, 1); OpenCvSharp.Point[][] contours; HierarchyIndex[] hierarchy; Cv2.FindContours(mat, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point()); Mat temp = new Mat(mat.Size(), mat.Type()); Cv2.DrawContours(temp, contours, -1, new Scalar(255), 1, LineTypes.Link8); Mat aaa = new Mat(temp.Size(), MatType.CV_8UC3); for(int i=0; i< contours.Length; i++) { if(hierarchy[i].Parent==-1 && Cv2.ContourArea(contours[i]) <=30) { Cv2.FloodFill(mat, contours[i][0], new Scalar(0)); } } /* Mat labels_left = new Mat(); Mat stats_left = new Mat(); Mat centroids_left = new Mat(); Cv2.ConnectedComponentsWithStats(mat, labels_left, stats_left, centroids_left, PixelConnectivity.Connectivity8); Dictionary keyValuePairs_left = new Dictionary(); for (int h = 1; h < centroids_left.Height; h++) { int width = stats_left.At(h, 2); int areaField1 = stats_left.At(h, 4); if ((0 <= areaField1 && areaField1 <= area)) { keyValuePairs_left.Add(h, 1); } } for (int h = 1; h < labels_left.Height; h++) { for (int w = 1; w < labels_left.Width; w++) { byte v = labels_left.At(h, w); if (v > 0 && keyValuePairs_left.ContainsKey(v)) { mat.Set(h, w, 0); } } }*/ return mat; } /// /// 二值化寻找直线 /// /// /// public unsafe static List FindLinesInThreshold(Mat mat, int topy, int topx, int type, XiGaoHModel model) { List lines = new List(); for (int i = 100; i < 255; i += 3) { start = 100; end = i; temp = new Mat(mat.Size(), mat.Type(), Scalar.All(0)); mat.ForEachAsByte(FindLinesInThreshold_For); foreach (int p in lines) { for (int a = 0; a < temp.Width; a++) { if (temp.At(p, a) > 0) Cv2.FloodFill(temp, new Point(a, p), Scalar.All(0)); } } if (temp.CountNonZero() > 0) { Mat labels = new Mat(); for (int h = topy; h < mat.Height - 2; h += 2) { if (type == 1) { Mat temp1 = new Mat(temp, new OpenCvSharp.Rect(topx - 400, h, 400, 3)); int v = temp1.CountNonZero(); if (v > 200 && temp1.ConnectedComponents(labels, PixelConnectivity.Connectivity8) < 10) { if (model.lowY - h > 9) { lines.Add(h); h += 8; } } } else { Mat temp1 = new Mat(temp, new OpenCvSharp.Rect(topx, h, 400, 3)); int v = temp1.CountNonZero(); if (v > 200 && temp1.ConnectedComponents(labels, PixelConnectivity.Connectivity8) < 10) { if (model.lowY - h > 9) { lines.Add(h); h += 8; } } } } } } return lines; } private static unsafe void FindLinesInThreshold_For(byte* value, int* position) { int y = position[0]; int x = position[1]; byte v = *value; if (v > 85 && v <= end) temp.Set(y, x, 255); else temp.Set(y, x, 0); } public static void SamplePic1(Mat koutu_left, Mat koutu_right, XiGaoHModel left, XiGaoHModel right, int threshold, out Mat mask_left, out Mat mask_right) { for (int i = left.topPoint.X; i < koutu_left.Width; i++) koutu_left.Col[i] *= 0; for (int i = 0; i < left.topPoint.Y + 150; i++) koutu_left.Row[i] *= 0; for (int i = 0; i < right.topPoint.X; i++) koutu_right.Col[i] *= 0; for (int i = 0; i < right.topPoint.Y + 150; i++) koutu_right.Row[i] *= 0; mask_left = koutu_left.Threshold(threshold, 255, ThresholdTypes.Binary); mask_right = koutu_right.Threshold(threshold, 255, ThresholdTypes.Binary); mask_left = null; mask_right = null; } public unsafe static Mat SamplePic1(Mat gray, double thres = 85) { threshold = thres; Mat clone = gray.Clone(); clone.ForEachAsByte(CommFillHoleEach); return clone; } public unsafe static Mat SamplePicZ(Mat gray, double thres = 85) { threshold = thres; Mat clone = gray.Clone(); clone.ForEachAsByte(CommFillHoleEachZ); return clone; } /// /// 第二次裁剪图片 /// /// /// /// /// /// /// /// 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) { //二值提取 mask_left = koutu_left.Threshold(0, 255, ThresholdTypes.Binary); mask_right = koutu_right.Threshold(0, 255, ThresholdTypes.Binary); //Cv2.ImWrite(@"C:\Users\zyh\Desktop\left_1.jpg", koutu_left); //Cv2.ImWrite(@"C:\Users\zyh\Desktop\right_1.jpg", koutu_right); //左侧 OpenCvSharp.Point[][] contours; HierarchyIndex[] hierarchy; Cv2.FindContours(mask_left, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point()); List list_left = contours.ToList(); Mat mask_l_1 = new Mat(mask_left.Size(), MatType.CV_8UC1); Cv2.DrawContours(mask_l_1, contours, -1, new Scalar(255), 1, LineTypes.Link8); int left_y = -1; for (int i = left.topPoint.Y + 150; i < mask_left.Height; i++) { if (mask_l_1.Row[i].CountNonZero() == 2) { left_y = i; break; } } if (left_y == -1) left_y = left.topPoint.Y + 200; Cv2.FindContours(mask_right, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point()); List list_right = contours.ToList(); Mat mask_r_1 = new Mat(mask_left.Size(), MatType.CV_8UC1); Cv2.DrawContours(mask_r_1, contours, -1, new Scalar(255), 1, LineTypes.Link8); int right_y = -1; for (int i = right.topPoint.Y + 150; i < mask_right.Height; i++) { if (mask_r_1.Row[i].CountNonZero() == 2) { right_y = i; break; } } if (right_y == -1) right_y = right.topPoint.Y + 200; for (int i = 0; i < right_y; i++) { koutu_right.Row[i] *= 0; mask_right.Row[i] *= 0; } for (int i = 0; i < left_y; i++) { koutu_left.Row[i] *= 0; mask_left.Row[i] *= 0; } for (int i = 0; i < right.topPoint.X; i++) { koutu_right.Col[i] *= 0; mask_right.Col[i] *= 0; } for (int i = right.topPoint.X + 450; i < koutu_right.Width; i++) { koutu_right.Col[i] *= 0; mask_right.Col[i] *= 0; } for (int i = 0; i < left.topPoint.X - 450; i++) { koutu_left.Col[i] *= 0; mask_left.Col[i] *= 0; } for (int i = left.topPoint.X; i < koutu_left.Width; i++) { koutu_left.Col[i] *= 0; mask_left.Col[i] *= 0; } OpenCvSharp.Point small = new Point(-1, -1); Cv2.FindContours(koutu_left, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point()); list_left = contours.ToList(); if (contours.Length >= 2) { for (int i = list_left.Count - 1; i >= 0; i--) { if (list_left[i].Count() < 50 || list_left[i].ToList().FindAll(a => a.Y < left.topPoint.Y + 10).Count > 0) { Cv2.FloodFill(mask_left, list_left[i][0], new Scalar(0)); list_left.RemoveAt(i); } } } contours = list_left.ToArray(); if (contours.Length >= 2) { int maxy = 0; for (int i = list_left.Count - 1; i >= 0; i--) { if (maxy == 0) { maxy = list_left[i].Max(a => a.Y); } else { if (maxy < list_left[i].Max(a => a.Y)) { maxy = list_left[i].Max(a => a.Y); mask_left.FloodFill(list_left[i][0], new Scalar(0)); list_left.RemoveAt(i); } } } } contours = list_left.ToArray(); if (contours.Length == 0) return; if (contours.Length >= 2) { int countPoints = 0; if (contours.Length > 2) { countPoints = contours.ToList().Min(a => a.Length); } foreach (OpenCvSharp.Point[] p in contours) { if (contours.Length > 2) { if (p.Length == countPoints) { mask_left.FloodFill(p[0], new Scalar(0)); break; } } List ps = p.ToList(); if (left.lowY == 0) { left.lowY = ps.Max(a => a.Y); } else { if (left.lowY < ps.Max(a => a.Y)) left.lowY = ps.Max(a => a.Y); } if (left.highY == 0) { left.highY = ps.Min(a => a.Y); left.highX = ps.ToList().Find(a => a.Y == left.highY).X; } else { if (left.highY > ps.Min(a => a.Y)) { left.highY = ps.Min(a => a.Y); left.highX = ps.ToList().Find(a => a.Y == left.highY).X; } } if (small.X == -1) { small = ps.Find(b => b.Y == ps.Min(a => a.Y)); } else { OpenCvSharp.Point t = ps.Find(b => b.Y == ps.Min(a => a.Y)); if (t.Y < small.Y) { small = t; } } left.centerX = (ps.Min(a => a.X) + ps.Max(a => a.X)) / 2; if (left.centerX < left.highX) { left.centerOffSetHighY = ps.Where(a => a.X < left.centerX - 110).ToList().Min(b => b.Y); left.centerOffSetHighX = ps.Where(a => a.X < left.centerX - 110).ToList().Find(b => b.Y == left.centerOffSetHighY).X; } } mask_left.FloodFill(small, new Scalar(0)); } else { left.lowY = contours[0].Max(a => a.Y); left.highY = contours[0].Min(a => a.Y); left.highX = contours[0].ToList().Find(a => a.Y == left.highY).X; left.centerX = (contours[0].Min(a => a.X) + contours[0].Max(a => a.X)) / 2; if (left.centerX < left.highX) { left.centerOffSetHighY = contours[0].ToList().Where(a => a.X < left.centerX - 110).ToList().Min(b => b.Y); left.centerOffSetHighX = contours[0].Where(a => a.X < left.centerX - 110).ToList().Find(b => b.Y == left.centerOffSetHighY).X; } } small = new Point(-1, -1); Cv2.FindContours(mask_right, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point()); list_right = contours.ToList(); if (contours.Length >= 2) { for (int i = list_right.Count - 1; i >= 0; i--) { if (list_right[i].Count() < 50 || list_right[i].ToList().FindAll(a => a.Y < right.topPoint.Y + 10).Count > 0) { Cv2.FloodFill(mask_right, list_right[i][0], new Scalar(0)); list_right.RemoveAt(i); } } } contours = list_right.ToArray(); if (contours.Length == 0) return; if (contours.Length >= 2) { int maxy = 0; for (int i = list_right.Count - 1; i >= 0; i--) { if (maxy == 0) { maxy = list_right[i].Max(a => a.Y); } else { if (maxy < list_right[i].Max(a => a.Y)) { maxy = list_right[i].Max(a => a.Y); mask_right.FloodFill(list_right[i][0], new Scalar(0)); list_right.RemoveAt(i); } } } } contours = list_right.ToArray(); if (contours.Length >= 2) { int countPoints = 0; if (contours.Length > 2) { countPoints = contours.ToList().Min(a => a.Length); } int k = 0; foreach (OpenCvSharp.Point[] p in contours) { if (hierarchy[k].Parent > -1) { break; } if (contours.Length > 2) { if (p.Length == countPoints) { mask_right.FloodFill(p[0], new Scalar(0)); break; } } List ps = p.ToList(); if (right.lowY == 0) { right.lowY = ps.Max(a => a.Y); } else { if (right.lowY < ps.Max(a => a.Y)) right.lowY = ps.Max(a => a.Y); } if (right.highY == 0) { right.highY = ps.Min(a => a.Y); right.highX = ps.ToList().Find(a => a.Y == right.highY).X; } else { if (right.highY > ps.Min(a => a.Y)) { right.highY = ps.Min(a => a.Y); right.highX = ps.ToList().Find(a => a.Y == right.highY).X; } } if (small.X == -1) { small = ps.Find(b => b.Y == ps.Min(a => a.Y)); } else { OpenCvSharp.Point t = ps.Find(b => b.Y == ps.Min(a => a.Y)); if (t.Y < small.Y) { small = t; } } right.centerX = (ps.Min(a => a.X) + ps.Max(a => a.X)) / 2; if (right.centerX > right.highX) { right.centerOffSetHighY = ps.Where(a => a.X > right.centerX + 110).ToList().Min(b => b.Y); right.centerOffSetHighX = ps.Where(a => a.X > right.centerX + 110).ToList().Find(b => b.Y == right.centerOffSetHighY).X; } } mask_right.FloodFill(small, new Scalar(0)); } else { right.lowY = contours[0].Max(a => a.Y); right.highY = contours[0].Min(a => a.Y); right.highX = contours[0].ToList().Find(a => a.Y == right.highY).X; right.centerX = (contours[0].Min(a => a.X) + contours[0].Max(a => a.X)) / 2; if (right.centerX > right.highX) { right.centerOffSetHighY = contours[0].ToList().Where(a => a.X > right.centerX + 110).ToList().Min(b => b.Y); right.centerOffSetHighX = contours[0].Where(a => a.X > right.centerX + 110).ToList().Find(b => b.Y == right.centerOffSetHighY).X; } } } private static unsafe void CommFillHoleEach(byte* value, int* position) { int y = position[0]; int x = position[1]; byte v = *value; if (v < 85 && v > 0) *value = 255; } private static unsafe void CommFillHoleEachZ(byte* value, int* position) { int y = position[0]; int x = position[1]; byte v = *value; if (v < threshold && v > 0) *value = 255; if (v==0) *value = 255; } /// /// /// /// /// 1左 2右 /// public static List FindLastLine(List list/*, List prevList*/, Mat mat, int type, int width = 0, int times = 1) { int now_l = (width == 0) ? mat.Width - 1 : width; int now_r = width; if (type == 1) { int xleft = 0; for (int i = now_l; i >= 0; i--) { if (mat.Col[i].CountNonZero() == 4) { xleft = i; break; } } for (int i = 0; i < mat.Height - 1; i++) { if (mat.At(i, xleft) > 0) list.Add(i); } bool pass = true; if (list.Count == 4) { if (list[1] - list[0] <= 5 || list[2] - list[1] <= 5 || list[3] - list[2] <= 5) { pass = false; } } else { pass = false; } if (pass || times > 20) return list;// list.Count == 4 ? list : prevList; if (!pass) { //if (list.Count == 4) //{ // prevList.Clear(); // prevList.AddRange(list); //} list.Clear(); FindLastLine(list/*, prevList*/, mat, 1, xleft - 1, ++times); } } else { int xright = 0; for (int i = now_r; i < mat.Width; i++) { if (mat.Col[i].CountNonZero() == 4) { xright = i; break; } } for (int i = 0; i < mat.Height - 1; i++) { if (mat.At(i, xright) > 0) list.Add(i); } bool pass = true; if (list.Count == 4) { if (list[1] - list[0] <= 5 || list[2] - list[1] <= 5 || list[3] - list[2] <= 5) { pass = false; } } else { pass = false; } if (pass || times > 20) return list;// list.Count == 4 ? list : prevList;// return list; if (!pass) { //if (list.Count == 4) //{ // prevList.Clear(); // prevList.AddRange(list); //} list.Clear(); FindLastLine(list/*, prevList*/, mat, 2, xright + 1, ++times); } } //if (list.Count == 0 && prevList.Count == 4) // list.AddRange(prevList); return list; } /// /// /// /// /// 1左 2右 /// public static List FindLastLine(List list, List prevList, Mat mat, int type, int width = 0, int times = 1) { int now_l = (width == 0) ? mat.Width - 1 : width; int now_r = width; if (type == 1) { int xleft = 0; for (int i = now_l; i >= 0; i--) { if (mat.Col[i].CountNonZero() == 4) { xleft = i; break; } } for (int i = 0; i < mat.Height - 1; i++) { if (mat.At(i, xleft) > 0) list.Add(i); } bool pass = true; if (list.Count == 4) { if (list[1] - list[0] <= 5 || list[2] - list[1] <= 5 || list[3] - list[2] <= 5) { pass = false; } } else { pass = false; } if (pass || times > 20) return list.Count == 4 ? list : prevList;// list;// if (!pass) { if (list.Count == 4) { prevList.Clear(); prevList.AddRange(list); } list.Clear(); FindLastLine(list, prevList, mat, 1, xleft - 1, ++times); } } else { int xright = 0; for (int i = now_r; i < mat.Width; i++) { if (mat.Col[i].CountNonZero() == 4) { xright = i; break; } } for (int i = 0; i < mat.Height - 1; i++) { if (mat.At(i, xright) > 0) list.Add(i); } bool pass = true; if (list.Count == 4) { if (list[1] - list[0] <= 5 || list[2] - list[1] <= 5 || list[3] - list[2] <= 5) { pass = false; } } else { pass = false; } if (pass || times > 20) return list.Count == 4 ? list : prevList;// return list;// list;// if (!pass) { if (list.Count == 4) { prevList.Clear(); prevList.AddRange(list); } list.Clear(); FindLastLine(list, prevList, mat, 2, xright + 1, ++times); } } if (list.Count == 0 && prevList.Count == 4) list.AddRange(prevList); return list; } public static void CClearDirtyData(Mat mat) { for (int i = mat.Height - 1; i >= 0; i--) { if (mat.Row[i].CountNonZero() > 0 && mat.Row[i].CountNonZero() < 20) { mat.Row[i] *= 0; } } } public unsafe static Mat ReverseNoneZeroPixel(Mat mat) { mat.ForEachAsByte(ReverseNoneZeroPixel_AsByte); mat = mat.Erode(null, null, 1); return mat; } private unsafe static void ReverseNoneZeroPixel_AsByte(byte* value, int* position) { int y = position[0]; int x = position[1]; byte v = *value; if (v > 0) { *value = (byte)(255 - v); /* byte j = (byte)(255 - v); if(j>150) *value = 0; else if (j < 47) *value = 0;*/ } } public static List FindAllLine(Mat koutu_left_canny, XiGaoHModel model, int lastLine, int offsetY = 23) { List final = new List(); List xs = new List(); List ys0 = new List(); //Dictionary dict = new Dictionary(); //Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\canny_left_3T.jpg", koutu_left_canny); for (int i = lastLine - offsetY; i > model.topPoint.Y + 200; i--) { int v = koutu_left_canny.Row[i].CountNonZero(); //if (v>0) { //dict.Add(i, v); xs.Add(i); ys0.Add(v); } } int[] hist_int = ys0.ToArray(); // HistTools.Smooth(ys.ToArray(), 10, ys.Count); List temps = hist_int.ToList(); int max = temps.Max(a => a); int max_index = temps.FindIndex(a => a == max); int h = 0; ////过滤3(11).jpg的强干扰 //int ensureTimes = 0; ////int max_next = -1;// temps.FindIndex(a => a == max); ////for (int i = max_index + 15; i < temps.Count; i++) ////{ //// if (temps[i] > 0) //// { //// max_next = i; //// break; //// } ////} //while (max_index > 20/*max_next == -1*/ && ++ensureTimes < 10) //{ // hist_int[max_index] = 0; // temps[max_index] = 0; // max = temps.Max(a => a); // max_index = temps.FindIndex(a => a == max); // //max_next = -1;// temps.FindIndex(a => a == max); // //for (int i = max_index + 15; i < temps.Count; i++) // //{ // // if (temps[i] > 0) // // { // // max_next = i; // // break; // // } // //} //} Console.WriteLine("max_index:" + max_index + "...offsetY:" + offsetY); for (int i = max_index; i >= 0; i--) { if (h > 10) break; h++; if (hist_int[i] > 0) { hist_int[i] = 0; } /*else { break; }*/ } int g = 0; for (int i = max_index + 1; i < hist_int.Length - 1; i++) { if (g > 10) break; g++; if (hist_int[i] > 0) { hist_int[i] = 0; } /*else { break; }*/ } if (max > 30 && Math.Abs(xs[max_index] - model.highY) >= 14) final.Add(xs[max_index]); temps = hist_int.ToList(); max = temps.Max(a => a); max_index = temps.FindIndex(a => a == max); if (max > 30 && Math.Abs(xs[max_index] - model.highY) >= 14) final.Add(xs[max_index]); return final; } public static void DisposeMat(Mat mat) { if (mat != null && !mat.IsDisposed) mat.Dispose(); } /// /// 处理旋转的图像 /// /// /// public static Mat ActioSpinXiGao(Mat gray) { Mat gray1 = gray.Clone(); int left_top = Cv2.FloodFill(gray1, new Point(0, 0), new Scalar(0)); int right_top = Cv2.FloodFill(gray1, new Point(gray.Width-1, 0), new Scalar(0)); int right_bottom = Cv2.FloodFill(gray1, new Point(gray.Width - 1, gray.Height-1), new Scalar(0)); int left_bottom = Cv2.FloodFill(gray1, new Point(0, gray.Height - 1), new Scalar(0)); if (right_top == right_bottom && right_bottom == left_bottom) return gray1; return gray; } public static int FineTuningLastLine(int lineY, Mat gray) { int topY = lineY - 5; int bottomY = lineY + 1; List means = new List(); List ys = new List(); for (int i=topY; i< bottomY; i++) { means.Add((int)(gray.Row[i].Mean())); ys.Add(i); } int minY = lineY; int minV = means[5]; for(int i=0; i< means.Count; i++) { if(Math.Abs(means[i] - minV) <13) { if (means[i] < minV) { minV = means[i]; minY = ys[i]; } } } return minY; } /// /// 寻找相似的轮廓 /// /// /// /// public static Mat FindSimilarContour(Mat gray) { Mat mask = new Mat(gray.Size(), gray.Type()); //计算直方图 float[] hist_float = HistTools.CalcHist(gray); //直方图平滑 int[] hist_int = HistTools.Smooth(hist_float, 25); //计算最佳阈值 List mountainsList = new List(); List mountainsArrList = new List(); List mountainsArrListBackUp = new List(); Tools.FindTopAndBetweenWithOutWT123(hist_int, 0, 255, mountainsList, mountainsArrList, mountainsArrListBackUp, new List(), 15); int threshold = mountainsArrList[mountainsList.IndexOf(mountainsList.Min())][1] - 20; int thresholdValue = threshold < 100 ? 130 : threshold; //Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\grayMat.jpg", gray); //二值化 Mat thresholdMat = gray.Threshold(thresholdValue/*-15*/, 255, ThresholdTypes.Binary); //Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\thresholdMat.jpg", thresholdMat); //碎屑删除 thresholdMat = thresholdMat.Dilate(null, null, 3); //Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\thresholdMat_1.jpg", thresholdMat); thresholdMat = BinaryTools.DebrisRemoval_New(thresholdMat.CvtColor(ColorConversionCodes.GRAY2BGR), 200).CvtColor(ColorConversionCodes.BGR2GRAY); //Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\thresholdMat_2.jpg", thresholdMat); //寻找需要处理的内容 OpenCvSharp.Point[][] contours; HierarchyIndex[] hierarchy; List models = new List(); Cv2.FindContours(thresholdMat, out contours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxNone, new OpenCvSharp.Point()); Mat temp = new Mat(thresholdMat.Size(), thresholdMat.Type(), Scalar.All(0)); Cv2.DrawContours(temp, contours, -1, new Scalar(255), 3, LineTypes.Link8); //Cv2.ImWrite(@"C:\Users\zyh\Desktop\temp.jpg", temp); for (int i = 0; i < contours.Length; i++) { int height = contours[i].Max(a => a.Y) - contours[i].Min(a => a.Y); int width = contours[i].Max(a => a.X) - contours[i].Min(a => a.X); float ratio = height * 1f / width; if (contours[i].Length > 150 && Cv2.ContourArea(contours[i])>5000 && height > 90 && width < gray.Width - 50 && (ratio>0.5 && ratio<0.9)) {//筛选用于分析的锡膏 XiGaoZModel model = new XiGaoZModel(); model.SetPoints(contours[i]); models.Add(model); } } //List models_toCal = new List(); //for (int i = 0; i < models.Count; i++) // if (models[i].points.Length > 100 && models[i].points.Length < 1000) // {//筛选用于分析的锡膏 // XiGaoZModel model = new XiGaoZModel(); // model.SetPoints(models[i].points); // models_toCal.Add(model); // } //if (models_toCal.Count < 2) //{ // models_toCal.Clear(); // for (int i = 0; i < models.Count; i++) // if (models[i].points.Length > 100) // {//筛选用于分析的锡膏 // XiGaoZModel model = new XiGaoZModel(); // model.SetPoints(models[i].points); // models_toCal.Add(model); // } //} int maxV = 0; int now_y = 0; for (int i = gray.Height - 1; i >0; i-=10) { int count = models/*models_toCal*//*models*/.Count(a => a.topY < i && a.bottomY > i); if (maxV == 0) {//筛选用于分析的锡膏 now_y = i; maxV = count; } else { if(count > maxV) { maxV = count; now_y = i; } } } //筛选用于分析的锡膏 List temps = models/*models_toCal*//*models*/.FindAll(a => a.topY < now_y && a.bottomY > now_y); var array = temps.Select(a => a.points).ToArray(); Cv2.DrawContours(mask, array, -1, new Scalar(255), -1, LineTypes.Link8); //Mat mask222 = new Mat(gray.Size(), gray.Type()); //Cv2.DrawContours(mask222, array, -1, new Scalar(255), 5, LineTypes.Link8); //Cv2.ImWrite(@"C:\Users\win10SSD\Desktop\mask222.jpg", mask222); return mask; } public static List FindAllLineZ(Mat src, XiGaoZModel model, int offsetY = 23) { Mat mat = 255 - src; //去碎屑 mat = RemoveSmallConnZ(mat.Erode(null, null, 1), src.Width>300 ? 30 : 10); int hs = 5; if(mat.Width<300) { mat = mat.Erode(null, null, 1); } List final = new List(); List xs = new List(); List ys = new List(); Dictionary dict = new Dictionary(); for (int i = (int)(mat.Height*0.92); i >= hs; i--) { int sum = (int)(mat[i, i + 1, 0, mat.Width].Sum()); int noneZeroCount = mat[i - hs, i, 0, mat.Width].CountNonZero(); if(noneZeroCount > src.Width) { final.Add(i); i -= 2;// 5;// 2;// 5; } } final.Sort(); while (final.Count > 2 && final[final.Count - 1] - final[final.Count - 1 - 1] < 10) { final.RemoveAt(final.Count - 1 - 1); } if (final.Count>2) { for(int i= final.Count-1; i>0; i--) { if(final[i] - final[i-1]<10) { if (i == 1 && Math.Max(final[i - 1], final[i]) < 20) { final.RemoveAt(i - 1); break; } else final.RemoveAt(i); } } } else if(final.Count == 1) { final.Clear(); final.Add((int)(src.Height * 0.9) - 3); final.Add((int)(src.Height / 2) + 1); } else if(final.Count==0) { final.Add((int)(src.Height * 0.9) - 3); final.Add((int)(src.Height /2 ) + 1); } if (final.Count == 2) { if (final[1] - final[0] > mat.Height / 2) { final.Insert(1, mat.Height / 2 + 20); } } //顶部校验 if(final.Count == 3) { } int v = mat.Row[final.Count - 1].CountNonZero(); for (int i= final[final.Count-1]; i> final[final.Count - 1] - 6; i--) { int d = mat.Row[i].CountNonZero(); if(d>v) { v = d; final[final.Count - 1] = i; } } return final; } } }