| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773 | using OTSDataType;using OTSModelSharp.ImageProcess;using System;using System.Collections.Generic;using System.Drawing;using System.Linq;using System.Text;using System.Threading.Tasks;using static OTSDataType.otsdataconst;namespace OTSModelSharp.ServiceCenter{    using OpenCvSharp;    using OTSCLRINTERFACE;    using OTSIMGPROC;    using System.Drawing.Imaging;    using System.Runtime.InteropServices;    using System.Windows;    public class CImageHandler    {        private ImageProForClr imgProEngine;        public CImageHandler()        {            COTSImgProcPrmClr imageprocessParam = new COTSImgProcPrmClr();            imgProEngine = new ImageProForClr(imageprocessParam);        }        #region 通过byte数组生成BMP图像文件        /// <summary>            /// 将一个byte的数组转换为8bit灰度位图        /// </summary>            /// <param name="data">数组</param>            /// <param name="width">图像宽度</param>            /// <param name="height">图像高度</param>            /// <returns>位图</returns>            public static Bitmap ToGrayBitmap(byte[] data, int width, int height)        {            if (width == 0 || height == 0)                 return null;            //// 申请目标位图的变量,并将其内存区域锁定                Bitmap bmp = new Bitmap(width, height, PixelFormat.Format8bppIndexed);            //// BitmapData这部分内容  需要 using System.Drawing.Imaging;              BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, width, height),            ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);            //// 获取图像参数                // 扫描线的宽度               int stride = bmpData.Stride;            // 显示宽度与扫描线宽度的间隙              int offset = stride - width;            // 获取bmpData的内存起始位置            IntPtr iptr = bmpData.Scan0;            // 用stride宽度,表示这是内存区域的大小            int scanBytes = stride * height;            //// 下面把原始的显示大小字节数组转换为内存中实际存放的字节数组                int posScan = 0;            int posReal = 0;// 分别设置两个位置指针,指向源数组和目标数组                byte[] pixelValues = new byte[scanBytes];  //为目标数组分配内存                //for (int x = height-1;x>=0 ; x--) data[startIndex+ y];//            for (int x = 0; x < height; x++)            {                int startIndex = x * width;                //// 下面的循环节是模拟行扫描                    for (int y = 0; y < width; y++)                {                    pixelValues[posScan++] = data[posReal++];                }                posScan += offset;  //行扫描结束,要将目标位置指针移过那段“间隙”                }            //// 用Marshal的Copy方法,将刚才得到的内存字节数组复制到BitmapData中                System.Runtime.InteropServices.Marshal.Copy(pixelValues, 0, iptr, scanBytes);            bmp.UnlockBits(bmpData);  // 解锁内存区域                //// 下面的代码是为了修改生成位图的索引表,从伪彩修改为灰度                ColorPalette tempPalette;            using (Bitmap tempBmp = new Bitmap(1, 1, PixelFormat.Format8bppIndexed))            {                tempPalette = tempBmp.Palette;            }            for (int i = 0; i < 256; i++)            {                tempPalette.Entries[i] = Color.FromArgb(i, i, i);            }            bmp.Palette = tempPalette;            return bmp;        }        #endregion        public static byte[] BitmapToGrayByte(Bitmap bitmap)        {            // 申请目标位图的变量,并将其内存区域锁定            BitmapData bitmapDat = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat);            // 获取bmpData的内存起始位置            IntPtr intPtr = bitmapDat.Scan0;            byte[] image = new byte[bitmap.Width * bitmap.Height];//原始数据            Marshal.Copy(intPtr, image, 0, bitmap.Width * bitmap.Height); // 将数据复制到byte数组中,            //解锁内存区域              bitmap.UnlockBits(bitmapDat);            return image;        }        //获取测量的BSE图             public bool GetBSEImage(COTSField tempFld, COTSImageProcParam ImgProcPrm, double pixelSize, int iWidth, int iHeight, ref byte[] BSEImageNoBG)        {            Rectangle rect = new Rectangle();            rect.Height = iHeight;            rect.Width = iWidth;                       CBSEImgClr pBSEImageOut = new CBSEImgClr(rect);                                          if (null == ImgProcPrm)            {                return false;            }            RemoveBackGround(tempFld, ImgProcPrm, pixelSize ,ref pBSEImageOut);            BSEImageNoBG = pBSEImageOut.GetImageDataPtr();            return true;        }               /// <summary>        /// 获取测量的BSE图        /// </summary>        /// <param name="BSEImage">BSE原数据</param>        /// <param name="iHeight">图像高度</param>        /// <param name="iWidth">图像宽度</param>        /// <param name="grayStart"></param>        /// <param name="grayEnd"></param>        /// <param name="BSEImageNoBG">去背景图数据</param>        /// <returns></returns>        public bool GetSpecificGreyRangeBSEImage(byte[] BSEImage, int iWidth, int iHeight, int grayStart, int grayEnd, ref byte[] BSEImageNoBG)        {            Rectangle rect = new Rectangle();            rect.Height = iHeight;            rect.Width = iWidth;            CBSEImgClr pBSEImageIn = new CBSEImgClr(rect);            CBSEImgClr pBSEImageOut = new CBSEImgClr(rect);                                  pBSEImageIn.SetImageData(BSEImage, iWidth, iHeight );                     CIntRangeClr cIntRangeClr = new CIntRangeClr();            cIntRangeClr.SetStart(grayStart);            cIntRangeClr.SetEnd(grayEnd);            //ImageProForClr imgpro = new ImageProForClr();            int num=0;            imgProEngine.GetSpecialGrayRangeImage(pBSEImageIn, cIntRangeClr, pBSEImageOut,ref num);            for (int i = 0; i < iWidth; i++)            {                for (int j = 0; j < iHeight; j++)                {                    var bse = pBSEImageOut.GetBSEValue(i, j);                    if (bse == 255)                    {                        var originalBse = pBSEImageIn.GetBSEValue(i, j);                        pBSEImageOut.SetBSEValue(i, j, originalBse);                    }                    else                     {                        pBSEImageOut.SetBSEValue(i, j, 255);                    }                                                  }                        }                        BSEImageNoBG = pBSEImageOut.GetImageDataPtr();            return true;        }        public bool GetColoredImage(COTSField tempFld, COTSImageProcParam ImgProcPrm, double pixelSize,  int iWidth, int iHeight, ref CBSEImgClr a_pImgOut, ref Bitmap BSEImageNoBG)        {                     if (null == ImgProcPrm)            {                return false;            }            RemoveBGAndGetColoredParts(tempFld, ImgProcPrm, pixelSize, ref a_pImgOut, ref BSEImageNoBG);//RemoveBGAndGetColoredParts            return true;        }        // remove background        private void RemoveBackGround(COTSField tempFld,  COTSImageProcParam a_pImgProcessParam, double a_pixelSize, ref CBSEImgClr a_pImgOut)        {                   List<COTSParticleClr> parts = new List<COTSParticleClr>();            List<COTSParticleClr> specialGreyparts = new List<COTSParticleClr>();            var ecdrange = a_pImgProcessParam.GetIncAreaRange();            var originalBse = tempFld.GetBSEImage();                       if (!RemoveBGAndGetParts(tempFld, a_pImgProcessParam, ref parts))            {                return;            }            tempFld.CalParticleImageProp(parts);            tempFld.SelectParticlesAccordingImgProp(a_pImgProcessParam);            parts = tempFld.GetListAnalysisParticles();            if (a_pImgProcessParam.GetSpecialGreyRangeParam().GetIsToRun())            {                var param = a_pImgProcessParam.GetSpecialGreyRangeParam();                var ranges = param.GetSpecialGreyRanges();                                               foreach (var r in ranges)                {                    CIntRangeClr r1 = new CIntRangeClr();                    r1.SetStart(r.range.GetStart());                    r1.SetEnd(r.range.GetEnd());                    CDoubleRangeClr r2 = new CDoubleRangeClr();                    r2.SetStart(r.diameterRange.GetStart());                    r2.SetEnd(r.diameterRange.GetEnd());                    GetParticlesBySpecialGray(originalBse, r1, r2, a_pixelSize, ref specialGreyparts);                }                          }            for (int i = 0; i < a_pImgOut.GetWidth(); i++)            {                for (int j = 0; j < a_pImgOut.GetHeight(); j++)                {                    a_pImgOut.SetBSEValue(i, j, 255);                }            }            if (specialGreyparts.Count > 0)            {                foreach (var p in specialGreyparts)                {                    foreach (var s in p.GetFeature().GetSegmentsList())                    {                        for (int i = s.GetStart(); i < s.GetStart() + s.GetLength(); i++)                        {                            var bseValue = originalBse.GetBSEValue(i, s.GetHeight());                            a_pImgOut.SetBSEValue(i, s.GetHeight(), bseValue);                        }                    }                }            }            foreach (var p in parts)            {                              foreach (var s in p.GetFeature().GetSegmentsList())                {                                       for (int i = s.GetStart(); i < s.GetStart() + s.GetLength(); i++)                    {                        var bseValue = originalBse.GetBSEValue(i, s.GetHeight());                        a_pImgOut.SetBSEValue(i, s.GetHeight(), bseValue);                    }                }            }                                           return;        }        private void RemoveBGAndGetColoredParts(COTSField tempFld, COTSImageProcParam a_pImgProcessParam, double a_pixelSize, ref CBSEImgClr a_pImgOut, ref Bitmap a_pBmpOut)        {            List<COTSParticleClr> parts = new List<COTSParticleClr>();            List<COTSParticleClr> specialGreyparts = new List<COTSParticleClr>();            var ecdrange = a_pImgProcessParam.GetIncAreaRange();                      if (!RemoveBGAndGetParts(tempFld, a_pImgProcessParam,  ref parts))            {                return;            }            tempFld.CalParticleImageProp(parts);            tempFld.SelectParticlesAccordingImgProp(a_pImgProcessParam);            parts = tempFld.GetListAnalysisParticles();            var a_pImgIn = tempFld.GetBSEImage();            Random c = new Random();                       for (int i = 0; i < a_pBmpOut.Width; i++)            {                for (int j = 0; j < a_pBmpOut.Height; j++)                {                    a_pBmpOut.SetPixel(i, j, Color.White);                }                           }                        foreach (var p in parts)            {                Color cValue = GetRandomColor30(c);                //Color cValue = p.GetTypeColor();                foreach (var s in p.GetFeature().GetSegmentsList())                    {                        for (int i = s.GetStart(); i < s.GetStart() + s.GetLength(); i++)                        {                        var y = s.GetHeight();                        a_pBmpOut.SetPixel(i, y, cValue);                        }                    }            }            if (a_pImgProcessParam.GetSpecialGreyRangeParam().GetIsToRun())            {                var param = a_pImgProcessParam.GetSpecialGreyRangeParam();                var ranges = param.GetSpecialGreyRanges();                foreach (var r in ranges)                {                    CIntRangeClr r1 = new CIntRangeClr();                    r1.SetStart(r.range.GetStart());                    r1.SetEnd(r.range.GetEnd());                    CDoubleRangeClr r2 = new CDoubleRangeClr();                    r2.SetStart(r.diameterRange.GetStart());                    r2.SetEnd(r.diameterRange.GetEnd());                    GetParticlesBySpecialGray(tempFld.GetBSEImage(), r1, r2, a_pixelSize, ref specialGreyparts);                }                if (specialGreyparts.Count > 0)                {                    foreach (var p in specialGreyparts)                    {                        Color cValue = GetRandomColor30(c);                        foreach (var s in p.GetFeature().GetSegmentsList())                        {                            for (int i = s.GetStart(); i < s.GetStart() + s.GetLength(); i++)                            {                                var bseValue = a_pImgIn.GetBSEValue(i, s.GetHeight());                                a_pBmpOut.SetPixel(i, s.GetHeight(), cValue);                            }                        }                    }                    tempFld.CalParticleImageProp(specialGreyparts);                    parts.AddRange(specialGreyparts);                    tempFld.SetListAnalysisParticles(parts);                    //tempFld.SelectParticlesAccordingImgProp(a_pImgProcessParam);                                                          }                            }                       Graphics graphics = Graphics.FromImage(a_pBmpOut);            // 绘制一个红色矩形            Pen pen = new Pen(Color.Red, 1);            var overlap=a_pImgProcessParam.GetOverlapParam();            if (overlap > 0)            {                int overlapPixels = (int)(overlap / a_pixelSize);                graphics.DrawRectangle(pen, overlapPixels, overlapPixels, a_pBmpOut.Width - 2 * overlapPixels, a_pBmpOut.Height - 2 * overlapPixels);            }            return;        }        public void GetImageWithBlackColoredParts(List<COTSParticleClr> analysitParts,COTSImageProcParam a_pImgProcessParam,double a_pixelSize, ref Bitmap a_pBmpOut)        {                      for (int i = 0; i < a_pBmpOut.Width; i++)            {                for (int j = 0; j < a_pBmpOut.Height; j++)                {                    a_pBmpOut.SetPixel(i, j, Color.White);                }            }            Random c = new Random();            foreach (var p in analysitParts)            {                Color cValue = GetRandomColor30(c);                foreach (var s in p.GetFeature().GetSegmentsList())                {                    for (int i = s.GetStart(); i < s.GetStart() + s.GetLength(); i++)                    {                        a_pBmpOut.SetPixel(i, s.GetHeight(), cValue);                    }                }            }            Graphics graphics = Graphics.FromImage(a_pBmpOut);            // 绘制一个红色矩形            Pen pen = new Pen(Color.Red, 1);            var overlap = a_pImgProcessParam.GetOverlapParam();            if (overlap > 0)            {                int overlapPixels = (int)(overlap / a_pixelSize);                graphics.DrawRectangle(pen, overlapPixels, overlapPixels, a_pBmpOut.Width - 2 * overlapPixels, a_pBmpOut.Height - 2 * overlapPixels);            }            return;        }        public void GetImageWithSTDColoredParts(List<COTSParticleClr> analysitParts, COTSImageProcParam a_pImgProcessParam, double a_pixelSize, ref Bitmap a_pBmpOut)        {            for (int i = 0; i < a_pBmpOut.Width; i++)            {                for (int j = 0; j < a_pBmpOut.Height; j++)                {                    a_pBmpOut.SetPixel(i, j, Color.White);                }            }            //Random c = new Random();            foreach (var p in analysitParts)            {                Color cValue = ColorTranslator.FromHtml(p.GetTypeColor()) ;                foreach (var s in p.GetFeature().GetSegmentsList())                {                    for (int i = s.GetStart(); i < s.GetStart() + s.GetLength(); i++)                    {                        a_pBmpOut.SetPixel(i, s.GetHeight(), cValue);                    }                }            }            Graphics graphics = Graphics.FromImage(a_pBmpOut);            // 绘制一个红色矩形            Pen pen = new Pen(Color.Red, 1);            var overlap = a_pImgProcessParam.GetOverlapParam();            if (overlap > 0)            {                int overlapPixels = (int)(overlap / a_pixelSize);                graphics.DrawRectangle(pen, overlapPixels, overlapPixels, a_pBmpOut.Width - 2 * overlapPixels, a_pBmpOut.Height - 2 * overlapPixels);            }            return;        }        public Color GetRandomColor30(Random r)        {                       int n = r.Next(0, 31);            Color ret_color;            switch (n)            {                case 1:                    ret_color = Color.Aqua;                    break;                case 2:                    ret_color = Color.Black;                    break;                case 3:                    ret_color = Color.Blue;                    break;                case 4:                    ret_color = Color.BlueViolet;                    break;                case 5:                    ret_color = Color.Brown;                    break;                case 6:                    ret_color = Color.BurlyWood;                    break;                case 7:                    ret_color = Color.CadetBlue;                    break;                case 8:                    ret_color = Color.CadetBlue;                    break;                case 9:                    ret_color = Color.CornflowerBlue;                    break;                case 10:                    ret_color = Color.DarkBlue;                    break;                case 11:                    ret_color = Color.Gray;                    break;                case 12:                    ret_color = Color.Indigo;                    break;                case 13:                    ret_color = Color.LightSlateGray;                    break;                case 14:                    ret_color = Color.Magenta;                    break;                case 15:                    ret_color = Color.Maroon;                    break;                case 16:                    ret_color = Color.MediumBlue;                    break;                case 17:                    ret_color = Color.MediumOrchid;                    break;                case 18:                    ret_color = Color.MidnightBlue;                    break;                case 19:                    ret_color = Color.Navy;                    break;                case 20:                    ret_color = Color.Olive;                    break;                case 21:                    ret_color = Color.PaleVioletRed;                    break;                case 22:                    ret_color = Color.Peru;                    break;                case 23:                    ret_color = Color.Purple;                    break;                case 24:                    ret_color = Color.Red;                    break;                case 25:                    ret_color = Color.RosyBrown;                    break;                case 26:                    ret_color = Color.RoyalBlue;                    break;                case 27:                    ret_color = Color.SaddleBrown;                    break;                case 28:                    ret_color = Color.SeaGreen;                    break;                case 29:                    ret_color = Color.Teal;                    break;                case 30:                    ret_color = Color.Tomato;                    break;                case 31:                    ret_color = Color.YellowGreen;                    break;                default:                    ret_color = Color.Black;                    break;            }            return ret_color;        }              public bool CalParticleImageProp( COTSParticleClr part, double a_pixelSize)        {                       imgProEngine.CalcuParticleImagePropertes(part,a_pixelSize);                        return true;        }              public bool RemoveBGAndGetParts(COTSField currentField, COTSImageProcParam a_pImgProcessParam,ref List<COTSParticleClr> parts)        {           var a_pixelSize = currentField.GetPixelSize();            COTSImgProcPrmClr prm = GetImageProcPrmClr(a_pImgProcessParam);            COTSFieldDataClr flddataclr = new COTSFieldDataClr();            PointF fldpos = currentField.GetOTSPosition();            flddataclr.SetPosition((int)fldpos.X, (int)fldpos.Y);            flddataclr.SetImageWidth(currentField.ImgWidth);            flddataclr.SetImageHeight(currentField.ImgHeight);            double left = fldpos.X - currentField.ImgWidth * a_pixelSize / 2;            double top = fldpos.Y + currentField.ImgHeight * a_pixelSize / 2;            double right = fldpos.X + currentField.ImgWidth * a_pixelSize / 2;            double bottom = fldpos.Y - currentField.ImgHeight * a_pixelSize / 2;            flddataclr.SetOTSRect(left, top, right, bottom);                      if (!imgProEngine.GetFieldDataFromImage(currentField.GetBSEImage(), prm, a_pixelSize, flddataclr))            {                return false;            }            List<COTSParticleClr> originalParts = flddataclr.GetParticleList();                       if(a_pImgProcessParam.GetBGRemoveType() == OTS_BGREMOVE_TYPE.WaterShed)            {                foreach(var p in originalParts)                {                    if (p.GetSubParticles().Count > 0)                    {                        parts.AddRange(p.GetSubParticles());                    }                    else                    {                        parts.Add(p);                    }                                  }                currentField.SetListAnalysisParticles(parts);            }            else            {                parts = originalParts;            }            currentField.SetListAnalysisParticles(parts);                                return true;        }        public bool GetParticlesBySpecialGray(CBSEImgClr img, CIntRangeClr grayrange, CDoubleRangeClr diameterRange,double a_pixelSize, ref List<COTSParticleClr> parts)        {                      COTSFieldDataClr flddataclr = new COTSFieldDataClr();            imgProEngine.GetParticlesBySpecialPartGrayRange(img, grayrange,diameterRange,a_pixelSize, flddataclr);            parts = flddataclr.GetParticleList();            return true;        }        private COTSImgProcPrmClr GetImageProcPrmClr(COTSImageProcParam a_oSource)        {            COTSImgProcPrmClr prmclr = new COTSImgProcPrmClr();            CDoubleRangeClr r1 = new CDoubleRangeClr(a_oSource.GetIncAreaRange().GetStart(), a_oSource.GetIncAreaRange().GetEnd());            prmclr.SetIncArea(r1);            CIntRangeClr r2 = new CIntRangeClr(a_oSource.GetBGGray().GetStart(), a_oSource.GetBGGray().GetEnd());            prmclr.SetBGGray(r2);            CIntRangeClr r3 = new CIntRangeClr(a_oSource.GetParticleGray().GetStart(), a_oSource.GetParticleGray().GetEnd());            prmclr.SetParticleGray(r3);            prmclr.SetBGRemoveType((int)a_oSource.GetBGRemoveType());            prmclr.SetAutoBGRemoveType((int)a_oSource.GetAutoBGRemoveType());                      prmclr.SetOverlapParam(a_oSource.GetOverlapParam());            prmclr.SetMatrixStep(a_oSource.MatrixStep);                        return prmclr;        }        public  bool CalculateBrightnessDarkGrayByOtsu(CBSEImgClr bseimg, ref int bright, ref int dark)        {            if (bseimg == null || bseimg.GetImageDataPtr() == null)            {                bright = 0;                dark = 0;                return false;            }                             return imgProEngine.CalcuBrightPhaseDarkPhaseGrayByOtsu(bseimg, ref bright, ref dark);        }           public bool MergeBigBoundaryParticles(List<COTSField> allFields, double pixelSize, int scanFieldSize, System.Drawing.Size ResolutionSize, ref List<COTSParticleClr> mergedParts)        {            List<COTSFieldDataClr> fldclrs = new List<COTSFieldDataClr>();            foreach (var f in allFields)            {                COTSFieldDataClr fldclr = new COTSFieldDataClr();                PointF p1 = f.GetOTSPosition();                System.Drawing.Point p2 = new System.Drawing.Point((int)p1.X, (int)p1.Y);                fldclr.SetPosition((int)p1.X,(int)p1.Y);                fldclr.SetImageWidth(f.ImgWidth);                fldclr.SetImageHeight(f.ImgHeight);                var parts = f.GetListAnalysisParticles();                foreach (var p in parts)                {                    fldclr.AddParticle(p);                }                fldclrs.Add(fldclr);            }                       imgProEngine.MergeBigBoundaryParticles(fldclrs, pixelSize, scanFieldSize, ResolutionSize, mergedParts);            return true;        }               /// <summary>        /// 根据Segment寻找边缘坐标点        /// </summary>        /// <param name="width"></param>        /// <param name="height"></param>        /// <param name="segmentClrs"></param>        /// <returns></returns>        public static List<System.Drawing.Point> FindContoursBySegment(int width, int height, List<COTSSegmentClr> segmentClrs)        {            List<System.Drawing.Point> points = new List<System.Drawing.Point>();             using (Mat mat = new Mat(height, width, MatType.CV_8UC1, new Scalar(0)))            {                for (int i = 0; i < segmentClrs.Count; i++)                {                    Cv2.Line(mat, new OpenCvSharp.Point(segmentClrs[i].GetStart(), segmentClrs[i].GetHeight()), new OpenCvSharp.Point(segmentClrs[i].GetStart() + segmentClrs[i].GetLength(), segmentClrs[i].GetHeight()), Scalar.White, 1, LineTypes.AntiAlias);                }                OpenCvSharp.Point[][] contours;                HierarchyIndex[] hierarchy;                Cv2.FindContours(mat, out contours, out hierarchy, RetrievalModes.External, ContourApproximationModes.ApproxSimple, null);                for (int i = 0; i < contours.ToList().Count(); i++)                {                    for (int j = 0; j < contours[i].Count(); j++)                    {                        System.Drawing.Point point = new System.Drawing.Point(contours[i][j].X, contours[i][j].Y);                        if (!points.Contains(point))                        {                            points.Add(point);                        }                    }                }            }            return points;        }           }}
 |