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;
}
}
}