Example #1
0
        private void CreateRib(int x1, int y1, int x2, int y2, byte[,] r, byte[,] g, byte[,] b, Versh[,] v2d, List <Rib> list)
        {
            double dist = Math.Sqrt(Math.Pow((x1 - x2), 2) + Math.Pow((y1 - y2), 2) +
                                    Math.Pow((r[x1, y1] - r[x2, y2]), 2) +
                                    Math.Pow((g[x1, y1] - g[x2, y2]), 2) +
                                    Math.Pow((b[x1, y1] - b[x2, y2]), 2));

            Rib rib = new Rib(v2d[x1, y1], v2d[x2, y2], dist);

            ribs.Add(rib);
            list.Add(rib);
        }
Example #2
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);
                }
            }
        }
Example #3
0
        // проходим второй раз либо по всем рёбрам, лбо по маленьким (реализовано два варианта)
        private void RemoveSmallSegments()
        {
            int[,] rebr = { { 0, 1 }, { 1, 0 } };

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

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

                        CreateRib(x, y, positionX, positionY, r, g, b, v2d, smallRibs);
                    }
                }
                for (int y = _width - 1; y < _width; y++)
                {
                    for (int i = 0; i < 2; 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, smallRibs);
                    }
                }
            }
            for (int x = _height - 1; x < _height; x++)
            {
                for (int y = 0; y < _width; y++)
                {
                    for (int i = 0; i < 2; 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, smallRibs);
                    }
                }
            }
            int minSize = (_height + _width) / segmSize;

            for (int k = 0, ribCount = ribs.Count; k < ribCount; k++)  // для всех рёбер
            // for (int k = 0, ribCount = smallRibs.Count; k < ribCount; k++) // для маленьких рёбер
            {
                Rib r = ribs[k];   // для всех рёбер
                // Rib r = smallRibs[k]; // для маленьких рёбер

                //если у них один корень, то они уже в одном сегменте - тогда их не надо соединять снова
                if (r._firstV.Root == r._secondV.Root)
                {
                    continue;
                }
                //если вершины в разных сегментах, и вес ребра меньше лимита - соединяем сегменты
                if (r._secondV.Root.VershCount < minSize)
                {
                    r._firstV.MergeSegment(r._secondV);
                }
                else if (r._firstV.Root.VershCount < minSize)
                {
                    r._secondV.MergeSegment(r._firstV);
                }
            }
        }
Example #4
0
        public Bitmap Segment()
        {
            int[,] maxSize = new int[_height * _width, 2];
            // соединяем по пикселям
            for (int k = 0, ribCount = ribs.Count /*так он один раз вычислит и не будет делать это на каждом шаге*/; k < ribCount; k++)
            {
                Rib r = ribs[k];
                if (r._dist > limit)
                {
                    break;
                }
                //если у них один корень, то они уже в одном сегменте - тогда их не надо соединять снова
                if (r._firstV.Root == r._secondV.Root)
                {
                    continue;
                }
                //если же они в разных сегментах, то мы должны оценить, должны ли мы соединять сегменты.
                //Одинокий пиксель - сегмент из одной вершины

                //если вершины в разных сегментах, и вес ребра меньше лимита - соединяем сегменты
                if (r._dist < limit)
                {
                    r._firstV.MergeSegment(r._secondV);
                }
            }
            //для каждого сегмента ищем самое большое ребро внутри него (идём от больших к меньшим, т.к. ищем больший)
            for (int k = ribs.Count - 1; k >= 0; k--)
            {
                if (ribs[k]._firstV.Root == ribs[k]._secondV.Root && ribs[k]._firstV.MaxDist < ribs[k]._dist)
                {
                    ribs[k]._firstV.MaxDist = ribs[k]._dist;
                }
            }

            // Вторая проверка, уже с образовавшимися сегментами
            RemoveSmallSegments();
            // MergeSegments();

            ///////////////////////////////////////////////////////////////////////////////
            // Красим сегменты в зависимости от цвета корней
            byte[] mimimi = new byte[_photo.Length];
            int    index  = 0;

            for (int i = 0; i < _height; i++)
            {
                for (int j = 0; j < _width; j++)
                {
                    mimimi[index++] = v2d[i, j].Root._r;
                    mimimi[index++] = v2d[i, j].Root._g;
                    mimimi[index++] = v2d[i, j].Root._b;
                }
            }
            Bitmap end = Filters.GetBitmap(mimimi, _width, _height);

            //////////////////////////////////////////////////////////////////////
            //end = Filters.GrayImage(end);
            //Bitmap zyuzyu = Filters.GetBitmap(_foto, _width, _height);
            //Application.Run(new Form1(zyuzyu, zyu));
            return(end);
            //new Form1(zyuzyu, end).Show();
        }