Рефетека.ру / Информатика и програм-ие

Реферат: Программа распознавания символов


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

Контрольная работа по дисциплине

«МАГИ»

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

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

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

Задание.

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

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

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

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

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

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

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

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

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

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

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

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

Рис. 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::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 Picture->Bitmap->Height - 1; I++)
{
CurrentLine = (Byte*)Image1->Picture->Bitmap->ScanLine[I]; for (J = 0; J 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) 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

Похожие работы:

  1. • Программа распознавания символов
  2. • Программа распознавания символов
  3. • Помехоустойчивое кодирование, распознавание символов
  4. • Сканеры: виды, устройство, принципы работы
  5. • Разработка автоматизированной информационной системы ...
  6. • Средства составления и изготовления текстовой информации ...
  7. • Классификация программ офисного назначения
  8. • Отдел вневедомственной охраны при ОВД г. Топки
  9. • Автоматизация делопроизводства
  10. • Аппаратное обеспечение ЭВМ
  11. • Периферийные устройства ЭВМ
  12. • Конструкция системной платы ЭВМ
  13. • Устройство персонального компьютера
  14. • Информационные системы в экономике
  15. • Цифровые образовательные ресурсы на уроках ...
  16. • Разработка структуры автоматизированного рабочего ...
  17. • Мой компьютер
  18. • Эволюция делопроизводства и офисных технологий
  19. • Информатика и компьютерная техника
Рефетека ру refoteka@gmail.com