123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966 |
- using OpenCvSharp;
- using PaintDotNet.Base.CommTool;
- using System;
- using System.Collections.Generic;
- using System.Linq;
- namespace PaintDotNet.Base.Functionodel
- {
- /// <summary>
- /// 轮廓以及相关信息
- /// 最大卡规直径\最小卡规直径\平均卡规直径,还没计算
- /// </summary>
- public class ContoursAndRelatedInfo
- {
- /// <summary>
- /// 轮廓数组
- /// </summary>
- public OpenCvSharp.Point[] contours;
- /// <summary>
- /// 完整的轮廓结构
- /// </summary>
- public List<List<OpenCvSharp.Point>> wholeContours;
-
- /// <summary>
- /// 关系
- /// </summary>
- public HierarchyIndex hierarchyIndex;
- /// <summary>
- /// 标尺
- /// </summary>
- public double rule;
- /// <summary>
- /// 下标,用于绘制等
- /// </summary>
- public int index;
- /// <summary>
- /// 原图
- /// </summary>
- public Mat mat;
- /// <summary>
- /// 灰度图
- /// </summary>
- public Mat matGray;
- /// <summary>
- /// 二值的mat的灰度图,单通道
- /// </summary>
- public Mat binarizationMatGray;
- /// <summary>
- /// 原始图片的分割
- /// </summary>
- public Mat[] mats;
- /// <summary>
- /// mask
- /// </summary>
- public Mat hole;
- /// <summary>
- /// 卡规直径的32个值
- /// </summary>
- public List<int> vs;
- /// <summary>
- /// 卡规直径的32个角度的集合
- /// </summary>
- public List<OpenCvSharp.Point[]> plist;
- /// <summary>
- /// 最大卡规直径对应的点
- /// </summary>
- public OpenCvSharp.Point[] points_max;
- /// <summary>
- /// 最小卡规直径对应的点
- /// </summary>
- public OpenCvSharp.Point[] points_min;
- /// <summary>
- /// 面积
- /// </summary>
- public double area = -1;
- /// <summary>
- /// 面积比
- /// </summary>
- public double areaRatio = -1;
- /// <summary>
- /// 周长
- /// </summary>
- public double perimeter = -1;
- /// <summary>
- /// 长轴
- /// </summary>
- public double longAxis = -1;
- /// <summary>
- /// 短轴
- /// </summary>
- public double shortAxis = -1;
- /// <summary>
- /// 中心坐标X
- /// </summary>
- public int centerX = -1;
- /// <summary>
- /// 中心坐标Y
- /// </summary>
- public int centerY = -1;
- /// <summary>
- /// 倾斜角度
- /// </summary>
- public double inclinationAngle = -1;
- /// <summary>
- /// 物相外貌
- /// </summary>
- public double objectAppearance = -1;
- /// <summary>
- /// 高度
- /// </summary>
- public int height = -1;
- /// <summary>
- /// 宽度
- /// </summary>
- public int width = -1;
- /// <summary>
- /// 宽高比
- /// </summary>
- public double aspectRatio = -1;
- /// <summary>
- /// 红密度
- /// </summary>
- public double redDensity = -1;
- /// <summary>
- /// 绿密度
- /// </summary>
- public double greenDensity = -1;
- /// <summary>
- /// 蓝密度
- /// </summary>
- public double blueDensity = -1;
- /*/// <summary>
- /// 最大密度
- /// </summary>
- public double maxDensity = -1;
- /// <summary>
- /// 最小密度
- /// </summary>
- public double minDensity = -1;
- /// <summary>
- /// 平均密度
- /// </summary>
- public double avgDensity = -1;
- /// <summary>
- /// 密度和
- /// </summary>
- public double sumDensity = -1;*/
- /// <summary>
- /// 长径
- /// </summary>
- public double majorAxis = -1;
- /// <summary>
- /// 短径
- /// </summary>
- public double minorAxis = -1;
- /// <summary>
- /// 外接圆直径
- /// </summary>
- public float circumcircleDiameter = -1;
- /// <summary>
- /// 球化率
- /// </summary>
- public double nodularity = -1;
- /// <summary>
- /// 等积圆直径
- /// </summary>
- public double equalCircleDiameter = -1;
- /// <summary>
- /// 最大卡规直径
- /// </summary>
- public int maxCaliperDiameter = -1;
- /// <summary>
- /// 最小卡规直径
- /// </summary>
- public int minCaliperDiameter = -1;
- /// <summary>
- /// 平均卡规直径
- /// </summary>
- public int avgCaliperDiameter = -1;
- /// <summary>
- /// 最大灰度
- /// </summary>
- public double maxGray = -1;
- /// <summary>
- /// 最小灰度
- /// </summary>
- public double minGray = -1;
- /// <summary>
- /// 平均灰度
- /// </summary>
- public double avgGray = -1;
- /// <summary>
- /// 纤维长度
- /// </summary>
- public double fiberLength = -1;
- /// <summary>
- /// 填充面积
- /// </summary>
- public double fillArea = -1;
- /// <summary>
- /// 腰宽
- /// </summary>
- public double waistDepth = -1;
- /// <summary>
- /// 腰深
- /// </summary>
- public double waistDepthShort = -1;
- /// <summary>
- /// 获取面积
- /// 说明:轮廓的面积
- /// </summary>
- public double Area
- {
- get
- {
- if (this.area == -1)
- {
- if (contours != null && contours.Length > 0)
- {
- Rect rect;
- this.area = Cv2.FloodFill(this.binarizationMatGray, this.contours[0], new Scalar(0, 0, 0, 0), out rect, null, null, FloodFillFlags.Link8);
- //this.area = Cv2.ContourArea(contours);
- }
- }
- return this.area * rule * rule; // (this.area - 0/*this.contours.Length / 2.0*/)<0 ? 0 : (this.area - this.contours.Length / 2.0) * rule * rule; //this.contours.Length/2.0
- }
- }
- /// <summary>
- /// 获取面积比
- /// 说明:轮廓的面积/最小外接矩形的面积
- /// </summary>
- public double AreaRatio
- {
- get
- {
- if (this.areaRatio == -1)
- {
- RotatedRect rotatedRect = Cv2.MinAreaRect(contours);
- this.areaRatio = this.Area / (rotatedRect.Size.Width * rotatedRect.Size.Height * rule * rule);
- }
- return this.areaRatio>1 ? 1 : this.areaRatio;
- }
- }
- /// <summary>
- /// 获取周长
- /// 说明:轮廓的点的个数
- /// </summary>
- public double Perimeter
- {
- get
- {
- if (this.perimeter == -1)
- {
- this.perimeter = this.contours.Length;
- }
- return this.perimeter * rule;
- }
- }
- /// <summary>
- /// 长轴
- /// 说明:最小外接矩形的长边
- /// </summary>
- public double LongAxis
- {
- get
- {
- if (this.longAxis == -1)
- {
- RotatedRect rect = Cv2.MinAreaRect(this.contours);
- this.longAxis = rect.Size.Width > rect.Size.Height ? rect.Size.Width : rect.Size.Height;
- this.shortAxis = rect.Size.Width < rect.Size.Height ? rect.Size.Width : rect.Size.Height;
- }
- return this.longAxis * rule;
- }
- }
- /// <summary>
- /// 短轴
- /// 说明:最小外接矩形的短边
- /// </summary>
- public double ShortAxis
- {
- get
- {
- if (this.shortAxis == -1)
- {
- RotatedRect rect = Cv2.MinAreaRect(this.contours);
- this.longAxis = rect.Size.Width > rect.Size.Height ? rect.Size.Width : rect.Size.Height;
- this.shortAxis = rect.Size.Width < rect.Size.Height ? rect.Size.Width : rect.Size.Height;
- }
- return this.shortAxis * rule;
- }
- }
- /// <summary>
- /// 中心坐标X
- /// 说明:外接矩形的中心
- /// </summary>
- public int CenterX
- {
- get
- {
- if (centerX == -1)
- {
- Rect rect = Cv2.BoundingRect(this.contours);
- this.centerX = rect.X + rect.Width/2;
- this.centerY = rect.Y + rect.Height / 2;
- }
- return this.centerX;
- }
- }
- /// <summary>
- /// 中心坐标Y
- /// 说明:外接矩形的中心
- /// </summary>
- public int CenterY
- {
- get
- {
- if (centerX == -1)
- {
- Rect rect = Cv2.BoundingRect(this.contours);
- this.centerX = rect.X + rect.Width / 2;
- this.centerY = rect.Y + rect.Height / 2;
- }
- return this.centerY;
- }
- }
- /// <summary>
- /// 倾斜角度
- /// </summary>
- public double InclinationAngle
- {
- get
- {
- if (this.inclinationAngle == -1)
- {
- if (this.contours.Length >= 5)
- {
- RotatedRect rect = Cv2.FitEllipse(this.contours);
- this.objectAppearance = Math.Round(rect.Size.Width, 10) / rect.Size.Height;
- this.inclinationAngle = rect.Angle;
- }
- else
- {
- this.objectAppearance = 1.0;
- this.inclinationAngle = 0.0;
- }
- }
- return this.inclinationAngle;
- }
- }
- /// <summary>
- /// 物相外貌,拟合椭圆的长短轴比
- /// </summary>
- public double ObjectAppearance
- {
- get
- {
- if(this.objectAppearance == -1)
- {
- if (this.contours.Length >= 5)
- {
- RotatedRect rect = Cv2.FitEllipse(this.contours);
- this.objectAppearance = Math.Round(rect.Size.Width, 10) / rect.Size.Height;
- this.inclinationAngle = rect.Angle;
- }
- else
- {
- this.objectAppearance = 1.0;
- this.inclinationAngle = 0.0;
- }
- }
- return this.objectAppearance;
- }
- }
- /// <summary>
- /// 高度
- /// </summary>
- public double Height
- {
- get
- {
- if(this.height == -1)
- {
- Rect rect = Cv2.BoundingRect(this.contours);
- this.height = rect.Height;
- this.width = rect.Width;
- this.aspectRatio = this.width / (this.height * 1.0);
- }
- return this.height * rule;
- }
- }
- /// <summary>
- /// 宽度
- /// </summary>
- public double Width
- {
- get
- {
- if (this.width == -1)
- {
- Rect rect = Cv2.BoundingRect(this.contours);
- this.height = rect.Height;
- this.width = rect.Width;
- this.aspectRatio = this.width / (this.height * 1.0);
- }
- return this.width * rule;
- }
- }
- /// <summary>
- /// 宽高比
- /// </summary>
- public double AspectRatio
- {
- get
- {
- if(this.aspectRatio == -1)
- {
- Rect rect = Cv2.BoundingRect(this.contours);
- this.height = rect.Height;
- this.width = rect.Width;
- this.aspectRatio = this.width / (this.height * 1.0);
- }
- return this.aspectRatio;
- }
- }
- /// <summary>
- /// 红密度
- /// </summary>
- public double RedDensity
- {
- get
- {
- if(this.redDensity == -1)
- {
- if(this.mat != null)
- {
- if(mat.Type()== MatType.CV_8UC3 || mat.Type() == MatType.CV_8UC4)
- {
- hole.SetTo(Scalar.All(-1));
- Cv2.FillPoly(hole, wholeContours, Scalar.All(255));
- double temp;
- Cv2.MinMaxIdx(mats[0], out temp, out this.blueDensity, new int[1], new int[1], hole);
- Cv2.MinMaxIdx(mats[1], out temp, out this.greenDensity, new int[1], new int[1], hole);
- Cv2.MinMaxIdx(mats[2], out temp, out this.redDensity, new int[1], new int[1], hole);
- }
- }
- }
- return this.redDensity;
- }
- }
- /// <summary>
- /// 绿密度
- /// </summary>
- public double GreenDensity
- {
- get
- {
- if (this.greenDensity == -1)
- {
- if (this.mat != null)
- {
- if (mat.Type() == MatType.CV_8UC3 || mat.Type() == MatType.CV_8UC4)
- {
- hole.SetTo(Scalar.All(-1));
- Cv2.FillPoly(hole, wholeContours, Scalar.All(255));
- double temp;
- Cv2.MinMaxIdx(mats[0], out temp, out this.blueDensity, new int[1], new int[1], hole);
- Cv2.MinMaxIdx(mats[1], out temp, out this.greenDensity, new int[1], new int[1], hole);
- Cv2.MinMaxIdx(mats[2], out temp, out this.redDensity, new int[1], new int[1], hole);
- /*Mat temp1 = DrawRulerHelper.CopyMatFromContours(this.mat, this.wholeContours);
- double temp;
- Mat[] mats = temp1.Split();
- Cv2.MinMaxIdx(mats[0], out temp, out this.blueDensity);
- Cv2.MinMaxIdx(mats[1], out temp, out this.greenDensity);
- Cv2.MinMaxIdx(mats[2], out temp, out this.redDensity);*/
- }
- }
- }
- return this.greenDensity;
- }
- }
- /// <summary>
- /// 蓝密度
- /// </summary>
- public double BlueDensity
- {
- get
- {
- if (this.blueDensity == -1)
- {
- if (this.mat != null)
- {
- if (mat.Type() == MatType.CV_8UC3 || mat.Type() == MatType.CV_8UC4)
- {
- hole.SetTo(Scalar.All(-1));
- Cv2.FillPoly(hole, wholeContours, Scalar.All(255));
- double temp;
- Cv2.MinMaxIdx(mats[0], out temp, out this.blueDensity, new int[1], new int[1], hole);
- Cv2.MinMaxIdx(mats[1], out temp, out this.greenDensity, new int[1], new int[1], hole);
- Cv2.MinMaxIdx(mats[2], out temp, out this.redDensity, new int[1], new int[1], hole);
- /*Mat temp1 = DrawRulerHelper.CopyMatFromContours(this.mat, this.wholeContours);
- double temp;
- Mat[] mats = temp1.Split();
- Cv2.MinMaxIdx(mats[0], out temp, out this.blueDensity);
- Cv2.MinMaxIdx(mats[1], out temp, out this.greenDensity);
- Cv2.MinMaxIdx(mats[2], out temp, out this.redDensity);*/
- }
- }
- }
- return this.blueDensity;
- }
- }
-
- /*/// <summary>
- /// 最大密度
- /// 说明:按AxioVision的说明
- /// Highest gray value of a region
- /// The gray values of a region are analyzed and the maximum value displayed.This is the brightest point in a region.If this parameter is measured for regions inside an RGB color image, the RGB color image is first converted to a gray level image in accordance with the formula (R+G+B) / 3 and the corresponding maximum value is then displayed.If you want the maximum values to be determined separately for one or all color channels, you need to use the Densitometric maximum blue, Densitometric maximum green and Densitometric maximum red parameters. This parameter can also be used to measure the maximum gray value of regions in multichannel fluorescence images.As a multichannel fluorescence image consists of several gray level images, no special parameter is needed.
- /// Unit: "gray levels" or "gray"
- /// Value range: 0...65535 (depending on the pixel or color depth of the image).
- /// </summary>
- public double MaxDensity
- {
- get
- {
- return this.maxDensity;
- }
- }
-
- /// <summary>
- /// 最小密度
- /// </summary>
- public double MinDensity
- {
- get
- {
- return this.minDensity;
- }
- }
-
- /// <summary>
- /// 平均密度
- /// Average of all gray values of a region
- /// The gray values of a region are analyzed and the average of all gray values displayed.If this parameter is measured for regions inside an RGB color image, the RGB color image is first converted to a gray level image in accordance with the formula (R+G+B) / 3 and the corresponding average is then displayed.If you want the averages to be determined separately for one or all color channels, you need to use the Densitometric mean blue, Densitometric mean green and Densitometric mean red parameters. This parameter can also be used to measure the average gray value of regions in multichannel fluorescence images.As a multichannel fluorescence image consists of several gray level images, no special parameter is needed.
- /// Unit: "gray levels" or "gray"
- /// Value range: 0...65535 (depending on the pixel or color depth of the image).
- /// </summary>
- public double AvgDensity
- {
- get
- {
- return avgDensity;
- }
- }
-
- /// <summary>
- /// 密度和
- /// Sum of gray values of a region
- /// All gray values of a region are added together.If this parameter is measured for regions inside an RGB color image, the RGB color image is first converted to a gray level image in accordance with the formula (R+G+B) / 3 and the sum is then calculated. If you want the sum to be determined separately for one or all color channels, you need to use the Densitometric sum blue, Densitometric sum green and Densitometric sum red parameters. This parameter can also be used to measure the sum of regions in multichannel fluorescence images. As a multichannel fluorescence image consists of several gray level images, no special parameter is needed.
- /// Unit: "gray levels" or "gray"
- /// Name in data tables: DensSum1
- /// </summary>
- public double SumDensity
- {
- get
- {
- return this.sumDensity;
- }
- }*/
-
- /// <summary>
- /// 长径(暂时理解为最小外接矩形的长边的一半)
- /// </summary>
- public double MajorAxis
- {
- get
- {
- if(this.majorAxis == -1)
- {
- this.majorAxis = this.LongAxis / 2;
- }
- return this.majorAxis;
- }
- }
- /// <summary>
- /// 短径(暂时理解为最小外接矩形的短边的一半)
- /// </summary>
- public double MinorAxis
- {
- get
- {
- if(this.minorAxis==-1)
- {
- this.minorAxis = this.ShortAxis / 2;
- }
- return this.minorAxis;
- }
- }
- /// <summary>
- /// 外接圆直径 = 最小外接圆的直径
- /// </summary>
- public float CircumcircleDiameter
- {
- get
- {
- if(this.circumcircleDiameter == -1)
- {
- Point2f point;
- float radius;
- if (this.contours.Length > 500)
- {
- Cv2.MinEnclosingCircle(Cv2.ConvexHull(this.contours, true), out point, out radius);
- }
- else
- {
- Cv2.MinEnclosingCircle(this.contours, out point, out radius);
- }
- this.circumcircleDiameter = radius * 2;
- this.nodularity = this.Area / (Math.PI * radius * radius * rule * rule);
- }
- return (float)(this.circumcircleDiameter * rule);
- }
- }
- /// <summary>
- /// 球化率 = 面积 / 最小外接圆的面积
- /// </summary>
- public double Nodularity
- {
- get
- {
- if (this.nodularity == -1)
- {
- Point2f point;
- float radius;
- if (this.contours.Length>500)
- {
- Cv2.MinEnclosingCircle(Cv2.ConvexHull(this.contours, true), out point, out radius);
- }
- else
- {
- Cv2.MinEnclosingCircle(this.contours, out point, out radius);
- }
- this.circumcircleDiameter = radius * 2;
- this.nodularity = this.Area / (Math.PI * radius * radius * rule * rule);
- }
- return this.nodularity>1 ? 1 : this.nodularity;
- }
- }
- /// <summary>
- /// 等积圆直径
- /// </summary>
- public double EqualCircleDiameter
- {
- get
- {
- if (this.equalCircleDiameter==-1)
- {
- this.equalCircleDiameter = Math.Sqrt(this.Area / Math.PI) * 2;
- }
- return this.equalCircleDiameter;
- }
- }
-
- /// <summary>
- /// 最大卡规直径
- /// </summary>
- public double MaxCaliperDiameter
- {
- get
- {
- if (this.maxCaliperDiameter == -1)
- {
- vs = BasicCalculationHelper.GetCaliperDiameter(this.contours, this.hierarchyIndex, out plist);
- this.maxCaliperDiameter = vs.Max();
- this.avgCaliperDiameter = (int)vs.Average();
- this.minCaliperDiameter = vs.Min();
- }
- return this.maxCaliperDiameter * rule;
- }
- }
- /// <summary>
- /// 最小卡规直径
- /// </summary>;
- public double MinCaliperDiameter
- {
- get
- {
- if (this.minCaliperDiameter == -1)
- {
- vs = BasicCalculationHelper.GetCaliperDiameter(this.contours, this.hierarchyIndex, out plist);
- this.maxCaliperDiameter = vs.Max();
- this.avgCaliperDiameter = (int)vs.Average();
- this.minCaliperDiameter = vs.Min();
- }
- return this.minCaliperDiameter * rule;
- }
- }
- /// <summary>
- /// 平均卡规直径
- /// </summary>
- public double AvgCaliperDiameter
- {
- get
- {
- if (this.avgCaliperDiameter == -1)
- {
- vs = BasicCalculationHelper.GetCaliperDiameter(this.contours, this.hierarchyIndex, out plist);
- this.maxCaliperDiameter = vs.Max();
- this.avgCaliperDiameter = (int)vs.Average();
- this.minCaliperDiameter = vs.Min();
- }
- return this.avgCaliperDiameter * rule;
- }
- }
- /// <summary>
- /// 最大灰度
- /// </summary>
- public double MaxGray
- {
- get
- {
- if(this.maxGray == -1)
- {
- hole.SetTo(Scalar.All(-1));
- Cv2.FillPoly(hole, wholeContours, Scalar.All(255));
- this.matGray.MinMaxIdx(out this.minGray, out this.maxGray, new int[1], new int[1], hole);
- }
- return this.maxGray;
- }
- }
- /// <summary>
- /// 最小灰度
- /// </summary>
- public double MinGray
- {
- get
- {
- if (this.minGray == -1)
- {
- hole.SetTo(Scalar.All(-1));
- Cv2.FillPoly(hole, wholeContours, Scalar.All(255));
- this.matGray.MinMaxIdx(out this.minGray, out this.maxGray, new int[1], new int[1], hole);
- }
- return this.minGray;
- }
- }
- public List<int> Vs
- {
- get
- {
- return this.vs;
- }
- set
- {
- this.vs = value;
- }
- }
- /// <summary>
- /// 平均灰度
- /// </summary>
- public double AvgGray
- {
- get
- {
- if (this.avgGray == -1)
- {
- hole.SetTo(Scalar.All(-1));
- Cv2.FillPoly(hole, wholeContours, Scalar.All(255));
- Mat mean = new Mat();
- Cv2.MeanStdDev(this.matGray, mean, new Mat(), hole);
- mean.ConvertTo(mean, MatType.CV_8UC1);
- this.avgGray = mean.At<byte>(0, 0);
- mean.Dispose();
- }
- return this.avgGray;
- }
- }
- /// <summary>
- /// 纤维长度
- /// 说明:公式参考AxioVision,(周长 + (周长的平方-16*面积)的平方根)/4
- /// </summary>
- public double FiberLength
- {
- get
- {
- return rule * (this.Perimeter + Math.Sqrt(this.Perimeter * this.Perimeter + 16 * this.Area)) / 4;
- }
- }
- /// <summary>
- /// 填充面积
- /// </summary>
- public double FillArea
- {
- get
- {
- if(this.fillArea == -1)
- {
- hole.SetTo(Scalar.All(-1));
- List<List<Point>> list = new List<List<Point>>();
- list.Add(this.contours.ToList());
- Cv2.FillPoly(this.hole, list, new Scalar(255, 255, 255, 0), LineTypes.Link8);
- Rect rect;
- int area_t = Cv2.FloodFill(this.hole, this.contours[0], new Scalar(0, 0, 0, 0), out rect, null, null, FloodFillFlags.Link8);
- this.fillArea = area_t * rule * rule - this.Area;
- }
- return this.fillArea;
- }
- }
- /// <summary>
- /// 腰深
- /// </summary>
- public double WaistDepth
- {
- get
- {
- if (this.waistDepth == -1)
- {
- //需要根据index 获取旋转的角度,再把点旋转回来
- if (this.MinCaliperDiameter > 0)
- {
- points_max = new Point[2];
- points_min = new Point[2];
- int max = vs.Max();
- int min = vs.Min();
- int index_max = vs.FindIndex(a => a == max);
- int index_min = vs.FindIndex(a => a == min);
- //计算中心点
- OpenCvSharp.Moments m = OpenCvSharp.Cv2.Moments(contours);
- double cx = m.M10 / m.M00;
- double cy = m.M01 / m.M00;
- try
- {
- //最大卡规直径的点
- points_max[0] = BasicCalculationHelper.GetPointAffinedPos(plist[index_max][0], new OpenCvSharp.Point(cx, cy), -360 / 64 * index_max);
- points_max[1] = BasicCalculationHelper.GetPointAffinedPos(plist[index_max][1], new OpenCvSharp.Point(cx, cy), -360 / 64 * index_max);
- //最小卡规直径的点,但是没有明显意义
- points_min[0] = BasicCalculationHelper.GetPointAffinedPos(plist[index_min][0], new OpenCvSharp.Point(cx, cy), -360 / 64 * index_min);
- points_min[1] = BasicCalculationHelper.GetPointAffinedPos(plist[index_min][1], new OpenCvSharp.Point(cx, cy), -360 / 64 * index_min);
- //寻找最大卡规直径的中垂线再轮廓上的点
- //1、把两个点都旋转九十度,得到两个新的点
- double cx1 = (points_max[0].X + points_max[1].X) / 2;
- double cy1 = (points_max[0].Y + points_max[1].Y) / 2;
- System.Drawing.Point a1 = BasicCalculationHelper.GetAnglePoint(new System.Drawing.Point(points_max[0].X, points_max[0].Y), new System.Drawing.Point((int)cx1, (int)cy1), 90);
- System.Drawing.Point b1 = BasicCalculationHelper.GetAnglePoint(new System.Drawing.Point(points_max[1].X, points_max[1].Y), new System.Drawing.Point((int)cx1, (int)cy1), 90);
- List<System.Drawing.Point> ps = BasicCalculationHelper.CalcExtensionCord(a1, b1);
- a1 = ps[0];
- b1 = ps[1];
- //Cv2.Line(this.mat, points_max[0], points_max[1], new Scalar(0, 0, 255), 3);
- //Cv2.Line(this.mat, new Point(a1.X, a1.Y), new Point(b1.X, b1.Y), new Scalar(0, 0, 255), 3);
- List<System.Drawing.Point> intersections = new List<System.Drawing.Point>();
- LineIterator it = new LineIterator(this.mat, new Point(a1.X, a1.Y), new Point(b1.X, b1.Y), PixelConnectivity.Connectivity8);
- foreach (var lip in it)
- {
- OpenCvSharp.Point p = lip.Pos;
- if (Math.Abs(Cv2.PointPolygonTest(contours, p, true)) < 1)
- {
- intersections.Add(new System.Drawing.Point(p.X, p.Y));
- //Cv2.Circle(this.mat, p, 1, new Scalar(255, 0, 0), 3);
- }
- }
- this.waistDepth = BasicCalculationHelper.GetLeftAndRightOrTopAndBottomPoint(intersections) * rule;
- }
- catch(Exception)
- {
- this.waistDepth = 0;
- }
- }
- else
- {
- this.waistDepth = 0;
- }
- }
- return this.waistDepth;
- }
- }
- /// <summary>
- /// 腰宽
- /// </summary>
- public double WaistDepthShort
- {
- get
- {
- if (this.waistDepthShort == -1)
- {
- this.waistDepthShort = this.MinCaliperDiameter - this.WaistDepth;
- }
- return this.waistDepthShort<0 ? 0 : this.waistDepthShort;
- }
- }
- }
- }
|