Example #1
0
        // Вычисление параметров объекта, которые будут
        // использованы для последующей его класстеризации.
        private ObjectParameters сalculateParameters(BitmapIntMatrix ba, List <Point> objectPoints)
        {
            ObjectParameters parameters = new ObjectParameters();

            parameters.Square = objectPoints.Count;

            int blackColor = unchecked ((int)(0xFF000000));

            foreach (Point objectPoint in objectPoints)
            {
                int x = objectPoint.X, y = objectPoint.Y;

                int top = ba[x, y + 1], bottom = ba[x, y - 1],
                    right = ba[x + 1, y], left = ba[x - 1, y];

                // Если есть чёрный сосед-4
                if (top == blackColor || bottom == blackColor ||
                    right == blackColor || left == blackColor)
                {
                    parameters.Perimeter++;
                }

                parameters.Xmas += x;
                parameters.Ymas += y;
            }

            parameters.Xmas /= parameters.Square;
            parameters.Ymas /= parameters.Square;

            foreach (Point objectPoint in objectPoints)
            {
                int x = objectPoint.X, y = objectPoint.Y;

                parameters.m02 += Math.Pow((y - parameters.Ymas), 2);
                parameters.m20 += Math.Pow((x - parameters.Xmas), 2);
                parameters.m11 += (x - parameters.Xmas) * (y - parameters.Ymas);
            }

            parameters.Compactness = Math.Pow((parameters.Perimeter), 2) / parameters.Square;

            double a1 = parameters.m20 + parameters.m02;
            double a2 = Math.Sqrt(
                Math.Pow((parameters.m20 - parameters.m02), 2) +
                4 * Math.Pow(parameters.m11, 2)
                );

            if ((a1 - a2) != 0)
            {
                parameters.Elongation = (a1 + a2) / (a1 - a2);
            }
            else
            {
                parameters.Elongation = 1;
            }

            return(parameters);
        }
Example #2
0
        // Int32 min-фильтр, анализирующий 32-разрядное значение содержания пикселя
        public static Image MinFilterInt(Image img, byte coreRank)
        {
            if (coreRank < 3 || coreRank % 2 == 0)
            {
                MessageBox.Show("Недопустимое значение размерности ядра фильтра: значение не может быть меньше 3, или чётным числом.");
                return(img);
            }

            BitmapIntMatrix bimOriginal = new BitmapIntMatrix(img);
            BitmapIntMatrix bimResult   = new BitmapIntMatrix(img.Width, img.Height);

            for (int x = 0; x < img.Width; ++x)
            {
                int
                    start_x_area = x - coreRank / 2,
                    end_x_area   = x + coreRank / 2;

                if (start_x_area < 0)
                {
                    start_x_area = 0;
                }
                if (end_x_area >= img.Width)
                {
                    end_x_area = img.Width;
                }

                for (int y = 0; y < img.Height; ++y)
                {
                    int
                        start_y_area = y - coreRank / 2,
                        end_y_area   = y + coreRank / 2;

                    if (start_y_area < 0)
                    {
                        start_y_area = 0;
                    }
                    if (end_y_area >= img.Height)
                    {
                        end_y_area = img.Height;
                    }

                    int[] area    = new int[(end_x_area - start_x_area + 1) * (end_y_area - start_y_area + 1)];
                    int   counter = 0;

                    // Сбор значений из области, покрываемой ядром
                    for (int x_m = start_x_area; x_m < end_x_area; ++x_m)
                    {
                        for (int y_m = start_y_area; y_m < end_y_area; ++y_m)
                        {
                            area[counter] = bimOriginal[x_m, y_m];
                            ++counter;
                        }
                    }

                    // Выбор наименьшего из найденных значений
                    int min = int.MaxValue;
                    for (int i = 0; i < area.Length; ++i)
                    {
                        if (area[i] < min)
                        {
                            min = area[i];
                        }
                    }

                    bimResult[x, y] = min;
                }
            }

            return(bimResult.getImage());
        }
Example #3
0
        // Разметка отдельных доменов уникальными численными значениями и
        // формирование массивов, состоящих из непересекающихся множеств пикселей.
        private BitmapIntMatrix differentiationOfConnectedDomains(Image img)
        {
            this.domainsMap = new BitmapIntMatrix(img);

            int blackColor = unchecked ((int)(0xFF000000));
            int whiteColor = unchecked ((int)(0xFFFFFFFF));

            for (int i = 0; i < domainsMap.Width; ++i)
            {
                domainsMap[i, 0] = blackColor;
                domainsMap[i, domainsMap.Height - 1] = blackColor;
            }
            for (int j = 0; j < domainsMap.Height; ++j)
            {
                domainsMap[0, j] = blackColor;
                domainsMap[domainsMap.Width - 1, j] = blackColor;
            }

            // Переменная отметки сплошной залитой области (объекта)
            int domainMarkCounter = 0;
            // Списки групп объектов, состоящих в соседстве-4
            List <List <int> > groupsNeighbors = new List <List <int> >();

            // Построчный проход заливки слева направо, сверху вниз
            for (int y = 1; y < domainsMap.Height; ++y)
            {
                for (int x = 1; x < domainsMap.Width; ++x)
                {
                    int target = domainsMap[x, y], top = domainsMap[x, y - 1], left = domainsMap[x - 1, y];

                    if (target != blackColor)
                    {
                        if (left != blackColor)
                        {
                            domainsMap[x, y] = left;

                            if (!domainsPixelTable.ContainsKey(left))
                            {
                                domainsPixelTable[left] = new List <Point>();
                            }

                            domainsPixelTable[left].Add(new Point(x, y));

                            // Если верхний и левый отличны от чёрного и не равны
                            if ((top != left) && (top != blackColor))
                            {
                                int leftGroupIndex = -1;
                                int topGroupIndex  = -1;

                                // Поиск групп, которым принадлежат объекты
                                for (int i = 0; i < groupsNeighbors.Count; ++i)
                                {
                                    if (groupsNeighbors[i].Contains(left))
                                    {
                                        leftGroupIndex = i;
                                    }

                                    if (groupsNeighbors[i].Contains(top))
                                    {
                                        topGroupIndex = i;
                                    }

                                    // Если обе группы найдены
                                    if ((leftGroupIndex != -1) && (topGroupIndex != -1))
                                    {
                                        break;
                                    }
                                }

                                // Если таких групп нет, то нужно создать новую группу
                                if ((leftGroupIndex == -1) && (topGroupIndex == -1))
                                {
                                    groupsNeighbors.Add(new List <int> {
                                        left, top
                                    });
                                }
                                // Если они в одной группе
                                else if (leftGroupIndex == topGroupIndex)
                                {
                                    continue;
                                }
                                // Если нет группы левого объекта, то добавить его в группу верхнего
                                else if (leftGroupIndex == -1)
                                {
                                    groupsNeighbors[topGroupIndex].Add(left);
                                }
                                // Если нет группы верхнего объекта, то добавить его в группу левого
                                else if (topGroupIndex == -1)
                                {
                                    groupsNeighbors[leftGroupIndex].Add(top);
                                }
                                // Если если они принадлежат двум разным группам, то необходимо объединить их
                                else
                                {
                                    groupsNeighbors[topGroupIndex].AddRange(groupsNeighbors[leftGroupIndex]);
                                    groupsNeighbors.RemoveAt(leftGroupIndex);
                                }
                            }
                        }
                        else if (top != blackColor)
                        {
                            domainsMap[x, y] = top;

                            if (!domainsPixelTable.ContainsKey(top))
                            {
                                domainsPixelTable[top] = new List <Point>();
                            }

                            domainsPixelTable[top].Add(new Point(x, y));
                        }
                        else if (target == whiteColor)
                        {
                            if (++domainMarkCounter == blackColor)
                            {
                                ++domainMarkCounter;
                            }

                            domainsMap[x, y] = domainMarkCounter;

                            domainsPixelTable[domainMarkCounter] = new List <Point>();

                            domainsPixelTable[domainMarkCounter].Add(new Point(x, y));

                            // Если предворительный счётчик объектов достиг предельного значения UInt32
                            if (domainMarkCounter == int.MaxValue)
                            {
                                throw new Exception("Переполнение счётчика числа объектов на изображении.");
                            }
                        }
                    }
                }
            }

            // Если есть группы объектов, состоящих в соседстве-4,
            // то необходимо произвести их слияние
            if (groupsNeighbors.Count > 0)
            {
                foreach (List <int> groupNeighbors in groupsNeighbors)
                {
                    do
                    {
                        int lastNeighbor = groupNeighbors.Last();

                        domainsPixelTable[groupNeighbors[0]].AddRange(domainsPixelTable[lastNeighbor]);
                        domainsPixelTable.Remove(lastNeighbor);
                        groupNeighbors.Remove(lastNeighbor);
                    }while (groupNeighbors.Count > 1);

                    // Перекрашивание карты объектов
                    foreach (Point pixel in domainsPixelTable[groupNeighbors[0]])
                    {
                        domainsMap[pixel.X, pixel.Y] = groupNeighbors[0];
                    }

                    groupNeighbors.Clear();
                }
            }

            MessageBox.Show(domainsPixelTable.Count.ToString());

            return(domainsMap);
        }