Білоруський Державний Університет Інформатики і радіоелектроніки. p>
Контрольна робота з дисципліни p>
«МАТИ» p>
Виконав студент групи 500501 p>
Балахонов Е. В. p>
Алгоритми виділення контурів. p>
Алгоритми виділення контурів можна умовно розбити на дві групи:відстежують і скануючі. p>
1. Відстежують алгоритми на прикладі алгоритму «жука». P>
1 Загальний опис алгоритму. P>
відстежують алгоритми грунтуються на тому, що на зображеннівідшукується об'єкт (перший зустрілася точка об'єкта) і контур об'єктавідстежується і векторізуется. Перевагою даних алгоритмів є їхпростота, до недоліків можна віднести їх послідовну реалізацію тадеяку складність в процесі пошуку та обробки внутрішніх контурів. Прикладвідслідковує алгоритму - "алгоритму жука" - наведено на рис. 5.12. Жукпочинає рух з білою області у напрямку до чорної, Як тільки вінпотрапляє на чорний елемент, він повертає ліворуч і переходить до наступногоелементу. Якщо цей елемент білий, то жук повертається направо, інакше --наліво. Процедура повторюється до тих пір, поки жук не повернеться у вихіднукрапку. Координати точок переходу з чорного на біле і з білого на чорне іописують кордон об'єкта. p>
На рис. 1 показана схема роботи такого алгоритму.
p>
Рис. 1. Схема роботи відслідковує алгоритму «жука». P>
1.2 Створення програми, що реалізує цей алгоритм. P>
Дана програма реалізована в середовищі програмування Borland C + +
Builder 4. P>
Загальний вигляд головного вікна програми у вихідному положенні показаний нарис. 2. P>
p>
Рис. 2. Головне вікно програми у вихідному положенні. P>
Зліва знаходиться вихідне зображення, справа знаходиться зображення наякому будуть малюватися виділяються контури об'єкта. p>
Вихідні тексти форми представлені в лістингу 1. p>
У лістингах 2 і 3 знаходяться вихідні тексти головного модуля програмиі модуля головної форми. p>
У лістингу 4 представлений модуль, що містить в собі функції виділенняконтурів об'єктів. p>
На рис. 3 можна побачити результат роботи алгоритмів виділенняконтурів. p>
p>
Рис. 3. Результат роботи відслідковує алгоритму виділення контурів. P>
2. Скануючі алгоритми. P>
2.2. Загальний опис алгоритму. P>
Скануючі алгоритми грунтуються на перегляді (скануванні)всього зображення і виділення контурних точок без відстеження контуруоб'єкта. p>
Розглянемо алгоритм, заснований на розробленій схемі зберігання смугизображення в пам'яті ЕОМ і знаходження контурних точок у процесі рухусмуги по всьому зображенню. Для обробки інформації в смузі розрізняютьдва випадки: виявлення ситуації у смузі зображення і її вирішення. Усмузі одночасно зберігаються два рядки зображення (поточна і попередня).
Аналізуються Х координати чорних серій обох строк в порядку їхзростання (зліва направо) і виявляються п'ять ситуацій, які можутьвиникнути. p>
Ситуація "початок" виникає в тому випадку, коли чорна серія поточноїрядки повністю покривається білою серією попередньої рядка (рис. 4, а). p>
Для ситуації "продовження" характерно часткове перекриття чорних серійобох строк (рис.4, б). p>
Якщо дві сусідні чорні серії поточного рядка покриваються чорноюсерією попередньої рядки, виникає ситуація "розгалуження" (рис. 4,в). p>
Ситуація "злиття" виявляється в тому випадку, коли чорна серія поточноїрядка стосується двох сусідніх чорних серій попередньої строки (рис.4, г).
Ситуація "кінець" виникає, коли біла серія поточного рядка повністюпокриває чорну серію попередньої строки (рис.4, д). p>
p>
Рис. 4. Ситуації. P>
Оброблювані рядка представлені у вигляді масивів структур, кудивходить координата Х початку/кінця чорної серії та адреса буфера,призначеного для збору та зберігання інформації по одній гілці (частиниконтуру), яка перетинає оброблювану рядок. У буфері містяться типгілки (ліва або права в залежності від розташування чорної серії зв'язковийкомпоненти), її внутрішній номер, параметри відстежені частини контуру
(довжина, площа, габарити) та її координатне опис, адреса буфера парноїгілки, яка є частиною того ж контура і деякі іншіпараметри. p>
При виявленні ситуації "початок" з стека вільних буферів вибирають два
(для лівої і правої гілок). Кожна пара гілок має свій унікальний номер,який зростає в міру появи нових гілок. p>
При виявленні ситуації "продовження" у буфери, адреси якихвибираються з опису верхнього рядка, дописуються координати нових точокі уточнюються геометричні параметри. Одночасно проводитьсяполігональних апроксимація гілок. У разі заповнення буфера метричнийопис відповідної ділянки контуру записується у вихідний файл, а вбуфері зберігається адреса записаного ділянки, що дає можливість зв'язатипосиланнями ділянки одного контура. p>
При виявленні ситуації "розгалуження" точки розгалуження обробляються поаналогії з ситуацією "початок". p>
Ситуація "злиття" виникає тоді, коли закінчено відстеженнявнутрішнього контуру, і коли об'єднуються гілки одного контура. У першувипадку відбувається поєднання інформації обох гілок і запис у вихіднуструктуру. У другому випадку гілка з меншим номером "поглинає" гілку звеликим номером і її пару. Об'єднана інформація зберігається в буферігілки з меншим номером, а в поточному рядку адреса буфера парної гілкизмінюється на адресу буфера, що залишилася, гілки. В обох випадках буфери
"поглиненої" пари звільняються. p>
Ситуація "кінець" свідчить про те. що або закінчилосявідстеження зовнішнього контуру, або зливаються гілки одного контура.
Обробка проводиться за аналогією з обробкою ситуації "злиття". P>
p>
Рис. 6. Результат роботи скануючого алгоритму виділення контурів. P>
У лістингу 4 представлений модуль, що містить в собі функції виділенняконтурів об'єктів. p>
Лістинг 2. Головний модуль програми: p>
//------------------------------------- ---------------------------------< br>----- p>
# include p>
# pragma hdrstop p>
USERES ( "Graphics.res "); p>
USEFORM (" MainUnit.cpp ", Form1); p>
USEUNIT (" GraphicUnit.cpp "); p>
//----------------- -------------------------------------------------- ---
----- p>
WINAPI WinMain (HINSTANCE, HINSTANCE, LPSTR, int) p>
(try p>
( p>
Application-> Initialize (); p>
Application-> CreateForm (__classid (TForm1), & Form1); p>
Application-> Run (); p>
) catch (Exception & exception ) p>
( p>
Application-> ShowException (& exception); p>
) return 0; p>
) p>
//------------------------------------------------ ----------------------< br>----- p>
Лістинг 3. Модуль головної форми p>
Файл заголовка: p>
//---------------------------- ------------------------------------------< br>----- p>
# ifndef MainUnitH p>
# define MainUnitH p>
//---------------- -------------------------------------------------- ----< br>----- p>
# include p>
# include p>
# include p>
# include p>
# include p>
# include p>
//-------------------------------- --------------------------------------< br>----- Class TForm1: public TForm p>
( p>
__published:// IDE-managed Components p>
TPanel * Panel1; p>
TImage * FromImage; p>
TPanel * Panel2; p>
TImage * ToImage; p>
TButton * Button1; void __fastcall Button1Click (TObject * Sender); private:// User declarations public:// User declarations p>
__fastcall TForm1 (TComponent * Owner); p>
); p>
//-------- -------------------------------------------------- ------------< br>----- Extern PACKAGE TForm1 * Form1; p>
//------------------------------ ----------------------------------------< br>----- p>
# endif p>
cpp файл: p>
//----------------- -------------------------------------------------- ---
----- p>
# include p>
# pragma hdrstop p>
# include "MainUnit.h" p>
# include "GraphicUnit. h " p>
//--------------------------------------- -------------------------------< br>----- p>
# pragma package (smart_init) p>
# pragma resource "*. dfm" p>
TForm1 * Form1; p>
//----------------------------------------------- -----------------------< br>----- p>
__fastcall TForm1:: TForm1 (TComponent * Owner) p>
: TForm (Owner) p>
( p>
) p>
//----------------------------------------- -----------------------------< br>----- Void __fastcall TForm1:: Button1Click (TObject * Sender) p>
( p>
AlgorithmBeatle (FromImage-> Picture-> Bitmap, p>
ToImage - > Picture-> Bitmap); p>
ToImage-> Visible = false; p>
ToImage-> Visible = true; p>
) p>
//------------------------------------------------ ----------------------< br>----- p>
Лістинг 4. Модуль виділення контурів. P>
Файл заголовка: p>
//--------------------------- -------------------------------------------< br>----- p>
# ifndef GraphicUnitH p>
# define GraphicUnitH p>
//---------------- -------------------------------------------------- ----< br>----- p>
# include p>
extern void AlgorithmBeatle (Graphics:: TBitmap * FromImage, p>
Graphics:: TBitmap * ToImage); extern void AlgorithmScan (Graphics:: TBitmap * FromImage, p>
Graphics:: TBitmap * ToImage); p>
# endif p>
cpp файл: p>
//------------------------------------------------- ---------------------< br>----- p>
# include p>
# pragma hdrstop p>
# include "GraphicUnit.h" p>
//--- -------------------------------------------------- -----------------< br>----- p>
# pragma package (smart_init) p>
# include p>
/* p>
відслідковує алгоритм виділення контурів p >
"Алгоритм жука" p>
*/ p>
void AlgorithmBeatle (Graphics:: TBitmap * FromImage, p>
Graphics:: TBitmap * ToImage) p>
(typedef enum (North, East, South, West) TDirectional; int X, Y;// Координати першої зустрічі з об'єктом int cX, cY;// Поточні координати маркера p>
Byte * Line, * ToLine;// Оброблювані лінії p>
Byte B;// Значення поточного пікселя p>
TDirectional Direct;// Напрямок руху жука p>
// Йдемо до тих пір, поки не зустрінемо чорну область for (Y = 0; Y Height; Y ++) p> ( p>
Line = (Byte *) FromImage-> ScanLine [Y ]; for (X = 0; X Width; X ++) p> ( p>
B = Line [X]; if (B <255) break; p >
) p>
// Якщо зустрінутий об'єкт, що відрізняється від кольору тла (255 - білий) p>
// перервати пошук if (X! = FromImage-> Width) break; p>
) p>
// Якщо не знайшли жодного чорного піксела, то виходимо із процедури if ((X == FromImage-> Width) & & (Y == FromImage-> Height) ) return; p>
// Якщо все нормально, починаємо обхід за алгоритмом жука p>
ToLine = (Byte *) ToImage-> ScanLine [Y]; p>
ToLine [X] = 0; p>
// Звертаємо ліворуч (новий напрямок - північ) cX = X; cY = Y - 1; p>
Direct = North; p>
Line = (Byte *) FromImage-> ScanLine [cY]; p>
// Ще не прийдемо у вихідну точку, виділяємо контур об'єкта while ((cX! = X) | | (cY! = Y) ) p>
( p>
// В залежності від поточного напрямку руху жука switch (Direct) p>
( p>
// Північ case North: p>
( p>
B = Line [cX]; p>
// Якщо елемент "чорний", повертаємо знову "наліво" if (B <255) p>
( p>
ToLine = (Byte *) ToImage-> ScanLine [cY]; p>
ToLine [cX] = 0; p>
Direct = West; cX -; p>
) p>
// Інакше повертаємо "направо" else p>
( p>
Direct = East; cX + +; p>
) p>
) break; p>
// Схід case East: p>
( p>
B = Line [ cX]; p>
// Якщо елемент "чорний", повертаємо знову "наліво" if (B <255) p>
( p>
ToLine = (Byte *) ToImage-> ScanLine [cY]; p>
ToLine [cX] = 0; p>
Direct = North; cY -; p>
Line = (Byte *) FromImage-> ScanLine [cY]; p>
) p>
// Інакше повертаємо "направо" else p>
( p>
Direct = South; cY ++; p>
Line = (Byte *) FromImage-> ScanLine [cY]; p>
) p>
) break; p>
// Південь case South: p>
( p>
B = Line [cX]; p>
// Якщо елемент "чорний", повертаємо знову "наліво" if (B < 255) p>
( p>
ToLine = (Byte *) ToImage-> ScanLine [cY]; p>
ToLine [cX] = 0; p> < p> Direct = East; cX ++; p>
) p>
// Інакше повертаємо "направо" else p>
( p>
Direct = West; cX -; p>
) p>
) break; p>
// Захід case West: p>
( p>
B = Line [cX]; p>
// Якщо елемент "чорний", повертаємо знову "наліво" if (B <255) p>
( p>
ToLine = (Byte *) ToImage-> ScanLine [cY]; p>
ToLine [cX] = 0; p>
Direct = South; cY ++; p>
Line = (Byte *) FromImage-> ScanLine [cY]; p>
) p>
// Інакше повертаємо "направо" else p>
( p>
Direct = North; cY -; p>
Line = (Byte *) FromImage-> ScanLine [cY]; p>
) p>
) p>
) p>
) p>
) p>
// ------------------------ ---------------------------------------------< br>------ p>
void AlgorithmScan (Graphics:: TBitmap * FromImage, p>
Graphics:: TBitmap * ToImage) p>
( p> < p>// Тип гілки (ліва або права) typedef enum (bLeft, bRight) TBranchType; p>
// Структура, що описує гілку struct TBranch p>
( p>
TBranchType BranchType;// Тип гілки p>
TBranch * Branch;// Парна гілку p>
); p>
// Структура, що описує рядок struct TString p>
(int BeginX;// Початок чорної серії int EndX;// Кінець чорної серії p>
TBranch * Branch;// Покажчик на структуру гілки p>
); p>
// Можливі ситуації typedef enum (sBegin,// Початок sNext,// Продовження sBranch,// Галуження sFusion,// Злиття sEnd// Кінець p>
) TSituation; p>
// сканується смуга struct TLine p>
( p>
Byte * L1;// Верхня лінія p>
Byte * L2;// Нижня лінія p> < p>); p>
int Y;// Поточна координата Y int X;// Поточна координата X int cX;// Тимчасова координата X для сканування p>
TLine Line;// сканується смуга p>
TSituation CurrentSituation;// Поточна ситуація p>
for (Y = 0; Y Height; Y ++) p> ( p> < p> Line.L1 = (Byte *) FromImage-> ScanLine [Y]; p>
Y ++; p>
Line.L2 = (Byte *) FromImage-> ScanLine [Y]; p>
// Пробуємо виявити ситуації: p>
// Шукаємо перший чорний елемент у другій лінії сканується смуги for (X = 0; X Width; X ++) p> (if (Line.L2 [X] <255) p>
( p>
// Якщо чорний елемент знайдений, намагаємося уточнити ситуацію p>
CurrentSituation = sBegin ; for (cX = X; cX Width; cX ++) p> ( p>
) p>
) p>
) p>
) p>
) p>
p>