# 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
(
9323_1-> Picture-> LoadFromFile (FileName);
)
catch (EInvalidGraphic & Exception)
(
AnsiString Error = "Помилка завантаження файлу зображення! Помилка системи:";
Error + = Exception.Message;
MessageBox (this-> Handle, Error.c_str (), "Помилка", MB_OK | MB_ICONERROR);
return false;
)
if (9323_1-> 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 <= 9323_1-> Picture-> Bitmap-> Height - 1; I + +)
(
CurrentLine = (Byte *) 9323_1-> Picture-> Bitmap-> ScanLine [I];
for (J = 0; J <= 9323_1-> Picture-> Bitmap-> Width - 1; J + +)
(
Summ = 0;
if (I> 0)
(
PrevisionLine = (Byte *) 9323_1-> Picture-> Bitmap-> ScanLine [I - 1];
if (J> 0)
(
Summ + = PrevisionLine [J - 1];
)
Summ = Summ + PrevisionLine [J];
if (J + 1 <9323_1-> Picture-> Bitmap-> Width)
(
Summ + = PrevisionLine [J + 1];
)
)
if (J> 0)
(
Summ + = CurrentLine [J - 1];
)
Summ + = CurrentLine [J];
if (J + 1 <9323_1-> Picture-> Bitmap-> Width)
(
Summ + = CurrentLine [J + 1];
)
if (I + 1 <9323_1-> Picture-> Bitmap-> Height)
(
NextLine = (Byte *) 9323_1-> Picture-> Bitmap-> ScanLine [I + 1];
if (J> 0)
(
Summ + = NextLine [J - 1];
)
Summ + = NextLine [J];
if (J + 1 <9323_1-> Picture-> Bitmap-> Width)
(
Summ + = NextLine [J + 1];
)
)
if ((int) (Summ/9) <= Value)
CurrentLine [J] = (Byte) Summ/9;
)
)
9323_1-> Visible = false;
9323_1-> 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-> 9323_1-> Width;
Y = OSRForm-> Height - OSRForm-> 9323_1-> Height;
OSRForm-> 9323_1-> Picture-> Bitmap-> Assign (9323_1-> Picture-> Bitmap);
OSRForm-> Width = OSRForm-> 9323_1-> Width + X;
OSRForm-> Height = OSRForm-> 9323_1-> Height + Y;
OSRForm-> 9323_1-> Canvas-> Rectangle (0, 0, OSRForm-> 9323_1-> Width - 1,
OSRForm-> 9323_1-> Height - 1);
Graphics:: TBitmap * From9323_ = 9323_1-> Picture-> Bitmap;
Graphics:: TBitmap * To9323_ = OSRForm-> 9323_1-> 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 Width; X + +)
(
for (Y = BeginY; 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 = 9323_1-> Picture-> Width;// Сама ліва координата
MaxX = 0;
MaxY = 0;
// Сама верхня точка
TVertex TopPoint;
TopPoint.Y = 9323_1-> 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 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 MaxY = cY;
)
)
break;
// Південь
case South:
(
B = Line [cX];
// Якщо елемент "чорний", повертаємо знову "наліво"
if (B <255)
(
Direct = East;
cX + +;
if (MaxX 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 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 i = 1; i (
To9323_-> Canvas-> LineTo (ShapeVector [i]. X, ShapeVector [i]. Y);
)
for (UINT i = 0; i (
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 i = 0; i (
OutFile < OutFile <)
OutFile.close ();
Symb + +;
)
else
(
if (SkipMode)
(
SkipMode = false;
Symb + +;
)
else if (Symb == 'И')
SkipMode = true;
)
* /
TTemplate * Template = FindTemplate (ShapeVector);
if (Template)
Result + = Template-> Symb;
)
// OSRForm-> Show ();
delete OSRForm;
Memo1-> Text = Result;
)
//--------------------------------------------- ------------------------------
TTemplate * FindTemplate (TShapeVector Vec)
(
TTemplate Template;
Template.Vec = Vec;
for (UINT i = 0; i (
if (Templates [i] == Template)
return & Templates [i];
)
return NULL;
)
//--------------------------------------------- ------------------------------
снапшот програми.
Початок роботи
Вироблено розпізнавання.