Программа розпізнавання символов

Тип работы:
Реферат
Предмет:
Информатика, программирование


Узнать стоимость

Детальная информация о работе

Выдержка из работы

Программа розпізнавання символів

Написать програму, здатну розпізнавати графічно представлені символи як растрового зображення перетворювати на звичайний текст.

платформа: Win32,

формат графічного зображення: Windows Bitmap (BMP), 8 біт,

шрифт для розпізнавання: Arial, 16

Этап 1. Виділення контуру об'єкта, визначення її кордонів.

В ролі алгоритму виділення контурів використовуватимемо алгоритм жука.

Общее опис алгоритму.

Отслеживающие алгоритми засновані у тому, що у зображенні відшукується об'єкт (перша яка зустрілася точка об'єкта) і контур об'єкта відстежується і векторизуется. Перевагою даних алгоритмів був частиною їхнього простота, до недоліків можна віднести їх не послідовну реалізацію й певну складність у пошуку та їх обробки внутрішніх контурів. Приклад відстежує алгоритму — «алгоритму жука «- наведено на рис. 5. 12. Жук починає рух із білою області з до чорної, Як він потрапляє про чорний елемент, він повертає ліворуч кермо і переходить ось до чого елементу. Якщо це елемент білий, то жук повертається направо, інакше — наліво. Процедура повторюється до того часу, поки жук не повернеться вихідну точку. Координати точок переходу з чорного на біле і з білого на чорне й описують кордон об'єкта.

На рис. 1 показано схема роботи такого алгоритму.

Рис. 1. Схема роботи відстежує алгоритму «жука».

Этап 2. Побудова з урахуванням контуру об'єкта скелетної лінії.

При перебування нової точки контуру, розраховується відстань між попередньої знайденою точкою та поглибленні нової. Якщо він перевищує деяку кордон (за умовчанням в розмірі 5 одиниць), вона запам’ятовується. Наприкінці побудови скелетної лінії програма має масив координат вершин ламаної, що є скелетної лінією об'єкта.

Этап 3. Порівняння отриманої кістякової лінії з списком шаблонів.

После побудови скелетної лінії виробляється порівняння її з списком шаблонів відомих символів. При перебування збіги, програма записує в рядок знайдений символ.

Исходный текст програми.

//---------------------------------------------------------------------------

#include

#pragma hdrstop

#include

#include

#include «ChildFormUnit.h «

#include «MainFormUnit.h «

#include «AverageFilterDialogFormUnit.h «

#include «OSRFormUnit.h «

//---------------------------------------------------------------------------

#pragma package (smart_init)

#pragma resource «*. dfm «

TChildForm *ChildForm;

TTemplates Templates;

//---------------------------------------------------------------------------

__fastcall TChildForm: :TChildForm (TComponent* Owner)

: TForm (Owner)

{

}

//---------------------------------------------------------------------------

bool __fastcall TChildForm: :Load9323_(AnsiString FileName)

{

try

{

93231-> Picture->LoadFromFile (FileName);

}

catch (EInvalidGraphic& Exception)

{

AnsiString Error = «Помилка завантаження файла зображення! Помилка системи: »;

Error += Exception. Message;

MessageBox (this-> Handle, Error. c_str (), «Помилка », MB_OK | MB_ICONERROR);

return false;

}

if (93231-> Picture->Bitmap->PixelFormat ≠ pf8bit)

{

MessageBox (Handle, «Такий формат файла доки подерживается… » ,

" Слабенький поки що… ", MB_OK | MB_ICONSTOP | MB_APPLMODAL);

return false;

}

return true;

}

//---------------------------------------------------------------------------

void __fastcall TChildForm: :FormClose (TObject *Sender,

TCloseAction & Action)

{

MainForm-> DeleteActiveChildForm ();

}

//---------------------------------------------------------------------------

void __fastcall TChildForm: :AverageFilter ()

{

AverageFilterDialogForm = new TAverageFilterDialogForm (this);

if (AverageFilterDialogForm-> ShowModal () == mrCancel)

{

delete AverageFilterDialogForm;

return;

}

int Value = atoi (AverageFilterDialogForm-> Edit1->Text. c_str ());

delete AverageFilterDialogForm;

Byte* PrevisionLine = NULL;

Byte* CurrentLine = NULL;

Byte* NextLine = NULL;

int I = 0, J = 0;

int Summ = 0;

for (I = 0; I Picture-> Bitmap->Height — 1; I++)

{

CurrentLine = (Byte*)93231-> Picture->Bitmap->ScanLine[I];

for (J = 0; J Picture-> Bitmap->Width — 1; J++)

{

Summ = 0;

if (I > 0)

{

PrevisionLine = (Byte*)93231-> Picture->Bitmap->ScanLine[I — 1];

if (J > 0)

{

Summ += PrevisionLine[J — 1];

}

Summ = Summ + PrevisionLine[J];

if (J + 1 < 93231-> Picture->Bitmap->Width)

{

Summ += PrevisionLine[J + 1];

}

}

if (J > 0)

{

Summ += CurrentLine[J — 1];

}

Summ += CurrentLine[J];

if (J + 1 < 93231-> Picture->Bitmap->Width)

{

Summ += CurrentLine[J + 1];

}

if (I + 1 < 93231-> Picture->Bitmap->Height)

{

NextLine = (Byte*)93231-> Picture->Bitmap->ScanLine[I + 1];

if (J > 0)

{

Summ += NextLine[J — 1];

}

Summ += NextLine[J];

if (J + 1 < 93231-> Picture->Bitmap->Width)

{

Summ += NextLine[J + 1];

}

}

if ((int)(Summ / 9) Visible = false;

93231-> Visible = true;

}

//---------------------------------------------------------------------------

// Відстань між двома точками

int Distance (TVertex& V1, TVertex& V2)

{

int a = abs (V1.Y — V2. Y);

int b = abs (V1.X — V2. X);

return sqrt (a*a + b*b);

}

//---------------------------------------------------------------------------

void __fastcall TChildForm: :OSR ()

{

// Граничне відстань для простроения спрощеної постаті

const int Treshold = 5;

// Сюди зберігається результат распознования

AnsiString Result;

// Отладочная форма із зображенням до роботи

OSRForm = new TOSRForm (this);

// Напрями руху жука

typedef enum {North, East, South, West} TDirectional;

TDirectional Direct;

// Координати першої зустрічі з поточним об'єктом

int X, Y;

// Тимчасово їх використовуємо для завдання нового розміру робочого зображення

X = OSRForm-> Width — OSRForm-> 93231->Width;

Y = OSRForm-> Height — OSRForm-> 93231->Height;

OSRForm-> 93231->Picture->Bitmap->Assign (93231->Picture->Bitmap);

OSRForm-> Width = OSRForm-> 93231->Width + X;

OSRForm-> Height = OSRForm-> 93231->Height + Y;

OSRForm-> 93231->Canvas->Rectangle (0, 0, OSRForm-> 93231->Width — 1,

OSRForm-> 93231->Height — 1);

Graphics: :TBitmap* From9323_ = 93231-> Picture->Bitmap;

Graphics: :TBitmap* To9323_ = OSRForm-> 93231->Picture->Bitmap;

// Поточні координати маркера

int cX, cY;

// Максимальні координати, що займає постать

int MaxX = 0;

int MaxY = From9323_-> Height;

// З цієї координати починається нове сканування по Y

int BeginY = 0;

// Оброблювані лінії

Byte *Line, *ToLine;

char Symb = «А »;

// Поточний байт

Byte B = 0;

bool SkipMode = false;

while (true)

{

// Список координат поточного об'єкта

TShapeVector ShapeVector;

// Тимчасова структура координат точки

TVertex Vertex;

// Пошук будь-якого об'єкта

// Йдемо до того часу, доки зустрінемо чорну область

for (X = MaxX; X < From9323_-> Width; X++)

{

for (Y = BeginY; Y < MaxY; Y++)

{

Line = (Byte*)From9323_-> ScanLine[Y];

if (Line[X] < 255)

goto FindedLabel;

}

if ((X + 1 == From9323_-> Width) && (Y == From9323_-> Height))

{

X++;

goto FindedLabel;

}

// Якщо пройшли впритул до правого краю, розширюємо кордону пошуку до низу

if (X + 1 == From9323_-> Width)

{

X = 0;

MaxX = 0;

BeginY = MaxY;

MaxY = From9323_-> Height;

}

}

FindedLabel:

// Якщо знайшли жодної чорної пиксела, то виходимо з процедури

if ((X == From9323_-> Width) && (Y == From9323_-> Height))

break;

// Спочатку завдання знайти максимальні кордону виявленої постаті,

// щоб тоді з неї починати будувати скелет

// Також шукаємо саму верхню точку постаті, спершу побудови

int MinX = 93231-> Picture->Width; // Найбільш ліва координата

MaxX = 0;

MaxY = 0;

// Найбільш верхня точка

TVertex TopPoint;

TopPoint.Y = 93231-> Picture->Height;

// Повертаємо наліво (новий напрям — північ)

cX = X;

cY = Y — 1;

Direct = North;

Line = (Byte*)From9323_-> ScanLine[cY];

// Поки що прийдемо в вихідну точку, виділяємо контур об'єкта

while ((cX ≠ X) || (cY ≠ Y))

{

// Залежно від того плинного напрями руху жука

switch (Direct)

{

// Північ

case North:

{

B = Line[cX];

// Якщо елемент «чорний », повертаємо знову «наліво «

if (B < 255)

{

Direct = West;

cX--;

// Може це найбільш ліва координата?

if (MinX > cX)

MinX = cX;

}

// Інакше повертаємо «направо «

else

{

Direct = East;

cX++;

if (MaxX < cX)

MaxX = cX;

}

}

break;

// Схід

case East:

{

B = Line[cX];

// Якщо елемент «чорний », повертаємо знову «наліво «

if (B < 255)

{

Direct = North;

cY--;

Line = (Byte*)From9323_-> ScanLine[cY];

// Може це найбільш верхня точка?

if (TopPoint.Y > cY)

{

TopPoint.Y = cY;

TopPoint.X = cX;

}

}

// Інакше повертаємо «направо «

else

{

Direct = South;

cY++;

Line = (Byte*)From9323_-> ScanLine[cY];

if (MaxY < cY)

MaxY = cY;

}

}

break;

// Південь

case South:

{

B = Line[cX];

// Якщо елемент «чорний », повертаємо знову «наліво «

if (B < 255)

{

Direct = East;

cX++;

if (MaxX < cX)

MaxX = cX;

}

// Інакше повертаємо «направо «

else

{

Direct = West;

cX--;

// Може це найбільш ліва координата?

if (MinX > cX)

MinX = cX;

}

}

break;

// Захід

case West:

{

B = Line[cX];

// Якщо елемент «чорний », повертаємо знову «наліво «

if (B < 255)

{

Direct = South;

cY++;

Line = (Byte*)From9323_-> ScanLine[cY];

if (MaxY < cY)

MaxY = cY;

}

// Інакше повертаємо «направо «

else

{

Direct = North;

cY--;

Line = (Byte*)From9323_-> ScanLine[cY];

// Може це найбільш верхня точка?

if (TopPoint.Y > cY)

{

TopPoint.Y = cY;

TopPoint.X = cX;

}

}

}

}

}

TopPoint. X++;

if ((!TopPoint. X) && (!TopPoint. Y))

{

TopPoint.X = X;

TopPoint.Y = Y;

}

else

{

X = TopPoint. X;

Y = TopPoint. Y;

}

// Будівництво скелета

ToLine = (Byte*)To9323_-> ScanLine[Y];

ToLine[X] = 0;

// Повертаємо наліво (новий напрям — південь)

cX = X;

cY = Y;

Vertex.X = X;

Vertex.Y = Y;

ShapeVector. push_back (Vertex);

Direct = East;

Line = (Byte*)From9323_-> ScanLine[cY];

// Поки що прийдемо в вихідну точку, виділяємо контур об'єкта

do

{

// Залежно від того плинного напрями руху жука

switch (Direct)

{

// Північ

case North:

{

B = Line[cX];

// Якщо елемент «чорний », повертаємо знову «наліво «

if (B < 255)

{

ToLine = (Byte*)To9323_-> ScanLine[cY];

ToLine[cX] = 0;

Vertex.X = cX;

Vertex.Y = cY;

if (Distance (Vertex, ShapeVector[ShapeVector. size () — 1]) >= Treshold)

ShapeVector. push_back (Vertex);

Direct = West;

cX--;

}

// Інакше повертаємо «направо «

else

{

Direct = East;

cX++;

}

}

break;

// Схід

case East:

{

B = Line[cX];

// Якщо елемент «чорний », повертаємо знову «наліво «

if (B < 255)

{

ToLine = (Byte*)To9323_-> ScanLine[cY];

ToLine[cX] = 0;

Vertex.X = cX;

Vertex.Y = cY;

if (Distance (Vertex, ShapeVector[ShapeVector. size () — 1]) >= Treshold)

ShapeVector. push_back (Vertex);

Direct = North;

cY--;

Line = (Byte*)From9323_-> ScanLine[cY];

}

// Інакше повертаємо «направо «

else

{

Direct = South;

cY++;

Line = (Byte*)From9323_-> ScanLine[cY];

}

}

break;

// Південь

case South:

{

B = Line[cX];

// Якщо елемент «чорний », повертаємо знову «наліво «

if (B < 255)

{

ToLine = (Byte*)To9323_-> ScanLine[cY];

ToLine[cX] = 0;

Vertex.X = cX;

Vertex.Y = cY;

if (Distance (Vertex, ShapeVector[ShapeVector. size () — 1]) >= Treshold)

ShapeVector. push_back (Vertex);

Direct = East;

cX++;

}

// Інакше повертаємо «направо «

else

{

Direct = West;

cX--;

}

}

break;

// Захід

case West:

{

B = Line[cX];

// Якщо елемент «чорний », повертаємо знову «наліво «

if (B < 255)

{

ToLine = (Byte*)To9323_-> ScanLine[cY];

ToLine[cX] = 0;

Vertex.X = cX;

Vertex.Y = cY;

if (Distance (Vertex, ShapeVector[ShapeVector. size () — 1]) >= Treshold)

ShapeVector. push_back (Vertex);

Direct = South;

cY++;

Line = (Byte*)From9323_-> ScanLine[cY];

}

// Інакше повертаємо «направо «

else

{

Direct = North;

cY--;

Line = (Byte*)From9323_-> ScanLine[cY];

}

}

}

} while ((cX ≠ X) || (cY ≠ Y));

Vertex.X = X;

Vertex.Y = Y;

ShapeVector. push_back (Vertex);

To9323_-> Canvas->Pen->Color = clRed;

To9323_-> Canvas->MoveTo (ShapeVector[0]. X, ShapeVector[0]. Y);

for (UINT і = 1; і < ShapeVector. size (); і++)

{

To9323_-> Canvas->LineTo (ShapeVector[i]. X, ShapeVector[i]. Y);

}

for (UINT і = 0; і < ShapeVector. size (); і++)

{

ShapeVector[i].X -= MinX;

ShapeVector[i].Y -= Y;

}

/*

if (Symb == «Й »)

{

Symb++;

}

if (Symb == «а »)

{

// Symb = «A »;

break;

}

if ((Symb ≠ «И ») && (!SkipMode))

{

AnsiString FileName = ExtractFilePath (Application-> ExeName) + «TPL »;

FileName += Symb;

ofstream OutFile (FileName. c_str ());

for (UINT і = 0; і < ShapeVector. size (); і++)

{

OutFile

ПоказатьСвернуть
Заполнить форму текущей работой