Пример #1
0
 public Rib(Versh first, Versh second, double dist)
 {
     _firstV  = first;
     _secondV = second;
     _dist    = dist;
     index    = 0;
 }
Пример #2
0
 // метод, задающий координату Z всему сегменту
 public void setZ(Versh ourSegm, int z)
 {
     foreach (Versh v in _v2d)
     {
         if (v.Root == ourSegm.Root)
         {
             v._z = z;
         }
     }
 }
Пример #3
0
 public void MergeSegment(Versh v)
 {
     //проверяем, если уже один сегмент
     if (this.Root == v.Root)
     {
         return;
     }
     VershCount += v.VershCount;
     v.Root      = this.Root;
 }
Пример #4
0
        // Нахождение заднего фона изображения
        public void FindBackground()
        {
            // Найдём самый большой сегмент, который касается верхнего края
            Versh Background = FindLargeSegment(0);

            // Т.к. это фон, координата z максимально возможно отдалена от пользователя
            int z = zCoordinates.Length;

            // Зададим z координату всем вершинам сегмента
            setZ(Background, z);
        }
Пример #5
0
 public Versh(int x1, int y1, byte r, byte g, byte b)
 {
     _count   = 1;
     _row     = x1;
     _column  = y1;
     _r       = r;
     _g       = g;
     _b       = b;
     _parent  = null;
     _maxDist = 0;
 }
Пример #6
0
 // принадлежит методу сверху, ищет самый больший перепад в сегменте
 private static void GetMaxDist(Versh root)
 {
     for (int i = ribs.Count - 1; i >= 0; i--)
     {
         //если оба принадлежат тому сегменту, который мы только что слепили - т.е. если у них тот же корень
         //то это ребро нам подходит
         if (ribs[i]._firstV.Root == root && ribs[i]._secondV.Root == root)
         {
             root.MaxDist = ribs[i]._dist;
             break;
         }
     }
 }
Пример #7
0
        // Нахождение самого большого сегмента в определённом ряду
        // Пока работает только для строк
        public Versh FindLargeSegment(int range)
        {
            int   max     = 1;
            Versh maxSegm = _v2d[range, 0];

            for (int x = 0; x < _width; x++)
            {
                if (_v2d[range, x].VershCount > max)
                {
                    max     = _v2d[range, x].VershCount;
                    maxSegm = _v2d[range, x];
                }
            }
            return(maxSegm.Root);
        }
Пример #8
0
        // очень умная шикарная штука, но она осложнила программу и добавила неточностей(
        private void MergeSegments()
        {
            //теперь объединяем уже существующие сегменты по какой-то хитрой формуле - МАГИЯ
            double ksegm = 2;

            for (int k = 0; k < ribs.Count; k++)
            {
                Rib r = ribs[k];
                //если у них один корень, то они уже в одном сегменте - тогда их не надо соединять снова
                if (r._firstV.Root == r._secondV.Root)
                {
                    continue;
                }
                //если же они в разных сегментах, то мы должны оценить, должны ли мы соединять сегменты
                //одинокий пиксель - сегмент из одной вершины

                //поправка от количества пикселей
                double t1 = ksegm / r._firstV.VershCount;
                double t2 = ksegm / r._secondV.VershCount;
                //перепады внутри сегментов с поправкой от количества пикселей внутри сегмента
                double m1 = r._firstV.MaxDist + t1;
                double m2 = r._secondV.MaxDist + t2;

                //меньшая из больших дистанций внутри сегментов, с поправкой (та которая с количеством пикселей)
                double minMax = Math.Min(m1, m2);

                if (r._dist < minMax)
                {
                    r._firstV.MergeSegment(r._secondV);
                    Versh root = r._firstV.Root;
                    //после объединения ищем новый наибольший перепад
                    //т.к. рёбра упорядочены по возрастанию веса, а мы идём с конца - первое попавшееся ребро из нашего сегмента будет самым большим
                    GetMaxDist(root);
                }
            }
        }
Пример #9
0
        public List <AreaContainer> FormAreas()
        {
            List <AreaContainer> result = new List <AreaContainer>();

            if (_v2d == null)
            {
                Segmentation segm = new Segmentation(_photo);
                segm.SortRebr();
                segm.Segment();
                _v2d = Segmentation.v2d; //Полученный битмап нам неинтересен, только массив
            }

            AreaContainer currentArea = new AreaContainer();
            // Сначала ищем землю
            // Находим самый большой сегмент на нижней строке (его корень)
            Versh ground      = FindLargeSegment(_height - 1);
            int   pixelRow    = 0;
            int   pixelColumn = 0;

            for (int i = 0; i < _width; i++)
            {
                if (_v2d[_height - 1, i].Root == ground.Root)
                {
                    pixelRow    = _height - 1;
                    pixelColumn = i;
                    break;
                }
            }
            // Формируем границу земли
            currentArea.Borders = FindBorder(pixelRow, pixelColumn);
            // Формируем всю область земли
            FormSingleArea(pixelRow, pixelColumn);
            // Добавляем землю в список областей - у неё будет индекс 0
            result.Add(currentArea);

            // Потом найдём небо
            currentArea = new AreaContainer();
            Versh sky = FindLargeSegment(0);

            pixelRow    = 0;
            pixelColumn = 0;
            for (int i = 0; i < _width; i++)
            {
                if (_v2d[0, i].Root == sky.Root)
                {
                    pixelRow    = 0;
                    pixelColumn = i;
                    break;
                }
            }
            // Формируем границу неба
            currentArea.Borders = FindBorder(pixelRow, pixelColumn);
            // Формируем всю область неба
            FormSingleArea(pixelRow, pixelColumn);
            // Добавляем небо в список областей - у него будет индекс 1
            result.Add(currentArea);

            // А теперь, дамы и господа, добавляем всё остальное
            for (int row = 0; row < _height; row++)
            {
                for (int column = 0; column < _width; column++)
                {
                    bool alreadyDone = false;
                    if (visited[row, column] == true)
                    {
                        continue;
                    }
                    // Чтобы избавиться от багов и мелких отростков пикселей
                    int svoi = 0;
                    for (int i = -1; i <= 1; i++)
                    {
                        for (int j = -1; j <= 1; j++)
                        {
                            if (row + i < 0 || row + i >= _height || column + j < 0 || column + j >= _width)
                            {
                                continue;
                            }
                            if (_v2d[row, column].Root == _v2d[row + i, column + j].Root)
                            {
                                svoi++;
                            }
                        }
                    }
                    if (svoi < 5)
                    {
                        continue;
                    }
                    currentArea = new AreaContainer();
                    // Ищет граничные пиксели
                    currentArea.Borders = FindBorder(row, column);
                    // Ищет все пиксели области
                    FormSingleArea(row, column);
                    // Добавляет в лист листов, где границы всех областей
                    result.Add(currentArea);
                }
            }
            return(result);
        }
Пример #10
0
        // Находим поверхность ("землю") 3д модели, а также максимальное количество слоёв
        public List <Versh> FindBorder(int firstRow, int firstColumn)
        {
            while (_v2d[firstRow, firstColumn].isBorderVersh(_height, _width) == false)
            {
                firstRow--;
            }

            int[,] steps = { { 0, 1 }, { 1, 1 }, { 1, 0 }, { 1, -1 }, { 0, -1 }, { -1, -1 }, { -1, 0 }, { -1, 1 } };

            List <Versh> borders = new List <Versh>();
            List <Versh> trash   = new List <Versh>();

            borders.Add(_v2d[firstRow, firstColumn]);
            Versh first   = _v2d[firstRow, firstColumn];
            Versh current = null;

            for (int k = 0; k < 8; k++)
            {
                int secondColumn = firstColumn + steps[k, 1];
                int secondRow    = firstRow + steps[k, 0];
                if (secondColumn < 0 || secondColumn >= _width || secondRow < 0 ||
                    secondRow >= _height)
                {
                    continue;
                }

                if (_v2d[secondRow, secondColumn].Root == first.Root &&
                    _v2d[secondRow, secondColumn].isBorderVersh(_height, _width) &&
                    _v2d[secondRow, secondColumn] != first)
                {
                    current = _v2d[secondRow, secondColumn];
                    borders.Add(current);
                    break;
                }
            }
            while (current != first)
            {
                bool foundNext     = false;
                int  currentRow    = current._row;
                int  currentColumn = current._column;
                for (int k = 0; k < 8; k++)
                {
                    int newRow    = currentRow + steps[k, 0];
                    int newColumn = currentColumn + steps[k, 1];
                    if (newRow == first._row && newColumn == first._column)
                    {
                        return(borders);
                    }
                    if (newColumn < 0 || newColumn >= _width || newRow < 0 ||
                        newRow >= _height)
                    {
                        continue;
                    }

                    if (_v2d[newRow, newColumn].Root == first.Root)
                    {
                        if (_v2d[newRow, newColumn].isBorderVersh(_height, _width))
                        {
                            if (borders.Contains(_v2d[newRow, newColumn]) == false)
                            {
                                if (trash.Contains(_v2d[newRow, newColumn]) == false) //для выхода из тупиков
                                {
                                    current = _v2d[newRow, newColumn];
                                    borders.Add(current);
                                    foundNext = true;
                                    break;
                                }
                            }
                        }
                    }
                }
                if (foundNext == false)
                {
                    trash.Add(borders[borders.Count - 1]);
                    borders.RemoveAt(borders.Count - 1);
                    current = borders[borders.Count - 1];
                }
            }
//            // Создадим землю 3д модели
//            for (int k = lastY, range = 0; k >= firstY; k--, range++)
//            {
//                for (int x = 0; x < _width; x++)
//                {
//                    // Оптимизировать??
//                    if (_v2d[k, x].Root == Ground.Root)
//                        _v2d[k, x]._z = range;
//                }
//            }
            return(borders);
        }
Пример #11
0
        public void SortRebr()
        {
            int index = 0;

            for (int i = 0; i < _height; i++)
            {
                for (int j = 0; j < _width; j++)
                {
                    r[i, j] = _photo[index++];
                    g[i, j] = _photo[index++];
                    b[i, j] = _photo[index++];
                }
            }
            v2d = new Versh[_height, _width];

            for (int x = 0; x < _height; x++)
            {
                for (int y = 0; y < _width; y++)
                {
                    v2d[x, y] = new Versh(x, y, r[x, y], g[x, y], b[x, y]);
                }
            }
            int[,] rebr = { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 0 }, { 2, 0 }, { 3, 0 } };

            for (int x = 0, limitX = _height - 3; x < limitX; x++)
            {
                for (int y = 0, limitY = _width - 3; y < limitY; y++)
                {
                    for (int i = 0; i < 6; i++)
                    {
                        int positionX = x + rebr[i, 0];
                        int positionY = y + rebr[i, 1];

                        //тут мы знаем, что следующий пиксель существует, потому что границы в цикле ширина-3, высота-3

                        CreateRib(x, y, positionX, positionY, r, g, b, v2d, ribs);
                    }
                }
                for (int y = _width - 3; y < _width; y++)
                {
                    for (int i = 0; i < 6; i++)
                    {
                        int positionX = x + rebr[i, 0];
                        int positionY = y + rebr[i, 1];

                        // если следующий пиксель не существует
                        if ((positionX >= _height) || (positionY >= _width))
                        {
                            continue;
                        }

                        CreateRib(x, y, positionX, positionY, r, g, b, v2d, ribs);
                    }
                }
            }
            for (int x = _height - 3; x < _height; x++)
            {
                for (int y = 0; y < _width; y++)
                {
                    for (int i = 0; i < 6; i++)
                    {
                        int positionX = x + rebr[i, 0];
                        int positionY = y + rebr[i, 1];

                        // если следующий пиксель не существует
                        if ((positionX >= _height) || (positionY >= _width))
                        {
                            continue;
                        }

                        CreateRib(x, y, positionX, positionY, r, g, b, v2d, ribs);
                    }
                }
            }
            // сортировка по дистанции (цене ребра)
            ribs.Sort((first, second) => first._dist.CompareTo(second._dist));
            foreach (Versh versh1 in v2d)
            {
                versh.Add(versh1);
            }
        }