private ObjectLayer Execute1stLevelSegmentation(GrayscaleProcessor gp, GrayscaleProcessor gpSobel, GrayscaleProcessor gpH)
        {
            ContourBasedSegmentation cbs = new ContourBasedSegmentation();

            cbs.CreatePrimarySegmentation(gp, MAX_CONTOURLENGTH);

            cbs.EvaluateContours(c =>
            {
                if (ContourProperties.FromContour(c).Convexity < 0.95)
                {
                    return(-1);
                }

                return(ContourValue.GetValue(c, gpSobel));
            });

            ObjectLayer layer = cbs.CreateLayer(MIN_CONTOURLENGTH, int.MaxValue);

            layer = new ContourOptimizer().RemoveNonCompactPixels(layer, 3);

            layer = layer.CreateAbove(obj =>
            {
                return(this.GetContourGradient(obj, gp) < 0);
            });

            //layer=new ConcaveObjectSeparation().Execute(layer, 0.33, true);

            return(layer);
        }
        private ObjectLayer Execute1stLevelSegmentation(GrayscaleProcessor gp, GrayscaleProcessor gpSobel, GrayscaleProcessor gpH)
        {
            ContourBasedSegmentation cbs = new ContourBasedSegmentation();

              cbs.CreatePrimarySegmentation(gp, MAX_CONTOURLENGTH);

              cbs.EvaluateContours(c =>
              {
            if (ContourProperties.FromContour(c).Convexity < 0.95) return -1;

            return ContourValue.GetValue(c, gpSobel);
              });

              ObjectLayer layer = cbs.CreateLayer(MIN_CONTOURLENGTH, int.MaxValue);

              layer = new ContourOptimizer().RemoveNonCompactPixels(layer, 3);

              layer = layer.CreateAbove(obj =>
              {
            return this.GetContourGradient(obj, gp) < 0;
              });

              layer = new ConcaveObjectSeparation().Execute(layer, 0.33, true);

              return layer;
        }
        private ObjectLayer Execute3rdLevelSegmentation(ObjectLayer l2ndLevel, GrayscaleProcessor gpSobel, GrayscaleProcessor gpH, float targetArea)
        {
            List<Contour> finalContours = new List<Contour>();

              for (int i = 0; i < l2ndLevel.Objects.Count; i++)
              {
            finalContours.Add(l2ndLevel.Objects[i].Contour);
              }

              double[] hBackground = this.GetBackgroundHistogram(l2ndLevel, gpH);
              double[] hForeground = this.GetForegroundHistogram(l2ndLevel, gpH);

              Parallel.For(0, l2ndLevel.Objects.Count, i =>
              {
            ImageObject obj = l2ndLevel.Objects[i];

            ContourProperties cp = ContourProperties.FromContour(obj.Contour);

            obj.Features.Add(new Feature("Area", cp.Area));
              });

              Map map = new Map(gpSobel.Width, gpSobel.Height);

              Parallel.For(0, gpH.Height, dy =>
              {
            for (int dx = 0; dx < gpH.Width; dx++)
            {
              UInt32 h = gpH[dx, dy];

              if (hForeground[h] <= hBackground[h]) continue;

              UInt32 id = l2ndLevel.Map[dx, dy];

              if (id != 0)
              {
            ImageObject obj = l2ndLevel.Objects.GetObjectById(id);

            double area = obj.Features["Area"].Value;

            if (area > 0.33 * targetArea) continue;
              }

              map[dx, dy] = 0xffffffff;
            }
              });

              ObjectLayer layer = new ConnectedComponentCollector().Execute(map);

              layer = new ContourOptimizer().RemoveNonCompactPixels(layer, 3);

              for (int i = 0; i < layer.Objects.Count; i++)
              {
            finalContours.Add(layer.Objects[i].Contour);
              }

              Contour[] contours = this.Sort(finalContours.ToArray(), gpSobel, gpH, targetArea);

              layer = this.CreateLayer(gpSobel.Width, gpSobel.Height, contours);

              Map finalMap = new Map(layer.Map, false);

              for (int dy = 0; dy < gpH.Height; dy++) for (int dx = 0; dx < gpH.Width; dx++)
            {
              if (l2ndLevel.Map[dx, dy] != 0) continue;

              if (map[dx, dy] != 0) continue;

              finalMap[dx, dy] = 0;
            }

              layer = new ConnectedComponentCollector().Execute(finalMap);

              layer = new ContourOptimizer().RemoveNonCompactPixels(layer, 3);

              layer = new ConcaveObjectSeparation().Execute(layer, 0.33, true);

              double minArea = Math.Max(0.1 * targetArea, MIN_AREA);

              layer = layer.CreateAbove(obj =>
              {
            float area = ContourProperties.FromContour(obj.Contour).Area;

            return area > minArea;
              });

              layer = this.RefillContours(layer);

              return layer;
        }
        private ObjectLayer Execute2ndLevelSegmentation(GrayscaleProcessor gp, GrayscaleProcessor gpSobel, GrayscaleProcessor gpH, float targetArea)
        {
            ContourBasedSegmentation cbs = new ContourBasedSegmentation();

              cbs.CreatePrimarySegmentation(gp, MAX_CONTOURLENGTH);

              cbs.EvaluateContours(c =>
              {
            return this.GetContourValue(c, gpSobel, gpH, targetArea);
              });

              ObjectLayer layer = cbs.CreateLayer(MIN_CONTOURLENGTH, int.MaxValue);

              layer = layer.CreateAbove(obj =>
              {
            return this.GetContourGradient(obj, gp) < 0;
              });

              layer = new ContourOptimizer().RemoveNonCompactPixels(layer, 3);

              layer = new ConcaveObjectSeparation().Execute(layer, 0.33, true);

              double[] hBackground = this.GetBackgroundHistogram(layer, gpH);
              double[] hForeground = this.GetForegroundHistogram(layer, gpH);

              bool isFirst = true;

              ObjectLayer firstStep = null;

              while (true)
              {
            bool removed = false;

            layer = layer.CreateAbove(obj =>
            {
              int[] hHistogram = this.GetHistogram(obj, gpH);

              double hRatioForeground = this.GetRatioForeground(hHistogram, hForeground, hBackground);

              if (hRatioForeground > 0.5) return true;

              for (int i = 0; i < 256; i++)
              {
            int val = hHistogram[i];

            hForeground[i] -= val;
            hBackground[i] += val;
              }

              removed = true;

              return false;
            });

            if (isFirst)
            {
              firstStep = layer;
              isFirst = false;
            }

            if (!removed) break;
              }

              if (layer.Objects.Count == 0) layer = firstStep;

              double minArea = Math.Max(0.1 * targetArea, MIN_AREA);

              layer = layer.CreateAbove(obj =>
              {
            float area = ContourProperties.FromContour(obj.Contour).Area;

            return area >= minArea;
              });

              layer = this.RefillContours(layer);

              return layer;
        }
        private ObjectLayer Execute3rdLevelSegmentation(ObjectLayer l2ndLevel, GrayscaleProcessor gpSobel, GrayscaleProcessor gpH, float targetArea)
        {
            List <Contour> finalContours = new List <Contour>();

            for (int i = 0; i < l2ndLevel.Objects.Count; i++)
            {
                finalContours.Add(l2ndLevel.Objects[i].Contour);
            }

            double[] hBackground = this.GetBackgroundHistogram(l2ndLevel, gpH);
            double[] hForeground = this.GetForegroundHistogram(l2ndLevel, gpH);

            Parallel.For(0, l2ndLevel.Objects.Count, i =>
            {
                ImageObject obj = l2ndLevel.Objects[i];

                ContourProperties cp = ContourProperties.FromContour(obj.Contour);

                obj.Features.Add(new Feature("Area", cp.Area));
            });

            Map map = new Map(gpSobel.Width, gpSobel.Height);

            Parallel.For(0, gpH.Height, dy =>
            {
                for (int dx = 0; dx < gpH.Width; dx++)
                {
                    UInt32 h = gpH[dx, dy];

                    if (hForeground[h] <= hBackground[h])
                    {
                        continue;
                    }

                    UInt32 id = l2ndLevel.Map[dx, dy];

                    if (id != 0)
                    {
                        ImageObject obj = l2ndLevel.Objects.GetObjectById(id);

                        double area = obj.Features["Area"].Value;

                        if (area > 0.33 * targetArea)
                        {
                            continue;
                        }
                    }

                    map[dx, dy] = 0xffffffff;
                }
            });

            ObjectLayer layer = new ConnectedComponentCollector().Execute(map);

            layer = new ContourOptimizer().RemoveNonCompactPixels(layer, 3);

            for (int i = 0; i < layer.Objects.Count; i++)
            {
                finalContours.Add(layer.Objects[i].Contour);
            }

            Contour[] contours = this.Sort(finalContours.ToArray(), gpSobel, gpH, targetArea);

            layer = this.CreateLayer(gpSobel.Width, gpSobel.Height, contours);

            Map finalMap = new Map(layer.Map, false);

            for (int dy = 0; dy < gpH.Height; dy++)
            {
                for (int dx = 0; dx < gpH.Width; dx++)
                {
                    if (l2ndLevel.Map[dx, dy] != 0)
                    {
                        continue;
                    }

                    if (map[dx, dy] != 0)
                    {
                        continue;
                    }

                    finalMap[dx, dy] = 0;
                }
            }

            layer = new ConnectedComponentCollector().Execute(finalMap);

            layer = new ContourOptimizer().RemoveNonCompactPixels(layer, 3);

            //layer=new ConcaveObjectSeparation().Execute(layer, 0.33, true);

            double minArea = Math.Max(0.1 * targetArea, MIN_AREA);

            layer = layer.CreateAbove(obj =>
            {
                float area = ContourProperties.FromContour(obj.Contour).Area;

                return(area > minArea);
            });

            layer = this.RefillContours(layer);

            return(layer);
        }
        private ObjectLayer Execute2ndLevelSegmentation(GrayscaleProcessor gp, GrayscaleProcessor gpSobel, GrayscaleProcessor gpH, float targetArea)
        {
            ContourBasedSegmentation cbs = new ContourBasedSegmentation();

            cbs.CreatePrimarySegmentation(gp, MAX_CONTOURLENGTH);

            cbs.EvaluateContours(c =>
            {
                return(this.GetContourValue(c, gpSobel, gpH, targetArea));
            });

            ObjectLayer layer = cbs.CreateLayer(MIN_CONTOURLENGTH, int.MaxValue);

            layer = layer.CreateAbove(obj =>
            {
                return(this.GetContourGradient(obj, gp) < 0);
            });

            layer = new ContourOptimizer().RemoveNonCompactPixels(layer, 3);

            //layer=new ConcaveObjectSeparation().Execute(layer, 0.33, true);

            double[] hBackground = this.GetBackgroundHistogram(layer, gpH);
            double[] hForeground = this.GetForegroundHistogram(layer, gpH);

            bool isFirst = true;

            ObjectLayer firstStep = null;

            while (true)
            {
                bool removed = false;

                layer = layer.CreateAbove(obj =>
                {
                    int[] hHistogram = this.GetHistogram(obj, gpH);

                    double hRatioForeground = this.GetRatioForeground(hHistogram, hForeground, hBackground);

                    if (hRatioForeground > 0.5)
                    {
                        return(true);
                    }

                    for (int i = 0; i < 256; i++)
                    {
                        int val = hHistogram[i];

                        hForeground[i] -= val;
                        hBackground[i] += val;
                    }

                    removed = true;

                    return(false);
                });

                if (isFirst)
                {
                    firstStep = layer;
                    isFirst   = false;
                }

                if (!removed)
                {
                    break;
                }
            }

            if (layer.Objects.Count == 0)
            {
                layer = firstStep;
            }

            double minArea = Math.Max(0.1 * targetArea, MIN_AREA);

            layer = layer.CreateAbove(obj =>
            {
                float area = ContourProperties.FromContour(obj.Contour).Area;

                return(area >= minArea);
            });

            layer = this.RefillContours(layer);

            return(layer);
        }