using OpenCvSharp; using PaintDotNet.Base.CommTool; using PaintDotNet.Base.SettingModel; using System; using System.Collections; using System.Collections.Generic; using System.Drawing; using System.Windows.Forms; using PaintDotNet.Base.DedicatedAnalysis.GrainSize; namespace PaintDotNet.DedicatedAnalysis.GrainSizeStandard.IntegrationClass { class GrainSizeStandardClass { /// /// 晶粒度截点样式集成 /// public GrainPointStyleClass styleClass = new GrainPointStyleClass(); /// /// 需要根据当前操作图片备份和读取的晶粒度数据 /// public GrainSizeStandardModel standardModel = new GrainSizeStandardModel(); /// /// 根据图片保存晶粒度数据 /// public Dictionary standardDict = new Dictionary(); /// /// 获取设置颜色的集合,按照等级从小到大排序 /// public List setColorOfGrades = new List(); /// /// 选择的评定方法 /// public MethodOfAssessment methodOfAssessment; /// /// 实现手动添加在原图情况下的截点位置跟随辅助线的移动而移动 /// public void MoveOriginCutOffPoints(float offsetX, float offsetY, string currentGuideName, Mat mat) { standardModel.linePointList.Clear(); styleClass.styleModel.straightLinePointList.Clear(); styleClass.styleModel.roundLinePointList.Clear(); //获取图形上所有的点 standardModel.linePointList.AddRange(GuideClass.getGuidePointListAndClassLine(mat, currentGuideName, out styleClass.styleModel.straightLinePointList, out styleClass.styleModel.roundLinePointList)); //##21247 styleClass.styleModel.MoveOriginCutOffPoints((int)offsetX, (int)offsetY, offsetX, offsetY); } /// /// 刷新图形边线点集合 /// public void AddRectangleToRectangleFCaps(string imagesKey/* = null*/, int grainMethodType, Mat imageMat, string currentGuideName, int matLevel, Mat mat, double physical_Micron) { GrainSizeStandardModel standardModel = this.standardModel; GrainPointStyleModel styleModel = styleClass.styleModel; if (imagesKey != null) { if (!this.standardDict.ContainsKey(imagesKey)) this.standardDict.Add(imagesKey, this.standardModel.cloneListParamModel()); standardModel = this.standardDict[imagesKey]; if (!styleClass.styleDict.ContainsKey(imagesKey)) styleClass.styleDict.Add(imagesKey, styleClass.styleModel.cloneListParamModel()); styleModel = styleClass.styleDict[imagesKey]; } if (grainMethodType == 1) { standardModel.linePointList.Clear(); int guideStyle; //获取图形上所有的点 standardModel.linePointList.AddRange(GuideClass.getGuideAreaPointList(imageMat.Width, imageMat.Height, currentGuideName, physical_Micron, out guideStyle)); return; } standardModel.linePointList.Clear(); styleModel.straightLinePointList.Clear(); styleModel.roundLinePointList.Clear(); //获取图形上所有的点 standardModel.linePointList.AddRange(GuideClass.getGuidePointListAndClassLine(mat, currentGuideName, out styleModel.straightLinePointList, out styleModel.roundLinePointList)); //垂直辅助线 / 水平辅助线 bool vGuideStylesOrHGuideStyles = GuideClass.IsVGuideStylesOrHGuideStyles(currentGuideName); //自动添加截点,并赋值截距列表 styleModel.AddRectangleToRectangleFCapsAndLine(mat, matLevel, vGuideStylesOrHGuideStyles, mat/*this.documentWorkspace.CompositionSurface*/.Width , mat/*this.documentWorkspace.CompositionSurface*/.Height); } /// /// 标准的方法类型(0 截点法/截距法, 1 面积法) /// public int GrainMethodType { get { if (methodOfAssessment == null) { return -1;//should never go here } return methodOfAssessment.grainMethodType; } } /// /// 晶粒度标准构造窗口时调用 /// /// /// public bool InitDialogMethod(MethodOfAssessment methodOfAssessment) { if (methodOfAssessment == null) return false; this.methodOfAssessment = methodOfAssessment; if (methodOfAssessment.grainMethodType == 1) GuideClass.createGuideAreaClassModelsNamed(this.methodOfAssessment.guideXmlName); else if (methodOfAssessment.grainMethodType == 0) GuideClass.createGuideClassModelsNamed(this.methodOfAssessment.guideXmlName); return true; } /// /// 晶粒度初始化辅助线组件时调用 /// /// public bool InitComboboxValue() { if (methodOfAssessment == null) return false; if (methodOfAssessment.grainMethodType == 1) GuideClass.createGuideAreaClassModelsNamed(this.methodOfAssessment.guideXmlName); else if (methodOfAssessment.grainMethodType == 0) GuideClass.createGuideClassModelsNamed(this.methodOfAssessment.guideXmlName); return true; } //Mat OriginalPicture2 = OriginalPicture0.Clone();//备注:改成切图方案更稳定些 ////int Rows = OriginalPicture0.Rows; ////int Cols = OriginalPicture0.Cols; //////List pointFs1 = GuideClass.getGuideAreaPointList(OriginalPicture0.Width, OriginalPicture0.Height, cal_GuideModel.oldSelectItem/*currentGuideName*/, physical_Micron); //////int[] point = new int[2]; //////多通道图像的格式化 ////foreach (var itemP in pointFs) //// OriginalPicture2.Set(new int[] { (int)itemP.Y, (int)itemP.X }, new Vec4b(0, 0, 0, 255)); //////Cv2.Erode(OriginalPicture1, OriginalPicture1, null, null, 1); /// //Cv2.Ellipse(imageMask, new RotatedRect(new Point2f((float)(rectangleF.X + rectangleF.Width / 2), (float)(rectangleF.Y + rectangleF.Height / 2)), new Size2f(rectangleF.Width, rectangleF.Height), 0), new Scalar(255), -1); //if (imageMask != null) imageMask.Dispose(); //GC.Collect(); //Cv2.ImShow("OriginalPicture1", OriginalPicture1); //Cv2.WaitKey(); /// /// 刷新晶粒编号 /// /// 目标选择 1不包含边缘 2边缘只处理内部 3边缘处理内外部 /// 返回晶粒个数 public double GetNumberOfGrains(bool cal_RectFlag, int targetSelection, GrainSizeStandardModel cal_StandardModel, GrainSizeGuideModel cal_GuideModel, Mat OriginalPicture0, Mat analyzeMat, bool analyzePhase, double physical_Micron, out Mat temp) { int guideStyle; List pointFs = GuideClass.getGuideAreaPointList(OriginalPicture0.Width, OriginalPicture0.Height, cal_GuideModel.oldSelectItem/*currentGuideName*/, physical_Micron, out guideStyle);// cal_StandardModel.linePointList; RectangleF rectangleF = cal_GuideModel.RectangleFLine; Mat erzhi; if (targetSelection == 2) { Mat OriginalPicture1 = new Mat(); Mat imageMask = new Mat(OriginalPicture0.Size(), MatType.CV_8UC1, new Scalar(0)); if (guideStyle == 1) Cv2.Circle(imageMask, (int)(rectangleF.X + rectangleF.Width / 2), (int)(rectangleF.Y + rectangleF.Width / 2), (int)(rectangleF.Width / 2), new Scalar(255), -1); else if (guideStyle == 2) { OpenCvSharp.Point[][] arr = new OpenCvSharp.Point[1][]; arr[0] = new OpenCvSharp.Point[] { new OpenCvSharp.Point((int)(rectangleF.X), (int)(rectangleF.Y)) , new OpenCvSharp.Point((int)(rectangleF.X+ rectangleF.Width), (int)(rectangleF.Y)) , new OpenCvSharp.Point((int)(rectangleF.X+ rectangleF.Width), (int)(rectangleF.Y+ rectangleF.Height)) , new OpenCvSharp.Point((int)(rectangleF.X), (int)(rectangleF.Y+ rectangleF.Height)) }; Cv2.FillPoly(imageMask, arr, new Scalar(255)); } OriginalPicture0.CopyTo(OriginalPicture1, imageMask); erzhi = OriginalPicture1; } else if (targetSelection == 1) { erzhi = OriginalPicture0; } else//targetSelection == 3 { erzhi = OriginalPicture0; } Cv2.CvtColor(erzhi, erzhi, ColorConversionCodes.BGR2GRAY); Cv2.Threshold(erzhi, erzhi, 100, 255, ThresholdTypes.Binary);//## //Cv2.AdaptiveThreshold(erzhi, erzhi, 255, AdaptiveThresholdTypes.MeanC, ThresholdTypes.Binary, 99, 10); OpenCvSharp.Point[][] contours; HierarchyIndex[] hierarchy; Cv2.FindContours(erzhi, out contours, out hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxNone); List pointss = new List(); foreach (OpenCvSharp.Point[] contour in contours) { if (contour.Length < 100) { foreach (OpenCvSharp.Point pointI in contour) { erzhi.Set(pointI.Y, pointI.X, 255); } pointss.Add(contour); } } Cv2.FillPoly(erzhi, pointss, new Scalar(255)); Mat labelMat = new Mat(); Mat stats = new Mat(); Mat centroids = new Mat(); // 连通域数量 int nccomps = Cv2.ConnectedComponentsWithStats(erzhi, labelMat, stats, centroids, PixelConnectivity.Connectivity8); if (cal_StandardModel.currentLabelMat != null) { cal_StandardModel.currentLabelMat.Dispose(); cal_StandardModel.currentLabelMat = null; } cal_StandardModel.currentLabelMat = labelMat.Clone(); //存储矩阵数据 if (cal_StandardModel.currentStats != null) { cal_StandardModel.currentStats.Dispose(); cal_StandardModel.currentStats = null; } cal_StandardModel.currentStats = stats.Clone(); // 连通域质点 Dictionary keyValues = new Dictionary(); cal_StandardModel.massLabelPoints.Clear(); for (int label = 1; label < centroids.Height; label++) keyValues[label] = new Point2d((int)centroids.At(label, 0), (int)centroids.At(label, 1)); cal_StandardModel.currentNccompSelect.Clear(); // 矩形边线上的连通域 ArrayList nccompSelect = new ArrayList(); // 矩形四个角的连通域 ArrayList rectSelect = new ArrayList(); if (cal_RectFlag) { int label = labelMat.At((int)rectangleF.Y, (int)rectangleF.X);//PointF pointF if (!rectSelect.Contains(label)) rectSelect.Add(label); label = labelMat.At((int)rectangleF.Y, (int)(rectangleF.X + rectangleF.Width - 1)); if (!rectSelect.Contains(label)) rectSelect.Add(label); label = labelMat.At((int)(rectangleF.Y + rectangleF.Height - 1), (int)(rectangleF.X + rectangleF.Width - 1)); if (!rectSelect.Contains(label)) rectSelect.Add(label); label = labelMat.At((int)(rectangleF.Y + rectangleF.Height - 1), (int)rectangleF.X); if (!rectSelect.Contains(label)) rectSelect.Add(label); } if (targetSelection == 2 || targetSelection == 3) foreach (PointF pointF in pointFs)//切换目标选择 { if (labelMat.Width <= pointF.X || labelMat.Height <= pointF.Y || pointF.X < 0 || pointF.Y < 0) continue; //判断是否在晶界上面 Vec4b vec4B = analyzeMat.At((int)pointF.Y, (int)pointF.X); if (analyzePhase && vec4B.Item3 != 0 || !analyzePhase && vec4B.Item0 == 0) continue; int label = labelMat.At((int)pointF.Y, (int)pointF.X); ////去掉四个角的晶粒 //if (cal_RectFlag && nccompSelect.Contains(label) && keyValues.ContainsKey(label) && keyValues[label] != null) //{ // 标记和跳过的操作 待完善 //} if (!rectSelect.Contains(label) && !nccompSelect.Contains(label) && keyValues.ContainsKey(label) && keyValues[label] != null) { nccompSelect.Add(label); cal_StandardModel.currentNccompSelect.Add(label); if (keyValues.ContainsKey(label) && keyValues[label] != null) cal_StandardModel.massLabelPoints.Add(label, new List() { 0, 0, keyValues[label].X, keyValues[label].Y }); } } analyzeMat.Dispose(); analyzeMat = null; // 矩形内的连通域 cal_StandardModel.within = 0; ArrayList inccompSelect = new ArrayList(); GrainSizeGuideAreaMethodModel grainSizeGuideStyleModel = GuideClass.GrainSizeGuideAreaMethodModel; // 圆形 if (grainSizeGuideStyleModel.circularGuideStyles != null) { foreach (var circularGuideStyle in grainSizeGuideStyleModel.circularGuideStyles) { if (cal_GuideModel.oldSelectItem/*currentGuideName*/.Equals(circularGuideStyle.tag)) { foreach (var keyValue in keyValues) { //求点到圆心的距离 double c = BasicCalculationHelper.GetDistance(new PointF((float)keyValue.Value.X, (float)keyValue.Value.Y), new PointF(rectangleF.X + rectangleF.Width / 2, rectangleF.Y + rectangleF.Height / 2), 10); if (!nccompSelect.Contains(keyValue.Key) && c < GuideClass.GetMat_lineDiameter(physical_Micron) / 2) { if (!inccompSelect.Contains(keyValue.Key)) { cal_StandardModel.within++; inccompSelect.Add(keyValue.Key); cal_StandardModel.currentNccompSelect.Add(keyValue.Key); if (keyValue.Value != null) cal_StandardModel.massLabelPoints.Add(keyValue.Key, new List() { 0, 1, keyValue.Value.X, keyValue.Value.Y }); } } } } } } // 矩形 if (grainSizeGuideStyleModel.rectangleGuideStyles != null) { foreach (var rectangleGuideStyle in grainSizeGuideStyleModel.rectangleGuideStyles) { if (cal_GuideModel.oldSelectItem/*currentGuideName*/.Equals(rectangleGuideStyle.tag)) { foreach (var keyValue in keyValues) { if (!rectSelect.Contains(keyValue.Key) && !nccompSelect.Contains(keyValue.Key) && keyValue.Value.X > rectangleF.X && keyValue.Value.X < rectangleF.Right && keyValue.Value.Y > rectangleF.Y && keyValue.Value.Y < rectangleF.Bottom) { if (!inccompSelect.Contains(keyValue.Key)) { cal_StandardModel.within++; inccompSelect.Add(keyValue.Key); cal_StandardModel.currentNccompSelect.Add(keyValue.Key); if (keyValue.Value != null) cal_StandardModel.massLabelPoints.Add(keyValue.Key, new List() { 0, 1, keyValue.Value.X, keyValue.Value.Y }); } } } } } } //根据等级设置晶粒颜色 temp = this.getMat2ColorOfLabelMat(cal_StandardModel, nccomps, physical_Micron); return cal_StandardModel.within + (double)nccompSelect.Count / 2; } public GrainSizeGuideClass GuideClass { get; } = new GrainSizeGuideClass(); public Mat[] CurrentStatsArray { get { return standardModel.currentStatsArray; } set { standardModel.currentStatsArray = value; } } public Mat[] CurrentLabelMatArray { get { return standardModel.currentLabelMatArray; } set { standardModel.currentLabelMatArray = value; } } /// /// 根据等级设置晶粒颜色 /// /// 连通域数量 public Mat getMat2ColorOfLabelMat(GrainSizeStandardModel cal_StandardModel, int nccomps, double physical_Micron) { if (cal_StandardModel.currentLabelMat == null || cal_StandardModel.currentStats == null) return null; Mat temp = new Mat(cal_StandardModel.currentLabelMat.Size(), MatType.CV_8UC4);//## if (setColorOfGrades.Count == 0) { GrainColorsStyleModel colorsStyleModel = XmlSerializeHelper.DESerializer(FileOperationHelper.ReadStringFromFile(Application.StartupPath + "\\Config\\" + Startup.instance.SettingPrefix + "\\GrainSizeAnalyze\\GrainColorsStyleModel.xml", System.IO.FileMode.Open)); if (colorsStyleModel == null) return null; Color color1 = Color.FromArgb(colorsStyleModel.ColorStyle1.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle2.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle3.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle4.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle5.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle6.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle7.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle8.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle9.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle10.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle11.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle12.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle13.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle14.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle15.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle16.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle17.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle18.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle19.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle20.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle21.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle22.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle23.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle24.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle25.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle26.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle27.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle28.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle29.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); color1 = Color.FromArgb(colorsStyleModel.ColorStyle30.pointColor); setColorOfGrades.Add(new Vec4b(color1.B, color1.G, color1.R, color1.A)); } //根据等级设置晶粒颜色 if (setColorOfGrades.Count > 0) { int label; double aec; Decimal NA; ////1013###19377##面积法位置,使用晶粒的实际面积去标准中的表进行对应,获取截距后,再进行平均的计算 double[] lengths = {3.88, 7.75 , 10.96, 15.50, 21.92, 31.0, 43.84, 62.0, 87.68, 124, 175.36, 248, 350.73, 496, 701.45, 992, 1402.9, 1984.0, 2805.8, 3968.0, 5611.6, 7936.0, 11223.2, 15872.0, 22446.4, 31744.1, 44892.9, 63488.1, 89785.8, 126976.3}; //Dictionary measurementUnitDictionary = Startup.instance.rules; ////选择标尺的物理长度(1倍下的 微米/像素) //double physical_area_length_Micron = measurementUnitDictionary[MeasurementUnit.Micron]; // 差值 decimal differenceNew; decimal differenceOld; int first; for (int y = 0; y < temp.Rows; y++) { for (int x = 0; x < temp.Cols; x++) { label = cal_StandardModel.currentLabelMat.At(y, x); if (!cal_StandardModel.currentNccompSelect.Contains(label)) continue; aec = cal_StandardModel.currentStats.At(label/*hcomp*/, 4) * physical_Micron * physical_Micron;//晶粒面积 aec = aec * 0.001 * 0.001; NA = Convert.ToDecimal(1.0/*grainNumber*/ / aec); differenceOld = Math.Abs(Convert.ToDecimal(Math.Max((double)NA - 2.88, (double)NA - 126977.3))); first = 0; if ((double)NA > lengths[lengths.Length - 1]) first = lengths.Length - 1; else foreach (double item in lengths) { differenceNew = Math.Abs(NA - Convert.ToDecimal(item)); if (differenceNew < differenceOld) { differenceOld = Math.Abs(NA - Convert.ToDecimal(item)); first++; } //else // break; } if (first >= lengths.Length) first = lengths.Length - 1; else if (first < 0) first = 0; temp.Set(y, x, setColorOfGrades[first/*label*/]); } } return temp; } //随机设置晶粒颜色 Random rd = new Random(); List colors = new List(nccomps); colors.Add(new Vec4b(0, 0, 0, 0)); for (int i = 1; i < nccomps; i++) { colors.Add(new Vec4b(((byte)(rd.Next() % 256)), ((byte)(rd.Next() % 256)), ((byte)(rd.Next() % 256)), 255)); } for (int y = 0; y < temp.Rows; y++) { for (int x = 0; x < temp.Cols; x++) { int label = cal_StandardModel.currentLabelMat.At(y, x); if (cal_StandardModel.currentNccompSelect.Contains(label)) temp.Set(y, x, colors[label]); } } return temp; } } }