Re[3]: Алгоритм утоньшения изображения
От: Were  
Дата: 11.08.08 22:53
Оценка:
Здравствуйте, xmlx, Вы писали:

X>Здравствуйте, Were, Вы писали:


W>>Здравствуйте, xmlx, Вы писали:


X>>>Как сделать алгоритм, который приведёт к утоньшения этой буквы L, к

X>>>такому виду, что у любой "1" было только две или только одна соседняя "1"

W>>Topological skeleton

W>>Внизу есть ссылки на алгоритмы.

X>я всё это прочитал. к сожалению, это не то что нужно.

X>у меня скелетонизация выполняется в два этапа. на первом — distance transform, вот после первого этапа получается изображение с "переменной толшиной" от 1 до 2 пикселей и нужно сделать заключительное утоньшение, оставив связное изображение толщиной точно в 1 пиксел. Я уже сделал такой алгоритм и он прекрасно работает, но мне он не совсем нравится, он не оптимальный. Может есть какие-то более "умные варианты"?

Я как-то делал скелетонизацию, но посеял pdf с алгоритмом (может позже найду). Остался только код:

void Skeletize()
{
    int x, y,
        n[8], 
        A, B,
        subiter = 0;

    bool bFound, bFound1 = true, bFound2 = true;

    while( bFound1 || bFound2 )
    {
        for ( y = 0; y < m_Height; y++ )
        {
            for ( x = 0; x < m_Width; x++ )
            {   
                if ( !At( x, y ))
                    continue;

                n[0] = At( x, y - 1 );
                n[1] = At( x + 1, y - 1 );
                n[2] = At( x + 1, y);
                n[3] = At( x + 1, y + 1 );
                n[4] = At( x, y + 1 );
                n[5] = At( x - 1, y + 1 );
                n[6] = At( x - 1, y );
                n[7] = At( x - 1, y - 1 );

                B = 0 != n[0];
                B += 0 != n[1];
                B += 0 != n[2];
                B += 0 != n[3];
                B += 0 != n[4];
                B += 0 != n[5];
                B += 0 != n[6];
                B += 0 != n[7];
            
                if ( B < 2 || B > 6 )
                    continue;

                A = !n[0] && n[1];
                A += !n[1] && n[2];
                A += !n[2] && n[3];
                A += !n[3] && n[4];
                A += !n[4] && n[5];
                A += !n[5] && n[6];
                A += !n[6] && n[7];
                A += !n[7] && n[0];
            
                if ( A != 1 )
                    continue;

                if ( subiter == 0 &&
                    ( n[0] && n[2] && n[4] ||
                    n[2] && n[4] && n[6] ))
                    continue;

                if ( subiter == 1 &&
                    ( n[0] && n[2] && n[6] ||
                    n[0] && n[4] && n[6] ))
                    continue;

                At( x, y ) = 2;
            }
        }

        bFound = false;

        for ( y = 0; y < m_Height; y++ )
        {
            for ( x = 0; x < m_Width; x++ )
            {
                int &v = At( x, y );

                if ( v == 2 ) 
                {
                    bFound = true;
                    v = 0;
                }
            }
        }

        if ( subiter == 0 )
            bFound1 = bFound;
        else
            bFound2 = bFound;


        subiter = !subiter;
    }

}


Небольшой комментарий:
Skeletize() — метод класса бинарного поля.
m_Height, m_Width — ширина и длина поля.
At() — метод, возвращающий ссылку на элемент поля. Если координаты вне поля, то ссылку на временный элемент.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.