| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256 | using System;using System.Collections.Generic;using System.Drawing;using System.Linq;using System.Runtime.InteropServices;using System.Text;using System.Threading.Tasks;using OpenCvSharp;using Point = System.Drawing.Point;using Size = OpenCvSharp.Size;using ZhaoKThinAndConnectionDLL;namespace PaintDotNet.DedicatedAnalysis.GrainSizeStandard.IntegrationClass{    internal class InParameter    {        public Mat MGryImg;        public Mat MHesOutImage;        public Mat MValley;        public int iDimA;        public int iDimB;    }    public class NewSeg    {        private Mat m_MOrgImg;        private Mat m_MOutImg;        private double[] m_adOutParam;        private InParameter m_InParam;        public int DoSeg(Mat _MOrgImg, Mat _MOutImg, double[] _adOutParam, Vec4b value)        {            PrepareParameter();            m_MOrgImg = _MOrgImg;            m_MOutImg = _MOutImg;            m_adOutParam = _adOutParam;            if (3 == m_MOrgImg.Channels())            {                Cv2.CvtColor(m_MOrgImg, m_InParam.MGryImg, ColorConversionCodes.RGB2GRAY);            }            else            {                if (1 != m_MOrgImg.Channels())                {                    return -1;                }                m_InParam.MGryImg = m_MOrgImg.Clone();            }            ImgHessian();            FindValley();            FindShed(value);            return 1;        }        private int FindShed(Vec4b value)        {            Mat mat = new Mat(m_InParam.MValley.Size(), 4);            Cv2.FindContours(m_InParam.MValley, out OpenCvSharp.Point[][] contours, out HierarchyIndex[] hierarchy, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple);            for (int i = 0; i < hierarchy.Length; i++)            {                Cv2.DrawContours(mat, contours, i, Scalar.All(i + 1), 1, LineTypes.Link8, hierarchy);            }            Cv2.Watershed(m_MOrgImg, mat);            int rows = mat.Rows;            int cols = mat.Cols;            int[] array = new int[2];            //Vec3b value = new Vec3b(0, 0, byte.MaxValue);            array[0] = 0;            while (array[0] < rows)            {                array[1] = 0;                while (array[1] < cols)                {                    if (0 >= mat.At<int>(array[0], array[1]))                    {                        m_MOutImg.Set(array, value);                    }                    array[1]++;                }                array[0]++;            }            return 1;        }        private int FindValley()        {            Mat structuringElement = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(m_InParam.iDimA, m_InParam.iDimA), new OpenCvSharp.Point(-1, -1));            Cv2.MorphologyEx(m_InParam.MHesOutImage, m_InParam.MHesOutImage, MorphTypes.Close, (InputArray)structuringElement);            Cv2.BitwiseNot(m_InParam.MHesOutImage, m_InParam.MValley);            Size size = m_InParam.MValley.Size();            Mat mat = (Mat)Mat.Zeros(size.Height + 2, size.Width + 2, m_InParam.MValley.Type());            m_InParam.MValley.CopyTo(mat.SubMat(new Range(1, size.Height + 1), new Range(1, size.Width + 1)));            Cv2.FloodFill(mat, new OpenCvSharp.Point(0, 0), new Scalar(255.0));            Mat mat2 = new Mat();            mat.SubMat(new Range(1, size.Height + 1), new Range(1, size.Width + 1)).CopyTo(mat2);            Cv2.BitwiseNot(mat2, mat2);            m_InParam.MValley = (Mat)(m_InParam.MValley | mat2);            return 1;        }        private int PrepareParameter()        {            m_InParam = new InParameter();            m_InParam.MGryImg = new Mat();            m_InParam.MHesOutImage = new Mat();            m_InParam.MValley = new Mat();            m_InParam.iDimA = 3;            m_InParam.iDimB = 1;            return 1;        }        private int ImgHessian()        {            Mat mat = new Mat();            m_InParam.MGryImg.ConvertTo(mat, 5);            int rows = mat.Rows;            int cols = mat.Cols;            int num = 5;            double num2 = 1.2;            Mat mat2 = new Mat(2 * num + 1, 2 * num + 1, MatType.CV_32FC1, Scalar.All(0.0));            Mat mat3 = new Mat(2 * num + 1, 2 * num + 1, MatType.CV_32FC1, Scalar.All(0.0));            Mat mat4 = new Mat(2 * num + 1, 2 * num + 1, MatType.CV_32FC1, Scalar.All(0.0));            for (int i = -num; i <= num; i++)            {                for (int j = -num; j <= num; j++)                {                    double num3 = 1.0 - (double)(i * i) / (num2 * num2);                    double num4 = Math.Exp((double)(-1 * (i * i + j * j)) / (2.0 * num2 * num2));                    double num5 = -1.0 / (Math.PI * 2.0 * Math.Pow(num2, 4.0));                    double num6 = num3 * num4 * num5;                    float value = (float)num6;                    mat2.Set(i + num, j + num, value);                    mat4.Set(i + num, j + num, (float)((1.0 - (double)(j * j) / (num2 * num2)) * Math.Exp((double)(-1 * (i * i + j * j)) / (2.0 * num2 * num2)) * (-1.0 / (Math.PI * 2.0 * Math.Pow(num2, 4.0)))));                    mat3.Set(i + num, j + num, (float)((double)(i * j) * Math.Exp((double)(-1 * (i * i + j * j)) / (2.0 * num2 * num2)) * (1.0 / (Math.PI * 2.0 * Math.Pow(num2, 6.0)))));                }            }            Mat mat5 = new Mat(rows, cols, MatType.CV_32FC1, Scalar.All(0.0));            Mat mat6 = new Mat(rows, cols, MatType.CV_32FC1, Scalar.All(0.0));            Mat mat7 = new Mat(rows, cols, MatType.CV_32FC1, Scalar.All(0.0));            Cv2.Filter2D(mat, mat5, mat5.Depth(), mat2);            Cv2.Filter2D(mat, mat6, mat6.Depth(), mat4);            Cv2.Filter2D(mat, mat7, mat7.Depth(), mat3);            byte[,] array = new byte[rows, cols];            float[] array2 = new float[rows * cols];            float[] array3 = new float[rows * cols];            float[] array4 = new float[rows * cols];            Marshal.Copy(mat5.Data, array2, 0, rows * cols);            Marshal.Copy(mat6.Data, array3, 0, rows * cols);            Marshal.Copy(mat7.Data, array4, 0, rows * cols);            for (int k = 0; k < rows; k++)            {                for (int l = 0; l < cols; l++)                {                    float num7 = array2[k * cols + l];                    float num8 = array3[k * cols + l];                    float num9 = array4[k * cols + l];                    double num10 = (num7 + num8) * (num7 + num8) - 4f * (num7 * num8 - num9 * num9);                    if (!(num10 < 0.0))                    {                        num10 = Math.Sqrt(num10);                        double num11 = ((double)(num7 + num8) + num10) / 2.0;                        double value2 = ((double)(num7 + num8) - num10) / 2.0;                        if (num11 > 0.0 && Math.Abs(num11) > 1.0 + Math.Abs(value2))                        {                            array[k, l] = byte.MaxValue;                        }                    }                }            }            m_InParam.MHesOutImage = new Mat(rows, cols, MatType.CV_8UC1, array, 0L);            return 0;        }    }    /////    /////    class OUTsegmsurf    {        public Mat cellbw;        public Mat wat;        public Mat imsegm;        public Mat minima;        public Mat minimacell;        //kkkkk public NEW_TYPE_SegInf info;    }    class In5segmsurf    {        public string smoothim_method;        public int filterridges;        public double gaussian_stdev;        public string LEVEL;        public double classifycells_convexarea;        public double classifycells_convexperim;        public Mat OrgImg;        public In5segmsurf Clone()        {            return this.MemberwiseClone() as In5segmsurf;        }    }    class In6segmsurf    {        public string prmfile;//Path to parameter file        public Mat minima;//All markers, for instance from manual drawings        public Mat minimacell;//; for cells, for instance from manual drawings        public Mat imnucl;//Nucleus image for defining markers    }    class PMergefragments//区域合并    {        public int optlog;        public int optint;        public double intint;        public double conv;        public PMergefragments Clone()        {            return this.MemberwiseClone() as PMergefragments;        }    }    class PSmoothim//平滑    {        public string method;        public double[] h;        public int gpu;        public int dim;        public int ced_maxniter;        public PSmoothim Clone()        {            return this.MemberwiseClone() as PSmoothim;        }    }    class PClassifycells//区域分类    {        public double convexarea;        public double convexperim;        public double[] h;        public double minvolfull;        public double maxvolfull;        public string method;        public PClassifycells Clone()        {            return this.MemberwiseClone() as PClassifycells;        }    }    class In4smoothim    {        public int filterridges;        public string LEVEL;        public double gaussian_stdev;        public double[] getminima_h;        public double getminima_minvolfull;        public double getminima_maxvolfull;        public double getminima_level;        //public string getminima_method;        public PMergefragments mergefragments;        public PSmoothim smoothim;        public PClassifycells classifycells;        public int[] dim;        public double minvol;        public double minvolvox;        public double maxvol;        public double maxvolvox;        public double watminvolfull;        public double watmaxvolfull;        public double minvolfull;        public double maxvolfull;        public double[] h;        public double just;        public int gpu;        public int illum;        public double illumdiameter;        public int merge;        public int iInterpolationMethod;//zzzzz new, 1 for Cubic spline interpolation, 2 for Bilinear interpolation, 3 for Nearest neighbor interpolation    }    class OUTgetminima    {        public Mat minimacell;        public Mat minima;    }    class OUTclassifycells    {        public Mat cellbw;        public PClassifycells classifycells;    }    class OUTmaxfilt3    {        public List<float>[,] maxim;        public float[,] sumim;        public int numpoints;        public float[][][] minim;    }    class MyFilter    {        public double[] x;        public double[] y;        public double[] z;    }    class OLDcellsegm    {        public const double m_PI = 3.1415926535897931;        void mf_mergeinputpar(In4smoothim prm, In5segmsurf prmin)        {            prm.smoothim.method = prmin.smoothim_method;            prm.filterridges = prmin.filterridges;            prm.gaussian_stdev = prmin.gaussian_stdev;            prm.LEVEL = (string)prmin.LEVEL.Clone();            prm.classifycells.convexarea = prmin.classifycells_convexarea;            prm.classifycells.convexperim = prmin.classifycells_convexperim;        }        void mf_cellsize(double minvol, double maxvol, In4smoothim prm, int ThreeDimNO)        {            if (0 == prm.h[0] * prm.h[1] * prm.h[2])            {                Console.WriteLine("There is zero voxel size");            }            double minr = Math.Pow((3 * minvol) / (4 * m_PI), 1 / 3);            //maxr = ((3*maxvol)/(4*pi))^(1/3);            //maxz = maxr/h(3);            double minz = minr / prm.h[2];            if (ThreeDimNO < minz)            {                //shrinink a sphere to a circle                double r = Math.Pow((3 * maxvol) / (4 * m_PI), 1 / 3);                maxvol = Math.Pow(ThreeDimNO, prm.just) * m_PI * r * r;                r = Math.Pow((3 * minvol) / (4 * m_PI), 1 / 3);                minvol = Math.Pow(ThreeDimNO, prm.just) * m_PI * r * r;            }            double voxelvol = prm.h[0] * prm.h[1] * prm.h[2];            double minvolvox = Math.Round(minvol / voxelvol, MidpointRounding.AwayFromZero);            double maxvolvox = Math.Round(maxvol / voxelvol, MidpointRounding.AwayFromZero);            prm.minvol = minvol;            prm.minvolvox = minvolvox;            prm.maxvol = maxvol;            prm.maxvolvox = maxvolvox;        }        public OUTsegmsurf mf_segmsurf_progress_auto(Mat GryImg, double minvol, double maxvol,            string[] INnamehere, In5segmsurf IN5varhere, In6segmsurf IN6varhere, Color phaseColor)        {            long start = Cv2.GetTickCount();            OUTsegmsurf rtn = new OUTsegmsurf();            //ttttt Cv2.FindContours(watermark, out contour, out hier, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, null);            rtn.wat = new Mat(GryImg.Size(), MatType.CV_8UC4, new Scalar(255, 0, 0, 0));            //Mat OutImg = new Mat(GryImg.Rows, GryImg.Cols, MatType.CV_8UC3, Scalar.All(0));            NewSeg NSeg = new NewSeg();            //转为为灰度?            if (/*3 == GryImg.Channels() || */4 == GryImg.Channels())            {                Cv2.CvtColor(GryImg, GryImg, ColorConversionCodes.BGRA2BGR);            }            else if (1 == GryImg.Channels())            {                Cv2.CvtColor(GryImg, GryImg, ColorConversionCodes.GRAY2BGR);            }            //Cv2.ImShow("oriImg", GryImg);            //Cv2.WaitKey();            double time_v2 = (Cv2.GetTickCount() - start) / Cv2.GetTickFrequency();            System.Console.WriteLine("晶界重现_V2_执行时间1:" + time_v2);            NSeg.DoSeg(GryImg.Clone()/*OrgImg*/, rtn.wat, null, new Vec4b(phaseColor.B, phaseColor.G, phaseColor.R, 255));            ////ttttt Cv2.DrawContours(rtn.wat, contour, -1, Scalar.Red);            //int Rows = OutImg.Rows;            //int Cols = OutImg/*watermark*/.Cols;            //int[] point = new int[2];            //Vec4b redcol;            //if (phaseColor != null)            //{            //    redcol = new Vec4b(phaseColor.B, phaseColor.G, phaseColor.R, 255);            //}            //else            //    redcol = new Vec4b(0, 0, 255/*255*/, 255);            //for (point[0] = 0; point[0] < Rows; point[0]++)            //{            //    for (point[1] = 0; point[1] < Cols; point[1]++)            //    {            //        if (0 >= watermark.At<int>(point[0], point[1]))            //        {            //            rtn.wat.Set<Vec4b>(point[0], point[1], redcol);//###            //        }            //    }            //}            time_v2 = (Cv2.GetTickCount() - start) / Cv2.GetTickFrequency();            System.Console.WriteLine("晶界重现_V2_执行时间2:" + time_v2);            ////Cv2.ImShow("contour", rtn.wat);//kkkkk            ////Cv2.WaitKey(0);//kkkkk            //control.Cursor = cursor;// System.Windows.Forms.Cursors.Default;            return rtn;            //System.Windows.Forms.Cursor cursor = control.Cursor;//.GetHashCode();//.CopyHandle();            //control.Cursor = System.Windows.Forms.Cursors.WaitCursor;            string mfilename = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;            Console.WriteLine("This is" + mfilename + "for segmentation of cells");            //image for segmentation            Mat imsegm = GryImg.Clone();            //cell volumes in cubic microns            double minvolfull = 1000 * minvol;            double maxvolfull = 1000 * maxvol;            Mat imsegmini = imsegm.Clone();            Mat minimacell = null;            Mat minima = null;            Mat imnucl = null;            string prmfile = null;            /*            //for visualilzation             int vis = 0;            int visfinal = 0;            */            In4smoothim prm = new In4smoothim();            prm.mergefragments = new PMergefragments();            prm.smoothim = new PSmoothim();            prm.classifycells = new PClassifycells();            /*Standard parameters*/            //voxel size            prm.h = new double[3] { 0.5, 0.5, 1.5 };            //adjust for not fully circular shape of 3D cells            prm.just = 0.9;            //filter ridges            prm.filterridges = 0;            //GPU, requires            prm.gpu = 0;            //correct illumination            prm.illum = 0;            prm.illumdiameter = 25;            /*Minima parameters*/            //level            prm.getminima_level = 0.30;            /*            //method            prm.getminima_method = "automated";            */            /*Smoothing parameters*/            //directional coherence enhancing diffusion            prm.smoothim.method = "dirced";            //2D or 3D smoothing            prm.smoothim.dim = 2;            //number of iterations of smoothing in CED            prm.smoothim.ced_maxniter = 100;            //dimension image            int[] dim = new int[3] { imsegm.Rows, imsegm.Cols, 1 };            /*Classification parameters*/            prm.classifycells.method = "threshold";            /*Watershed parameters*/            //To test intensity of wat lines; merging            prm.merge = 0;            //methods for merging            prm.mergefragments.optlog = 2;            prm.mergefragments.optint = 2;            /* The signicance of watershed lines, stronger if larger, done on ridgeim!!            if the raw image, then use much smaller, around 1            set to 1.05-1.10            prm.watthint = 1.06;*/            prm.mergefragments.intint = 1.3;            /* The conexity measure for the merging, we should not allow a very much            smaller convexity after merging            thconv = 1 if no change in convexity            thconv > 1 if increase in convexity            thconv < 1 if decrease in convexity */            prm.mergefragments.conv = 1.0;            if (maxvolfull < minvolfull)            {                Console.WriteLine(mfilename + ": The upper cell volume is lower than the lower, check the input");            }            /* 无用matlab代码                   % read from parameter file?            for i = 4 : 2 : nargin                namehere = varargin{4};                varhere = varargin{5};                switch(namehere)                    case('prmfile')                        prmfile = varhere;                                otherwise                        % nothing                end;            end;            %            % Load the parameter file if one is given            %            if ~isempty(prmfile)                isfolder = ~isempty(strfind(prmfile,'/'));                [a b c] = fileparts(prmfile);                if isfolder                            A = pwd;                    cd(a);                        end;                    msg = sprintf('Reading from parameter file %s',prmfile);                disp(msg);                cmd = [b c];                prmin = eval(cmd);                    if isfolder                    cd(A);                end;                % merge the structs by overriding the existing values                prm = mergestruct(prm,prmin);            end;            */            /*The command line has the highest priority, merge the variables here*/            In5segmsurf prmin = null;            for (int i = 0; i < INnamehere.GetLength(0); i++)            {                //this variable                string namehere = INnamehere[i];                switch (namehere)                {                    case "minima":                        minima = IN6varhere.minima;                        break;                    case "prm":                        prmin = IN5varhere.Clone();                        mf_mergeinputpar(prm, prmin);                        break;                    case "minimacell":                        minimacell = IN6varhere.minimacell;                        break;                    case "imnucleus":                        imnucl = IN6varhere.imnucl;                        break;                    default:                        Console.WriteLine("Wrong option " + namehere);                        break;                }            }            prm.dim = new int[2] { imsegm.Rows, imsegm.Cols };            /*  无用matlab代码            % if you give in a nucleus image you want to use it!            if ~isempty(imnucl)                prm.getminima.method = 'nucleus';                prm.classifycells.method = 'minimacell';            end;            % test for credibility!            if isequal(prm.getminima.method,'manual')                if isempty(minima) && isempty(minimacell)                    error('You must specify either minima eller minimacell')                end;            end;            if isequal(prm.getminima.method,'nucleus')                if isempty(imnucl)                    error('You must specify a nucleus image');                end;            end;            */            /*Computed settings*/            //get the ADJUSTED 3D cell size, in case its not a full 3D volume.             //NB: This is not always linearly scalable, try to avoid using reduced 3D.            mf_cellsize(minvolfull, maxvolfull, prm, dim[2]);            //give the voxel sizes in thousand, since all programs are tuned for this            //prm.classifycells.minvolfull = prm.classifycells.minvolfull;            //prm.classifycells.maxvolfull = prm.classifycells.maxvolfull;            prm.getminima_minvolfull = minvolfull / 1000;            prm.getminima_maxvolfull = maxvolfull / 1000;            prm.watminvolfull = minvolfull / 1000;            prm.watmaxvolfull = maxvolfull / 1000;            prm.minvolfull = minvolfull;            prm.maxvolfull = maxvolfull;            prm.classifycells.minvolfull = minvolfull / 1000;            prm.classifycells.maxvolfull = maxvolfull / 1000;            Console.WriteLine("Using settings:");            /* 无用matlab代码            printstructscreen(prm);            */            //pixel size            prm.getminima_h = (double[])prm.h.Clone();            prm.classifycells.h = (double[])prm.h.Clone();            prm.smoothim.h = (double[])prm.h.Clone();            //gpu for smoothing            prm.smoothim.gpu = prm.gpu;            //zzzzz            prm.iInterpolationMethod = 1;            /*Cell segmentation start*/            //Correcting for uneven illumination            //Smoothing            PSmoothim prminsmt = prm.smoothim.Clone();            imsegm = smoothim(imsegm, prm.smoothim.method, "prm", prm);            //zzzzz Cv2.ImShow("smoothim", imsegm);//kkkkk            //zzzzz Cv2.WaitKey(0);//kkkkk            //Ridge enhancement            if (1 == prm.filterridges)            {                Console.WriteLine("Ridge enhancement");                //kkkkk imsegm = cellsegm.ridgeenhhessian(imsegm,prm.h);            }            else            {                Console.WriteLine("No ridge enhancement");            }            //Finding minima            OUTgetminima gmout = getminima(imsegm, minimacell, prmin);            //kkkkk minimacell = gmout.minimacell;            minima = gmout.minima;            //3D watershed segmentation            Console.WriteLine("3D watershed segmentation");            //Iimpose = imimposemin(imsegm,minima);            //wat = watershed(Iimpose);            //vector<vector<Point>> contour;            Mat watermark = new Mat(imsegm.Size(), MatType.CV_32S);            OpenCvSharp.Point[][] contour;            HierarchyIndex[] hier;            Cv2.FindContours(minima, out contour, out hier, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, null);            for (int i = 0; i < hier.Length; i++)            {                Cv2.DrawContours(watermark, contour, i, Scalar.All(i + 1), 1, LineTypes.Link8, hier);            }            //Mat Temp = new Mat(imsegm.Size(), MatType.CV_8UC3);            //imsegm.CopyTo(Temp);            Cv2.Watershed(IN5varhere.OrgImg, watermark);//mmmmm            //Mat afterWatershed = new Mat();//kkkkk            //Cv2.ConvertScaleAbs(watermark, afterWatershed);//kkkkk            //Cv2.ImWrite("D:\\afterWatershed.jpg", afterWatershed);//kkkkk            //Cv2.ImShow("watermark", afterWatershed);//kkkkk            //Cv2.WaitKey(0);//kkkkk            PClassifycells prmclf = prm.classifycells.Clone();            OUTclassifycells cfout;            if (null != minimacell)//mmmmm            {                cfout = classifycells(watermark, imsegmini, prmclf, minimacell);            }            else            {                cfout = classifycells(watermark, imsegmini, prmclf);            }            Mat cellbw = cfout.cellbw;            //kkkkk info.classifycells = cfout.classifycells;            //kkkkk info.prm = prm;            //9. 绘制轮廓 drawContours            //Mat maskers = Mat::zeros(imgDist8U.size(), CV_32SC1);            //for (size_t i=0; i<contour.size(); i++){            //drawContours(maskers, contour, static_cast<int>(i), Scalar::all(static_cast<int>(i) + 1)); }            //imshow("maskers", maskers);            //ttttt Cv2.FindContours(watermark, out contour, out hier, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, null);            rtn.wat = new Mat(watermark.Size(), MatType.CV_8UC4, new Scalar(255, 0, 0, 0));            //ttttt Cv2.DrawContours(rtn.wat, contour, -1, Scalar.Red);            int Rows = watermark.Rows;            int Cols = watermark.Cols;            int[] point = new int[2];            Vec4b redcol;            if (phaseColor != null)            {                redcol = new Vec4b(phaseColor.B, phaseColor.G, phaseColor.R, 255);            }            else                redcol = new Vec4b(0, 0, 255/*255*/, 255);            for (point[0] = 0; point[0] < Rows; point[0]++)            {                for (point[1] = 0; point[1] < Cols; point[1]++)                {                    if (0 >= watermark.At<int>(point[0], point[1]))                    {                        rtn.wat.Set<Vec4b>(point[0], point[1], redcol);//###                    }                }            }            double time = (Cv2.GetTickCount() - start) / Cv2.GetTickFrequency();            System.Console.WriteLine("晶界重现_执行时间:" + time);            ////Cv2.ImShow("contour", rtn.wat);//kkkkk            ////Cv2.WaitKey(0);//kkkkk            //control.Cursor = cursor;// System.Windows.Forms.Cursors.Default;            return rtn;        }                OUTclassifycells classifycells(Mat watermark, Mat imsegmini, PClassifycells prmclf, Mat minimacell = null)        {            OUTclassifycells rtn = new OUTclassifycells();            return rtn;        }        OUTgetminima getminima(Mat imsegm, Mat minimacell, In5segmsurf prmin)        {            OUTgetminima rtn = new OUTgetminima();            rtn.minima = null;            rtn.minimacell = null;            if (null == minimacell)            {                rtn.minima = automated(imsegm, prmin);            }            return rtn;        }        Mat automated(Mat imsegm, In5segmsurf prmin)        {            Mat mat_mean = new Mat(), mat_stddev = new Mat();            double m, s, d;            //Cv2.MeanStdDev(imsegm, mat_mean, mat_stddev);            //m = mat_mean.At<double>(0, 0);            //s = mat_stddev.At<double>(0, 0);            //d = 0;//mmmmm            double th;            //th = Math.Min(Math.Max(m+d*s, m/2),1.5*m);            Mat minima = new Mat(), minimacell = new Mat(imsegm.Size(), MatType.CV_8UC3);            //Cv2.Threshold(imsegm, minimacell, th, 255, ThresholdTypes.Binary);            int iRad = 39;            Mat matTempA = new Mat();            Mat matTempB = new Mat();            Cv2.MedianBlur(imsegm, matTempA, iRad);            Cv2.AddWeighted(imsegm, 1, matTempA, -1, 0, matTempB);            Cv2.MeanStdDev(matTempB, mat_mean, mat_stddev);            m = mat_mean.At<double>(0, 0);            s = mat_stddev.At<double>(0, 0);            d = 0;//mmmmm            th = m + d * s;            Cv2.Threshold(matTempB, minimacell, th, 255, ThresholdTypes.Binary);            int diam;//mmmmm            Mat kernel;            diam = 9;            kernel = Cv2.GetStructuringElement(MorphShapes.Cross, new Size(diam, diam), new OpenCvSharp.Point(-1, -1));            Cv2.Dilate(minimacell, minimacell, kernel);            diam = 3;            kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(diam, diam), new OpenCvSharp.Point(-1, -1));            Cv2.Erode(minimacell, minimacell, kernel);            Cv2.MorphologyEx(minimacell, minimacell, MorphTypes.Open, kernel);            //zzzzz Cv2.ImShow("bianjie", minimacell);            //zzzzz Cv2.WaitKey(0);            Cv2.BitwiseNot(minimacell, minima);            Size bianjieSize = minima.Size();            Mat Temp = Mat.Zeros(bianjieSize.Height + 2, bianjieSize.Width + 2, minimacell.Type());//延展图像            minima.CopyTo(Temp.SubMat(new Range(1, bianjieSize.Height + 1), new Range(1, bianjieSize.Width + 1)));            Cv2.FloodFill(Temp, new OpenCvSharp.Point(0, 0), new Scalar(255));            Mat cutImg = new Mat();            Temp.SubMat(new Range(1, bianjieSize.Height + 1), new Range(1, bianjieSize.Width + 1)).CopyTo(cutImg);            Cv2.BitwiseNot(cutImg, cutImg);            minima = minima | cutImg;            diam = 9;            kernel = Cv2.GetStructuringElement(MorphShapes.Rect, new Size(diam, diam), new OpenCvSharp.Point(-1, -1));            Cv2.MorphologyEx(minima, minima, MorphTypes.Open, kernel);            //zzzzz Cv2.ImShow("neibu", minima);//kkkkk            //zzzzz Cv2.WaitKey(0);//kkkkk            return minima;        }        Mat smoothim(Mat im, string method, string prmflg, In4smoothim prm)        {            //diameter of filter            int iPrmD = 13;            Mat rst = new Mat();            Cv2.ConvertScaleAbs(dircohenh(im, iPrmD, prm.h, prm.iInterpolationMethod), rst);            return rst;        }        Mat dircohenh(Mat im, int iPrmD, double[] adPrmH, int iInterpolationMethod)        {            int[] dim = new int[3] { im.Rows, im.Cols, 1 };            if (3 == im.Dims())            {                dim[2] = im.Height;            }            //number of elements to remove before one takes the Olympic average. Set to            //1-->3            int numremele = 2;            int stepxy = 30;            int numdeghere = (180 - stepxy) / stepxy + 1;            int[] deghere = new int[numdeghere];            deghere[0] = 0;            for (int i = 1; i < numdeghere; i++)            {                deghere[i] = deghere[i - 1] + stepxy;            }            double[,] deg2D = new double[numdeghere, 2];            for (int i = 1; i < numdeghere; i++)            {                deg2D[i, 0] = (double)(deghere[i]);                deg2D[i, 1] = 90;            }            double[,] deg;            deg = deg2D;            if (1 != dim[2])            {                double[,] deg3D = new double[numdeghere + 1, 2];                for (int i = 1; i < numdeghere; i++)                {                    deg3D[i, 0] = deg2D[i, 0];                    deg3D[i, 1] = deg2D[i, 1];                }                deg3D[numdeghere, 0] = 0;                deg3D[numdeghere, 1] = 0;                deg = deg3D;            }            //the half filter size            int p = iPrmD / 2;            //make filter            MyFilter[] c = makefilter(deg, p);            //number of directions            int numdir = c.Length;            //inisization            Mat filtim = new Mat(im.Rows, im.Cols, MatType.CV_32F, 0.0);            //zzzzz            //201118 for Acceleration   Mat imRs = new Mat();            Mat imRs = null;            float[] afImRs = null;            int iProportion = 5;            if (1 == iInterpolationMethod)            {                imRs = new Mat();//201118 for Acceleration                Mat imFt = new Mat();                im.ConvertTo(imFt, MatType.CV_32F);                Cv2.Resize(imFt, imRs, new Size(imFt.Cols * iProportion, imFt.Rows * iProportion), 0, 0, InterpolationFlags.Cubic);                //afImRs = new float[imRs.Rows, imRs.Cols];                afImRs = new float[imRs.Rows * imRs.Cols];                Marshal.Copy(imRs.Data, afImRs, 0, imRs.Rows * imRs.Cols);                /*            for (int i = 0; i < imRs.Rows; i++)            {                for (int j = 0; j < imRs.Cols; j++)                {                    afImRs[i, j] = imRs.At<float>(i, j);                }                 */                imRs = null;            }            for (int i = 0; i < numdir; i++)            {                //coordinates of points in this direction after rotation of filter                MyFilter chere = c[i];                //filter image for max value                //zzzzz                OUTmaxfilt3 fltrst;                if (1 == iInterpolationMethod)                {                    //201118 for Acceleration   fltrst = maxfilt3ByCubicSpline(im, chere, numremele/*, dim*/, imRs, iProportion);                    fltrst = maxfilt3ByCubicSpline(im, chere, numremele/*, dim*/, afImRs, iProportion);                }                else if (2 == iInterpolationMethod)                {                    fltrst = maxfilt3ByBilinear(im, chere, numremele/*, dim*/);                }                else                {                    fltrst = maxfilt3ByNearest(im, chere, numremele/*, dim*/);                }                //structural filtering                   //filtim = max(filtim,(sumim - sum(maxim,4))/ (numpoints-numremele));                int[] point = new int[2];                for (point[0] = 0; point[0] < filtim.Rows; point[0]++)                {                    for (point[1] = 0; point[1] < filtim.Cols; point[1]++)                    {                        float fTemp = filtim.At<float>(point[0], point[1]);                        /*201118 for Acceleration                         fTemp = Math.Max(fTemp,                            (fltrst.sumim[point[0], point[1]] - (fltrst.maxim[point[0], point[1]]).Sum()) / (fltrst.numpoints - numremele)                                        );                        */                        //(fltrst.minim[point[0], point[1]]).Sum()                        fTemp = fTemp = Math.Max(fTemp, (fltrst.minim[point[0]][point[1]].Take<float>(fltrst.numpoints - numremele)).Sum() / (fltrst.numpoints - numremele));                        filtim.Set<float>(point, fTemp);                    }                }            }            return filtim;        }        OUTmaxfilt3 maxfilt3ByNearest(Mat im, MyFilter chere, int numremele/*, int[] dim*/)        {            /////Mat imRs = new Mat();            /////im.ConvertTo(imRs, MatType.CV_32F);            int BigRows = im.Rows;            int BigCols = im.Cols;            OUTmaxfilt3 rst = new OUTmaxfilt3();            rst.sumim = new float[im.Rows, im.Cols];            rst.maxim = new List<float>[im.Rows, im.Cols];            for (int i = 0; i < im.Rows; i++)            {                for (int j = 0; j < im.Cols; j++)                {                    (rst.sumim)[i, j] = 0;                    List<float> lisTmp = new List<float>();                    for (int k = 0; k < numremele; k++)                    {                        lisTmp.Add(0);                    }                    (rst.maxim)[i, j] = lisTmp;                }            }            rst.numpoints = chere.x.Length;            for (int i = 0; i < rst.numpoints; i++)            {                double xhere;                double yhere;                int[] point = new int[2];                for (point[0] = 0; point[0] < im.Rows; point[0]++)                {                    for (point[1] = 0; point[1] < im.Cols; point[1]++)                    {                        xhere = (point[0] + (chere.x)[i]);                        yhere = (point[1] + (chere.y)[i]);                        int iX = Math.Min(Math.Max((int)(xhere + 0.5), 0), BigRows - 1);                        int iY = Math.Min(Math.Max((int)(yhere + 0.5), 0), BigCols - 1);                        float fTemp = im.At<byte>(iX, iY);                        (rst.sumim)[point[0], point[1]] += fTemp;                        (rst.maxim)[point[0], point[1]].Add(fTemp);                        (rst.maxim)[point[0], point[1]].Sort();                        (rst.maxim)[point[0], point[1]].RemoveAt(0);                        (rst.maxim)[point[0], point[1]].Reverse();                    }                }            }            return rst;        }        OUTmaxfilt3 maxfilt3ByBilinear(Mat im, MyFilter chere, int numremele/*, int[] dim*/)        {            /////Mat imRs = new Mat();            /////im.ConvertTo(imRs, MatType.CV_32F);            int BigRows = im.Rows;            int BigCols = im.Cols;            OUTmaxfilt3 rst = new OUTmaxfilt3();            rst.sumim = new float[im.Rows, im.Cols];            rst.maxim = new List<float>[im.Rows, im.Cols];            for (int i = 0; i < im.Rows; i++)            {                for (int j = 0; j < im.Cols; j++)                {                    (rst.sumim)[i, j] = 0;                    List<float> lisTmp = new List<float>();                    for (int k = 0; k < numremele; k++)                    {                        lisTmp.Add(0);                    }                    (rst.maxim)[i, j] = lisTmp;                }            }            rst.numpoints = chere.x.Length;            for (int i = 0; i < rst.numpoints; i++)            {                double xhere;                double yhere;                int[] point = new int[2];                for (point[0] = 0; point[0] < im.Rows; point[0]++)                {                    for (point[1] = 0; point[1] < im.Cols; point[1]++)                    {                        xhere = point[0] + (chere.x)[i];                        yhere = point[1] + (chere.y)[i];                        int iXS = Math.Min(Math.Max((int)(xhere), 0), BigRows - 1);                        int iYS = Math.Min(Math.Max((int)(yhere), 0), BigCols - 1);                        int iXB = Math.Min(Math.Max((int)(xhere + 1.0), 0), BigRows - 1);                        int iYB = Math.Min(Math.Max((int)(yhere + 1.0), 0), BigCols - 1);                        double dWXB = Math.Min(Math.Max((xhere - (double)iXS), 0.0), 1.0);                        double dWXS = 1.0 - dWXB;                        double dWYB = Math.Min(Math.Max((yhere - (double)iYS), 0.0), 1.0);                        double dWYS = 1.0 - dWYB;                        double dTempA = im.At<byte>(iXS, iYS);                        double dTempB = im.At<byte>(iXS, iYB);                        double dTempC = im.At<byte>(iXB, iYS);                        double dTempD = im.At<byte>(iXB, iYB);                        double dTempAB = dTempA * dWYS + dTempB * dWYB;                        double dTempCD = dTempC * dWYS + dTempD * dWYB;                        float fTemp = (float)(dTempAB * dWXS + dTempCD * dWXB);                        (rst.sumim)[point[0], point[1]] += fTemp;                        (rst.maxim)[point[0], point[1]].Add(fTemp);                        (rst.maxim)[point[0], point[1]].Sort();                        (rst.maxim)[point[0], point[1]].RemoveAt(0);                        (rst.maxim)[point[0], point[1]].Reverse();                    }                }            }            return rst;        }        //201118 for Acceleration   OUTmaxfilt3 maxfilt3ByCubicSpline(Mat im, MyFilter chere, int numremele/*, int[] dim*/, Mat imRs, int iProportion)        OUTmaxfilt3 maxfilt3ByCubicSpline(Mat im, MyFilter chere, int numremele, float[] afImRs, int iProportion)        {            /////Mat imFt = new Mat();            /////Mat imRs = new Mat();            /////im.ConvertTo(imFt, MatType.CV_32F);            /////int iProportion = 5;            /////Cv2.Resize(imFt, imRs, new Size(imFt.Cols * iProportion, imFt.Rows * iProportion), 0, 0, InterpolationFlags.Cubic);            //201118 for Acceleration   int BigRows = imRs.Rows;            //201118 for Acceleration   int BigCols = imRs.Cols;            int BigRows = im.Rows * iProportion;            int BigCols = im.Cols * iProportion;            /*            double[,] x = new double[dim[0], dim[1]];            double[,] y = new double[dim[0], dim[1]];            for (int i = 0; i < dim[0]; i++)            {                for (int j = 0; j < dim[1]; j++)                {                    x[i, j] = (double)i;                    y[i, j] = (double)j;                }            }            */            OUTmaxfilt3 rst = new OUTmaxfilt3();            //rst.maxim = new Mat[numremele];            //201118 for Acceleration   rst.sumim = new float[im.Rows, im.Cols];            //201118 for Acceleration   rst.maxim = new List<float>[im.Rows, im.Cols];            rst.numpoints = chere.x.Length;            rst.minim = new float[im.Rows][][];            for (int i = 0; i < im.Rows; i++)            {                rst.minim[i] = new float[im.Cols][];                for (int j = 0; j < im.Cols; j++)                {                    rst.minim[i][j] = new float[rst.numpoints];                    //201118 for Acceleration   (rst.sumim)[i, j] = 0;                    //201118 for Acceleration   List<float> lisTmp = new List<float>();                    //201118 for Acceleration   for (int k = 0; k < numremele; k++)                    //201118 for Acceleration   {                    //201118 for Acceleration       lisTmp.Add(0);                    //201118 for Acceleration   }                    //201118 for Acceleration   (rst.maxim)[i, j] = lisTmp;                    //201118 for Acceleration   List<float> lisTmpMin = new List<float>();                    //201118 for Acceleration   (rst.minim)[i, j] = lisTmpMin;                }            }            //Mat imhere = new Mat(imFt.Rows, imFt.Cols, MatType.CV_32F, 0.0);            /* 201118 for Acceleration            for (int i = 0; i < rst.numpoints; i++)            {                //the coordinate where we want to find the values                //NB!!!!!!!!!                //Must not do this for z direction, then it goes wrong.                //Do NOOOOOT replacestr any Inf or NaN by image values, then the filter                //does not work anymore!!!!!!                //xhere(xhere < h(1)) = h(1);xhere(xhere > dim(1)*h(1)) = dim(1)*h(1);                //yhere(yhere < h(1)) = h(1);yhere(yhere > dim(2)*h(1)) = dim(2)*h(2);                //double[,] xhere = new double[dim[0], dim[1]];                //double[,] yhere = new double[dim[0], dim[1]];                double xhere;                double yhere;                int[] point = new int[2];                for (point[0] = 0; point[0] < im.Rows; point[0]++)                {                    for (point[1] = 0; point[1] < im.Cols; point[1]++)                    {                        //xhere[i, j] = Math.Min(Math.Max(x[i, j]+(chere.x)[t],1),dim[0]);                        //yhere[i, j] = Math.Min(Math.Max(y[i, j]+(chere.y)[t],1),dim[1]);                        xhere = (point[0] + (chere.x)[i]) * iProportion;                        yhere = (point[1] + (chere.y)[i]) * iProportion;                        int iX = Math.Min(Math.Max((int)(xhere + 0.5), 0), BigRows - 1);                        int iY = Math.Min(Math.Max((int)(yhere + 0.5), 0), BigCols - 1);                        float fTemp = imRs.At<float>(iX, iY);                        //imhere.Set<float>(point, fTemp);                        (rst.sumim)[point[0], point[1]] += fTemp;                        (rst.maxim)[point[0], point[1]].Add(fTemp);                        (rst.maxim)[point[0], point[1]].Sort();                        (rst.maxim)[point[0], point[1]].RemoveAt(0);                        (rst.maxim)[point[0], point[1]].Reverse();                    }                }            }            */            for (int ir = 0; ir < im.Rows; ir++)            {                for (int ic = 0; ic < im.Cols; ic++)                {                    double xhere;                    double yhere;                    for (int ip = 0; ip < rst.numpoints; ip++)                    {                        xhere = (ir + (chere.x)[ip]) * iProportion;                        yhere = (ic + (chere.y)[ip]) * iProportion;                        int iX = Math.Min(Math.Max((int)(xhere + 0.5), 0), BigRows - 1);                        int iY = Math.Min(Math.Max((int)(yhere + 0.5), 0), BigCols - 1);                        //201118 for Acceleration   float fTemp = imRs.At<float>(iX, iY);                        float fTemp = afImRs[iX * BigCols + iY];                        //201118 for Acceleration   (rst.sumim)[ir, ic] += fTemp;                        //201118 for Acceleration   (rst.maxim)[ir, ic].Add(fTemp);                        (rst.minim)[ir][ic][ip] = fTemp;                    }                    //201118 for Acceleration   (rst.maxim)[ir, ic].Sort((x, y) => -x.CompareTo(y));                    //201118 for Acceleration   (rst.maxim)[ir, ic].RemoveRange(numremele, rst.numpoints - numremele);                    Array.Sort((rst.minim)[ir][ic]);                    //201118 for Acceleration   (rst.minim)[ir, ic].Sort();                    //201118 for Acceleration   (rst.minim)[ir, ic].RemoveRange(rst.numpoints - numremele,numremele);                }            }            return rst;        }        MyFilter[] makefilter(double[,] deg, int p)        {            int iNum = deg.GetLength(0);            MyFilter[] c = new MyFilter[iNum];            //r = linspace(-p,p,7);            int iArrLength = 7;            double[] r = new double[iArrLength];            double dStep = p * 2.0 / (iArrLength - 1.0);            for (int i = 0; i < 7; i++)            {                r[i] = -1.0 * p + i * dStep;            }            /*             for i = 1 : size(deg,1)                % the degrees                theta = deg(i,1);                phi = deg(i,2);                        % the positions                c(i).x = r*sind(phi)*cosd(theta);                c(i).y = r*sind(phi)*sind(theta);                c(i).z = r*cosd(phi);            end;             */            for (int i = 0; i < iNum; i++)            {                double theta = deg[i, 0];                double phi = deg[i, 1];                c[i] = new MyFilter();                c[i].x = new double[iArrLength];                c[i].y = new double[iArrLength];                c[i].z = new double[iArrLength];                for (int j = 0; j < iArrLength; j++)                {                    (c[i].x)[j] = r[j] * Math.Sin(phi) * Math.Cos(theta); ;                    (c[i].y)[j] = r[j] * Math.Sin(phi) * Math.Sin(theta); ;                    (c[i].z)[j] = r[j] * Math.Cos(phi);                }            }            return c;        }        public Mat ProFroStandardImage(Mat GryImg, int iConnect, Color phaseColor)        {            //Mat GryImg = new Mat();            ////转为为灰度?            //if (3 == OrgImg.Channels())            //{            //    Cv2.CvtColor(OrgImg, GryImg, ColorConversionCodes.RGB2GRAY);            //}            //else            //{            //    if (1 == OrgImg.Channels())            //    {            //        GryImg = OrgImg.Clone();            //    }            //    else            //    {            //        return null;            //    }            //}            Mat CrystalImg = new Mat();            Mat BoundaryImg = new Mat();            Mat mat_mean = new Mat(), mat_stddev = new Mat();            double m, s, d = 0.5;            Cv2.MeanStdDev(GryImg, mat_mean, mat_stddev);            m = mat_mean.At<double>(0, 0);            s = mat_stddev.At<double>(0, 0);            //Cv2.Threshold(GryImg, CrystalImg, (int)Math.Min(m+d*s,230), 255, ThresholdTypes.Binary);            //Cv2.Threshold(GryImg, CrystalImg, 0, 1, ThresholdTypes.Otsu);            Cv2.Threshold(GryImg, CrystalImg, m, 255, ThresholdTypes.Binary);            //Cv2.ImShow("src", CrystalImg);//kkkkk            //Cv2.WaitKey(0);//kkkkk            int diam = 3;//mmmmm            Mat kernel = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(diam, diam), new OpenCvSharp.Point(-1, -1));            //Cv2.Erode(CrystalImg, CrystalImg, kernel);            Cv2.MorphologyEx(CrystalImg, CrystalImg, MorphTypes.Open, kernel);            Cv2.BitwiseNot(CrystalImg, BoundaryImg);            //kernel = Cv2.GetStructuringElement(MorphShapes.Ellipse, new Size(diam, diam), new Point(-1, -1));            //Cv2.MorphologyEx(BoundaryImg, BoundaryImg, MorphTypes.Open, kernel);            //Cv2.MorphologyEx(BoundaryImg, BoundaryImg, MorphTypes.Close, kernel);            //Cv2.Dilate(BoundaryImg, BoundaryImg, kernel);            Class1 TCAlgo = new Class1();            TCAlgo.ImgThin(BoundaryImg);            //string filename = "D:\\temp.jpg";            //Cv2.ImWrite(filename, BoundaryImg);            if (1 == iConnect)            {                TCAlgo.ConnectionBoundary(BoundaryImg, 108);            }            //Cv2.ImShow("wai", BoundaryImg);//kkkkk            //Cv2.WaitKey(0);//kkkkk            //Cv2.BitwiseNot(BoundaryImg, CrystalImg);            //diam = 9;            //kernel = Cv2.GetStructuringElement(MorphShapes.Cross, new Size(diam, diam), new Point(-1, -1));            //Cv2.MorphologyEx(BoundaryImg, BoundaryImg, MorphTypes.Close, kernel);            //Cv2.Erode(CrystalImg, CrystalImg, kernel);            //Cv2.MorphologyEx(CrystalImg, CrystalImg, MorphTypes.Open, kernel);            //Cv2.MorphologyEx(CrystalImg, CrystalImg, MorphTypes.Close, kernel);            //Cv2.ImShow("nei", CrystalImg);//kkkkk            //Cv2.WaitKey(0);//kkkkk            /*            Mat watermark = new Mat(CrystalImg.Size(), MatType.CV_32S);            Point[][] contour;            HierarchyIndex[] hier;            Cv2.FindContours(CrystalImg, out contour, out hier, RetrievalModes.CComp, ContourApproximationModes.ApproxSimple, null);            for (int i = 0; i < hier.Length; i++)            {                Cv2.DrawContours(watermark, contour, i, Scalar.All(i + 1), 1, LineTypes.Link8, hier);            }            Cv2.Watershed(OrgImg, watermark);            BoundaryImg = new Mat(watermark.Size(), MatType.CV_8UC3);            //ttttt Cv2.DrawContours(rtn.wat, contour, -1, Scalar.Red);            */            /*            Mat NewWat = new Mat();            Cv2.BitwiseNot(CrystalImg, NewWat);            Cv2.ImShow("bian", NewWat);//kkkkk            Cv2.WaitKey(0);//kkkkk            ImgThin(NewWat);            int Rows = NewWat.Rows;            int Cols = NewWat.Cols;            */            int[] point = new int[2];            Vec4b redcol;            if (phaseColor != null)            {                redcol = new Vec4b(phaseColor.B, phaseColor.G, phaseColor.R, 255);            }            else                redcol = new Vec4b(0, 0, 255/*255*/, 255);            Mat WAT = new Mat(BoundaryImg.Size(), MatType.CV_8UC4);            for (point[0] = 0; point[0] < WAT.Rows; point[0]++)            {                for (point[1] = 0; point[1] < WAT.Cols; point[1]++)                {                    if (0 < BoundaryImg.At<byte>(point[0], point[1]))                    {                        WAT.Set<Vec4b>(point, redcol);                    }                }            }            return WAT;        }    }} 
 |