Реферат по предмету "Информатика, программирование"


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

Белорусский Государственный Университет Информатики и
Радиоэлектроники.





































Контрольная работа



по дисциплине



«МАГИ»





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





































Выполнил студент группы
500501



Балахонов Е.В.



Задание.





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



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



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



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







Выбор средств разработки.





В качестве среды разработки будет использоваться Borland C++ Builder 5.





Распознавание символов.





Этап 1. Выделение контура объекта, определение его границ.





В качестве алгоритма выделения контуров будем
использовать алгоритм жука.



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





Отслеживающие
алгоритмы
основаны на том, что
на изображении отыскивается объект (первая встретившаяся точка объекта) и
контур объекта отслеживается и векторизуется. Достоинством данных алгоритмов
является их простота, к недостаткам можно отнести их последовательную
реализацию и некоторую сложность при поиске и обработке внутренних контуров.
Пример отслеживающего алгоритма - "алгоритма жука" - приведен на рис.
5.12. Жук начинает движение с белой области по направлению к черной, Как только
он попадает на черный элемент, он поворачивает налево и переходит к следующему
элементу. Если этот элемент белый, то жук поворачивается направо, иначе -
налево. Процедура повторяет­ся до тех пор, пока жук не вернется в исходную
точку. Координаты точек перехода с черного на белое и с белого на черное и
описывают границу объекта.



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





Рис. 1. Схема работы
отслеживающего алгоритма «жука».







Этап 2. Построение на основе контура объекта скелетной линии.





            При нахождении новой точки контура,
рассчитывается расстояние между предыдущей найденной точкой и новой. Если оно
превышает некоторую границу (по умолчанию в 5 единиц),  она запоминается. К
концу построения скелетной линии программа имеет массив координат вершин
ломаной, которая является скелетной линией объекта.





Этап 3. Сравнение полученной скелетной линии с списком шаблонов.





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











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





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





#include <vcl.h>



#pragma hdrstop





#include <math.h>



#include <fstream.h>





#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::LoadImage(AnsiString FileName)



{



 try



 {



 
Image1->Picture->LoadFromFile(FileName);



 }



 catch (EInvalidGraphic& Exception)



 {



  AnsiString Error = "Ошибка
загрузки файла изображения! Ошибка системы: ";



  Error += Exception.Message;



  MessageBox(this->Handle,
Error.c_str(), "Ошибка", MB_OK |
MB_ICONERROR);



  return false;



 }





 if
(Image1->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 <=
Image1->Picture->Bitmap->Height - 1; I++)



 {



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



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



  {



   Summ = 0;





   if (I > 0)



   {



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



    if (J > 0)



    {



     Summ += PrevisionLine[J - 1];



    }





    Summ = Summ + PrevisionLine[J];





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



    {



     Summ += PrevisionLine[J + 1];



    }



   }





   if (J > 0)



   {



    Summ += CurrentLine[J - 1];



   }





   Summ += CurrentLine[J];





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



   {



    Summ += CurrentLine[J + 1];



   }





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



   {



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



    if (J > 0)



    {



     Summ += NextLine[J - 1];



    }





    Summ += NextLine[J];





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



    {



     Summ += NextLine[J + 1];



    }



   }





   if ((int)(Summ / 9) <= Value)



    CurrentLine[J] = (Byte) Summ / 9;



  }



 }



 Image1->Visible = false;



 Image1->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->Image1->Width;



 Y = OSRForm->Height -
OSRForm->Image1->Height;



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



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



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



 OSRForm->Image1->Canvas->Rectangle(0,
0, OSRForm->Image1->Width - 1,



                                    OSRForm->Image1->Height
- 1);





 Graphics::TBitmap* FromImage =
Image1->Picture->Bitmap;



 Graphics::TBitmap* ToImage =
OSRForm->Image1->Picture->Bitmap;





 // Текущие координаты маркера



 int cX,cY;





 // Максимальные координаты,
которые занимает фигура



 int MaxX = 0;



 int MaxY = FromImage->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 <
FromImage->Width; X++)



  {



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



   {



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



    if (Line[X] < 255)



     goto FindedLabel;



   }





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



   {



    X++;



    goto FindedLabel;



   }





   // Если прошли до самого правого края, расширяем
границы поиска до низа



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



   {



    X = 0;





    MaxX = 0;



    BeginY = MaxY;



    MaxY = FromImage->Height;



   }





  }



FindedLabel:





  // Если не нашли ни одного черного пиксела, то выходим
из процедуры



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



   break;





  // Сначала задача найти максимальные границы
обнаруженной фигуры,



  // чтобы потом от нее начинать строить скелет



  // Также ищем самую верхнюю точку фигуры, для начала
построения



  int MinX =
Image1->Picture->Width;  // Самая левая координата





  MaxX = 0;



  MaxY = 0;





  // Самая верхняя точка



  TVertex TopPoint;



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





  // Поворачиваем налево (новое
направление - север)



  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)



     {



      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*)FromImage->ScanLine[cY];



      // Может это самая верхняя
точка?



      if (TopPoint.Y > cY)



      {



       TopPoint.Y = cY;



       TopPoint.X = cX;



      }



     }



     // Иначе поворачиваем "направо"



     else



     {





      Direct = South;



      cY++;



      Line =
(Byte*)FromImage->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*)FromImage->ScanLine[cY];



      if (MaxY < cY)



       MaxY = cY;



     }



     // Иначе поворачиваем "направо"



     else



     {



      Direct = North;



      cY--;



      Line =
(Byte*)FromImage->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*)ToImage->ScanLine[Y];



  ToLine[X] = 0;





  // Поворачиваем налево (новое направление - юг)



  cX = X;



  cY = Y;





  Vertex.X = X;



  Vertex.Y = Y;



  ShapeVector.push_back(Vertex);





  Direct = East;



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





  // Пока не придем в исходную
точку, выделяем контур объекта



  do



  {



   // В зависимости от текущего направления движения жука



   switch (Direct)





   {



     // Север



    case North:



    {



     B = Line[cX];



     // Если элемент
"черный", поворачиваем снова "налево"



     if (B < 255)



     {



      ToLine =
(Byte*)ToImage->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*)ToImage->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*)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;





      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*)ToImage->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*)FromImage->ScanLine[cY];



     }



     // Иначе поворачиваем "направо"



     else



     {



      Direct = North;



      cY--;



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



     }



    }



   }



  } while ((cX != X) || (cY != Y));





  Vertex.X = X;



  Vertex.Y = Y;



  ShapeVector.push_back(Vertex);





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



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



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



  {



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



  }





  for (UINT i = 0; i < ShapeVector.size();
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 <
ShapeVector.size(); i++)



   {



    OutFile <<
IntToStr(ShapeVector[i].X).c_str() << endl;



    OutFile <<
IntToStr(ShapeVector[i].Y).c_str() << endl;



   }



   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 <
Templates.size(); i++)



 {



  if (Templates[i] == Template)



   return &Templates[i];



 }





 return NULL;



}



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





Снапшоты программы.





Начало работы











































Произведено
распознавание.







Не сдавайте скачаную работу преподавателю!
Данный реферат Вы можете использовать для подготовки курсовых проектов.

Поделись с друзьями, за репост + 100 мильонов к студенческой карме :

Пишем реферат самостоятельно:
! Как писать рефераты
Практические рекомендации по написанию студенческих рефератов.
! План реферата Краткий список разделов, отражающий структура и порядок работы над будующим рефератом.
! Введение реферата Вводная часть работы, в которой отражается цель и обозначается список задач.
! Заключение реферата В заключении подводятся итоги, описывается была ли достигнута поставленная цель, каковы результаты.
! Оформление рефератов Методические рекомендации по грамотному оформлению работы по ГОСТ.

Читайте также:
Виды рефератов Какими бывают рефераты по своему назначению и структуре.

Сейчас смотрят :

Реферат Экспертизы декоративной косметики на примере лака для ногтей
Реферат Анализ структуры ассортимента безалкогольных газированных напитков
Реферат Vii дороги, которые рок выбирает судьба и рок а. Козлова
Реферат "Давний союз" 1295-1560 годов между Шотландией и Францией и его культурологические последствия
Реферат Аннотация рабочей программы дисциплины «Дифракционный структурный анализ» Направление подготовки 011200 «Физика»
Реферат Приватизация земли и ее социально-экономические последствия
Реферат Plato On Justice Essay Research Paper J
Реферат Авраам (урок первый)
Реферат Австралия. Общий обзор
Реферат Язвенная болезнь желудка
Реферат Physics Relevance Essay Research Paper One aspect
Реферат Шерман, Джеймс Скулкрафт
Реферат Создание простейшей нейросети
Реферат The Terrible Trins Essay Research Paper What
Реферат Техника: сущность, закономерности развития и роль в жизни общества