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); }
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()); }
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); }