public static ConnectLevel connectLevel(this Image <Gray, Byte> src, int curLv, int level, int padding)
        {
            ConnectLevel conn = new ConnectLevel {
                Level = curLv
            };
            int width = src.Width, height = src.Height;
            var visit = new bool[height, width];
            int grade = 256 / level, color = conn.Level * grade;

            for (int i = padding; i < height - padding; ++i)
            {
                for (int j = padding; j < width - padding; ++j)
                {
                    if (visit[i, j])
                    {
                        continue;
                    }
                    Point p = new Point(j, i);
                    if (src[i, j].Intensity < color)
                    {
                        conn.NotIn.Add(p);
                    }
                    else
                    {
                        bfsSearch(src, visit, conn, p, color, padding);
                    }
                }
            }
            double[] stats = Stats.CalcMeansAndVariance(conn.Domains.Select(c => (double)c.Area).ToArray());
            conn.MeanArea = stats[0];
            conn.Variance = stats[1];
            return(conn);
        }
        public static ConnectLevel[] Connect(this Image <Gray, Byte> src, int level)
        {
            var result = new ConnectLevel[level];

            for (int i = 0; i < level; ++i)
            {
                result[i] = connectLevel(src, i, level, 1);
            }
            return(result);
        }
 public static Image<Bgr, Byte> ColorLevel(this Image<Gray, Byte> src, ConnectLevel conn)
 {
     var dst = src.Convert<Bgr, Byte>();
     var color = new Bgr(0, 0, 255);
     foreach (var domain in conn.Domains) {
         foreach (var p in domain.Points) {
             dst[p.Y, p.X] = color;
         }
     }
     return dst;
 }
        private static int bfsSearch(Image <Gray, Byte> img, bool[,] vi, ConnectLevel conn, Point start, int color, int padding)
        {
            if (vi[start.Y, start.X])
            {
                return(0);
            }

            var domain = new ConnectDomain();

            Queue <Point> queue = new Queue <Point>();

            queue.Enqueue(start);
            var dir = DirVec;

            while (queue.Count > 0)
            {
                Point p = queue.Dequeue();
                if (vi[p.Y, p.X])
                {
                    continue;
                }
                vi[p.Y, p.X] = true;
                domain.Add(p);
                for (int i = 0; i < connect; ++i)
                {
                    int ny = p.Y + dir[i, 1], nx = p.X + dir[i, 0];
                    if (ny < padding || ny >= img.Height - padding)
                    {
                        continue;
                    }
                    if (nx < padding || nx >= img.Width - padding)
                    {
                        continue;
                    }

                    if (vi[ny, nx])
                    {
                        continue;             // 提前判断一下,好选择加入哪个集合
                    }
                    Point np = new Point(nx, ny);
                    if (img[ny, nx].Intensity >= color)
                    {
                        queue.Enqueue(np);
                    }
                    else
                    {
                        conn.NotIn.Add(np);
                    }
                }
            }
            conn.AddDomain(domain);
            return(domain.Area);
        }
        public static Image <Bgr, Byte> ColorLevel(this Image <Gray, Byte> src, ConnectLevel conn)
        {
            var dst   = src.Convert <Bgr, Byte>();
            var color = new Bgr(0, 0, 255);

            foreach (var domain in conn.Domains)
            {
                foreach (var p in domain.Points)
                {
                    dst[p.Y, p.X] = color;
                }
            }
            return(dst);
        }
        public static ConnectLevel connectLevel(this Image<Gray, Byte> src, int curLv, int level, int padding)
        {
            ConnectLevel conn = new ConnectLevel { Level = curLv };
            int width = src.Width, height = src.Height;
            var visit = new bool[height, width];
            int grade = 256 / level, color = conn.Level * grade;

            for (int i = padding; i < height - padding; ++i) {
                for (int j = padding; j < width - padding; ++j) {
                    if (visit[i, j]) continue;
                    Point p = new Point(j, i);
                    if (src[i, j].Intensity < color) {
                        conn.NotIn.Add(p);
                    } else {
                        bfsSearch(src, visit, conn, p, color, padding);
                    }
                }
            }
            double[] stats = Stats.CalcMeansAndVariance(conn.Domains.Select(c => (double)c.Area).ToArray());
            conn.MeanArea = stats[0];
            conn.Variance = stats[1];
            return conn;
        }
 public static ConnectLevel[] Connect(this Image<Gray, Byte> src, int level)
 {
     var result = new ConnectLevel[level];
     for (int i = 0; i < level; ++i) {
         result[i] = connectLevel(src, i, level, 1);
     }
     return result;
 }
        private static int bfsSearch(Image<Gray, Byte> img, bool[,] vi, ConnectLevel conn, Point start, int color, int padding)
        {
            if (vi[start.Y, start.X]) return 0;

            var domain = new ConnectDomain();

            Queue<Point> queue = new Queue<Point>();
            queue.Enqueue(start);
            var dir = DirVec;
            while (queue.Count > 0) {
                Point p = queue.Dequeue();
                if (vi[p.Y, p.X]) continue;
                vi[p.Y, p.X] = true;
                domain.Add(p);
                for (int i = 0; i < connect; ++i) {
                    int ny = p.Y + dir[i, 1], nx = p.X + dir[i, 0];
                    if (ny < padding || ny >= img.Height - padding) continue;
                    if (nx < padding || nx >= img.Width - padding) continue;

                    if (vi[ny, nx]) continue; // 提前判断一下,好选择加入哪个集合

                    Point np = new Point(nx, ny);
                    if (img[ny, nx].Intensity >= color) {
                        queue.Enqueue(np);
                    } else {
                        conn.NotIn.Add(np);
                    }
                }
            }
            conn.AddDomain(domain);
            return domain.Area;
        }