Алгоритмы выделения контуровРефераты >> Программирование и компьютеры >> Алгоритмы выделения контуров
Файл заголовка:
//---------------------------------------------------------------------------
#ifndef MainUnitH
#define MainUnitH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <ExtCtrls.hpp>
#include <Graphics.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
published: // IDE-managed Components
TPanel *Panel1;
TImage *FromImage;
TPanel *Panel2;
TImage *ToImage;
TButton *Button1;
void fastcall Button1Click(TObject *Sender);
private: // User declarations
public: // User declarations
fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
cpp файл:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "MainUnit.h"
#include "GraphicUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void fastcall TForm1::Button1Click(TObject *Sender)
{
AlgorithBeatle(FromImage->Picture->Bitmap,
ToImage->Picture->Bitmap);
ToImage->Visible = false;
ToImage->Visible = true;
}
//---------------------------------------------------------------------------
Листинг 4. Модуль выделения контуров.
Файл заголовка:
//---------------------------------------------------------------------------
#ifndef GraphicUnitH
#define GraphicUnitH
//---------------------------------------------------------------------------
#include <Graphics.hpp>
extern void AlgorithBeatle(Graphics::TBitmap* FromImage,
Graphics::TBitmap* ToImage);
extern void AlgorithScan(Graphics::TBitmap* FromImage,
Graphics::TBitmap* ToImage);
#endif
cpp файл:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include "GraphicUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#include <Sysutils.hpp>
/*
Отслеживающий алгоритм выделения контуров
"Алгоритм жука"
*/
void AlgorithBeatle(Graphics::TBitmap* FromImage,
Graphics::TBitmap* ToImage)
{
typedef enum {North, East, South, West} TDirectional;
int X,Y; // Координаты первой встречи с объектом
int cX,cY; // Текущие координаты маркера
Byte *Line, *ToLine; // Обрабатываемые линии
Byte B; // Значение текущего пиксела
TDirectional Direct; // Направление движения жука
// Идем до тех пор, пока не встретим черную область
for (Y = 0; Y < FromImage->Height; Y++)
{
Line = (Byte*)FromImage->ScanLine[Y];
for (X = 0; X < FromImage->Width; X++)
{
B = Line[X];
if (B < 255)
break;
}
// Если встречен объект, отличающийся от цвета фона (255 - белый)
// прервать поиск
if (X != FromImage->Width)
break;
}
// Если не нашли ни одного черного пиксела, то выходим из процедуры
if ((X == FromImage->Width) && (Y == FromImage->Height))
return;
// Если все нормально, начинаем обход по алгоритму жука
ToLine = (Byte*)ToImage->ScanLine[Y];
ToLine[X] = 0;
// Поворачиваем налево (новое направление - север)
cX = X;
cY = Y - 1;
Direct = North;
Line = (Byte*)FromImage->ScanLine[cY];
// Пока не придем в исходную точку, выделяем контур объекта
while ((cX != X) || (cY != Y))
{
// В зависимости от текущего направления движения жука
switch (Direct)
{
// Север
case North:
{
B = Line[cX];
// Если элемент "черный", поворачиваем снова "налево"
if (B < 255)
{
ToLine = (Byte*)ToImage->ScanLine[cY];
ToLine[cX] = 0;
Direct = West;
cX--;
}
// Иначе поворачиваем "направо"
else
{
Direct = East;
cX++;
}
}
break;
// Восток
case East:
{
B = Line[cX];
// Если элемент "черный", поворачиваем снова "налево"
if (B < 255)
{
ToLine = (Byte*)ToImage->ScanLine[cY];
ToLine[cX] = 0;
Direct = North;
cY--;
Line = (Byte*)FromImage->ScanLine[cY];
}
// Иначе поворачиваем "направо"
else
{
Direct = South;
cY++;
Line = (Byte*)FromImage->ScanLine[cY];
}
}
break;
// Юг
case South:
{
B = Line[cX];
// Если элемент "черный", поворачиваем снова "налево"
if (B < 255)
{
ToLine = (Byte*)ToImage->ScanLine[cY];
ToLine[cX] = 0;
Direct = East;
cX++;
}
// Иначе поворачиваем "направо"
else
{
Direct = West;
cX--;
}
}
break;
// Запад
case West:
{
B = Line[cX];
// Если элемент "черный", поворачиваем снова "налево"
if (B < 255)
{
ToLine = (Byte*)ToImage->ScanLine[cY];
ToLine[cX] = 0;
Direct = South;
cY++;
Line = (Byte*)FromImage->ScanLine[cY];
}
// Иначе поворачиваем "направо"
else
{
Direct = North;
cY--;
Line = (Byte*)FromImage->ScanLine[cY];
}
}
}
}
}
// ---------------------------------------------------------------------------
void AlgorithScan(Graphics::TBitmap* FromImage,
Graphics::TBitmap* ToImage)
{
// Тип ветви (левая или правая)
typedef enum {bLeft, bRight} TBranchType;
// Структура, описывающая ветвь
struct TBranch
{
TBranchType BranchType; // Тип ветви
TBranch* Branch; // Парная ветвь
};
// Структура, описывающая строку
struct TString
{
int BeginX; // Начало черной серии
int EndX; // Конец черной серии
TBranch* Branch; // Указатель на структуру ветви
};
// Возможные ситуации
typedef enum {
sBegin, // Начало
sNext, // Продолжение
sBranch, // Ветвление
sFusion, // Слияние
sEnd // Конец
} TSituation;
// Сканируемая полоса
struct TLine
{
Byte* L1; // Верхняя линия