Ejemplo n.º 1
0
        private static double GetIntensityPixel(Pixel pixel, IntensivityStandard standard)
        {
            if (standard == IntensivityStandard.DigitalITU)
            {
                //Digital ITU BT.601
                return(pixel.Color.R * 0.299 + pixel.Color.G * 0.587 + pixel.Color.B * 0.114);
            }
            else if (standard == IntensivityStandard.Photometric)
            {
                //Photometric / digital ITU BT.709
                return(pixel.Color.R * 0.2126 + pixel.Color.G * 0.7152 + pixel.Color.B * 0.0722);
            }
            if (standard == IntensivityStandard.ApproximationFormula)
            {
                //Approximation formula
                return(pixel.Color.R * 0.375 + pixel.Color.B * 0.5 + pixel.Color.G * 0.125);
            }

            return(Double.NaN);
        }
Ejemplo n.º 2
0
        private static IList <Edge> SortEdges(IList <Edge> workEdges, SegmentationType type, IntensivityStandard standard)
        {
            if (type == SegmentationType.Intensity)
            {
                foreach (var edge in workEdges)
                {
                    edge.Weight = Math.Abs(GetIntensityPixel(edge.StartPixel, standard) - GetIntensityPixel(edge.EndPixel, standard));
                }
            }
            else if (type == SegmentationType.Color)
            {
                foreach (var edge in workEdges)
                {
                    edge.Weight = GetDistColorEdge(edge);
                }
            }

            return(workEdges.OrderBy(w => w.Weight).ToList());
        }
Ejemplo n.º 3
0
        public static Bitmap RunSeparation(Bitmap sourceBitmap, SegmentationType type, Connectivity connectivity, double delta, IntensivityStandard standard, ColorsOfSegments colorsOfSegments, CancellationToken token)
        {
            Bitmap resultBitmap = new Bitmap(sourceBitmap.Width, sourceBitmap.Height);

            Pixel[,] graphFromSourceBitmap = BuildGraphByImage(sourceBitmap);

            // Получаем набор связных ребер для данного пикселя
            IList <Edge> collectionOfEdges = GetEdges(graphFromSourceBitmap, connectivity);

            // Присваиваем им вес в зависимости от выбранного способа сегментации и сортируем их по возрастанию
            collectionOfEdges = SortEdges(collectionOfEdges, type, standard);

            // Создадим коллекцию для будующих сегментов, первым сегментом будет первое ребро из нашего полученного graphFromSoueceBitmap.
            List <Tree> segments = new List <Tree>()
            {
                new Tree(collectionOfEdges.First())
            };

            // На начальном этапе имеется набор минимальных деревьев, состоящих из одного ребра, имеющего свой вес. Объекты отсортированы по возрастанию.
            // Делаем обход по всем пикселям, объединяя соседние в деревья (либо соседние деревья в одно), если они удовлетворяют критерию похожести
            foreach (var edge in collectionOfEdges)
            {
                token.ThrowIfCancellationRequested();
                if (edge.EndPixel.Root == null && edge.StartPixel.Root == null)
                {
                    //Оба пикселя ребра не принадлежат ни одному из сегментов, значит такого сегмента еще нет и его необходимо создать
                    segments.Add(new Tree(edge));
                }
                else if (edge.StartPixel.Root != null && edge.EndPixel.Root == null)
                {
                    Tree tree = GetTreeByRoot(edge.StartPixel.Root, segments);
                    // Первый пиксель ребра содержится в каком то сегменте, нужно проверить на возможноть присоединения ребра к treeOfStartPixel
                    if (Math.Abs(edge.Weight - tree.MaxWeightEdge.Weight) > delta)
                    {
                        // Перепад больше заданного параметра delta, поэтому мы не присоединяем это ребро к treeOfStartPixel,
                        // переходим к рассмотрению следующего ребра
                        continue;
                    }
                    else
                    {
                        // Перепад удовлетворяет заданному параметру delta, поэтому мы присоединяем это ребро к treeOfStartPixel
                        tree.AddEdge(edge.StartPixel, edge.EndPixel);
                    }
                }
                else if (edge.StartPixel.Root == null && edge.EndPixel.Root != null)
                {
                    Tree tree = GetTreeByRoot(edge.EndPixel.Root, segments);
                    // Второй пиксель ребра содержится в каком то сегменте, нужно проверить на возможноть присоединения ребра к treeOfEndPixel
                    if (Math.Abs(edge.Weight - tree.MaxWeightEdge.Weight) > delta)
                    {
                        // Перепад больше заданного параметра delta, поэтому мы не присоединяем это ребро к treeOfStartPixel,
                        // переходим к рассмотрению следующего ребра
                        continue;
                    }
                    else
                    {
                        // Перепад удовлетворяет заданному параметру delta, поэтому мы присоединяем это ребро к treeOfStartPixel
                        tree.AddEdge(edge.EndPixel, edge.StartPixel);
                    }
                }
                else if (edge.EndPixel.Root.Equals(edge.StartPixel.Root))
                {
                    // Точки этого ребра уже содержаться в одном дереве, поэтому переходим к следующему ребру
                    continue;
                }
                else
                {
                    Tree firstTree  = GetTreeByRoot(edge.StartPixel.Root, segments);
                    Tree secondTree = GetTreeByRoot(edge.EndPixel.Root, segments);
                    // Пиксели ребра содержатся в разных сегментах, нужно проверить возможность их объединения
                    if (Math.Abs(edge.Weight - firstTree.MaxWeightEdge.Weight) > delta ||
                        Math.Abs(edge.Weight - secondTree.MaxWeightEdge.Weight) > delta)
                    {
                        // Если перепад на границе и внутри хотя бы одного сегмента больше заданного параметра delta,
                        // тогда эти сегменты не объединяются и переходим к рассмотрению следующего ребра
                    }
                    else
                    {
                        // Перепад на границе удовлетворяет заданному параметру delta, нужно объединить эти сегменты
                        // Сначала добавим ребро к графу
                        firstTree.AddEdge(edge);
                        // Потом присоединим второе дерево
                        firstTree.Join(secondTree);
                        // Удалим сегмент после его присоединения
                        segments.Remove(secondTree);
                    }
                }
            }

            // Сгенерируем цвета для полученных областей
            InitiateColorSegments(segments, colorsOfSegments, token);

            // Заполним resultBitmap
            foreach (var tree in segments)
            {
                foreach (var pixel in tree.Pixels)
                {
                    resultBitmap.SetPixel(pixel.X, pixel.Y, tree.Color);
                }
            }

            return(resultBitmap);
        }