1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231 |
- 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;
- /// <summary>
- /// 寻找构件
- /// </summary>
- /// <returns></returns>
- public static List<XiGaoHModel> FindXiGaoHModels(Mat thresholdMat)
- {
- OpenCvSharp.Point[][] contours;
- HierarchyIndex[] hierarchy;
- Cv2.FindContours(thresholdMat, out contours, out hierarchy, RetrievalModes.List, ContourApproximationModes.ApproxSimple, new OpenCvSharp.Point());
- //List<OpenCvSharp.Point[]> contoursDraw = new List<Point[]>();
- List<XiGaoHModel> list = new List<XiGaoHModel>();
- 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<XiGaoHModel> list_final = new List<XiGaoHModel>();
- 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;
- }
- /// <summary>
- /// 处理连接在一起的构件
- /// </summary>
- /// <param name="thresholdMat"></param>
- /// <param name="list_final"></param>
- /// <returns></returns>
- public static List<XiGaoHModel> FindXiGaoHModelsForConnState(Mat thresholdMat, List<XiGaoHModel> 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);
- }
- /// <summary>
- /// 移除小的联通区域 锡膏
- /// </summary>
- /// <param name="mat"></param>
- /// <returns></returns>
- 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<int, int> keyValuePairs_left = new Dictionary<int, int>();
- for (int h = 1; h < centroids_left.Height; h++)
- {
- int width = stats_left.At<int>(h, 2);
- int areaField1 = stats_left.At<int>(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<byte>(h, w);
- if (v > 0 && keyValuePairs_left.ContainsKey(v))
- {
- mat.Set<byte>(h, w, 0);
- }
- }
- }
- return mat;
- }
- /// <summary>
- /// 移除小的联通区域 锡膏Z
- /// </summary>
- /// <param name="mat"></param>
- /// <returns></returns>
- 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<byte>(h, w);
- if(v>128) mat.Set<byte>(h, w, 255);
- else mat.Set<byte>(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<int, int> keyValuePairs_left = new Dictionary<int, int>();
- for (int h = 1; h < centroids_left.Height; h++)
- {
- int width = stats_left.At<int>(h, 2);
- int areaField1 = stats_left.At<int>(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<byte>(h, w);
- if (v > 0 && keyValuePairs_left.ContainsKey(v))
- {
- mat.Set<byte>(h, w, 0);
- }
- }
- }*/
- return mat;
- }
- /// <summary>
- /// 二值化寻找直线
- /// </summary>
- /// <param name="mat"></param>
- /// <returns></returns>
- public unsafe static List<int> FindLinesInThreshold(Mat mat, int topy, int topx, int type, XiGaoHModel model)
- {
- List<int> lines = new List<int>();
- 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<byte>(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<byte>(y, x, 255);
- else
- temp.Set<byte>(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;
- }
- /// <summary>
- /// 第二次裁剪图片
- /// </summary>
- /// <param name="koutu_left"></param>
- /// <param name="koutu_right"></param>
- /// <param name="left"></param>
- /// <param name="right"></param>
- /// <param name="threshold"></param>
- /// <param name="mask_left"></param>
- /// <param name="mask_right"></param>
- 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<OpenCvSharp.Point[]> 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<OpenCvSharp.Point[]> 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<OpenCvSharp.Point> 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<OpenCvSharp.Point> 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;
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="mat"></param>
- /// <param name="type">1左 2右</param>
- /// <returns></returns>
- public static List<int> FindLastLine(List<int> list/*, List<int> 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<byte>(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<byte>(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;
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="mat"></param>
- /// <param name="type">1左 2右</param>
- /// <returns></returns>
- public static List<int> FindLastLine(List<int> list, List<int> 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<byte>(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<byte>(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<int> FindAllLine(Mat koutu_left_canny, XiGaoHModel model, int lastLine, int offsetY = 23)
- {
- List<int> final = new List<int>();
- List<int> xs = new List<int>();
- List<int> ys0 = new List<int>();
- //Dictionary<int, int> dict = new Dictionary<int, int>();
- //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<int> 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();
- }
- /// <summary>
- /// 处理旋转的图像
- /// </summary>
- /// <param name="thresholdMat"></param>
- /// <returns></returns>
- 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<int> means = new List<int>();
- List<int> ys = new List<int>();
- 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;
- }
- /// <summary>
- /// 寻找相似的轮廓
- /// </summary>
- /// <param name="lineY"></param>
- /// <param name="gray"></param>
- /// <returns></returns>
- 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<int> mountainsList = new List<int>();
- List<int[]> mountainsArrList = new List<int[]>();
- List<int[]> mountainsArrListBackUp = new List<int[]>();
- Tools.FindTopAndBetweenWithOutWT123(hist_int, 0, 255, mountainsList, mountainsArrList, mountainsArrListBackUp, new List<string>(), 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<XiGaoZModel> models = new List<XiGaoZModel>();
- 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<XiGaoZModel> models_toCal = new List<XiGaoZModel>();
- //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<XiGaoZModel> 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<int> 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<int> final = new List<int>();
- List<int> xs = new List<int>();
- List<float> ys = new List<float>();
- Dictionary<int, int> dict = new Dictionary<int, int>();
- 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;
- }
- }
- }
|