МЕНЮ


Фестивали и конкурсы
Семинары
Издания
О МОДНТ
Приглашения
Поздравляем

НАУЧНЫЕ РАБОТЫ


  • Инновационный менеджмент
  • Инвестиции
  • ИГП
  • Земельное право
  • Журналистика
  • Жилищное право
  • Радиоэлектроника
  • Психология
  • Программирование и комп-ры
  • Предпринимательство
  • Право
  • Политология
  • Полиграфия
  • Педагогика
  • Оккультизм и уфология
  • Начертательная геометрия
  • Бухучет управленчучет
  • Биология
  • Бизнес-план
  • Безопасность жизнедеятельности
  • Банковское дело
  • АХД экпред финансы предприятий
  • Аудит
  • Ветеринария
  • Валютные отношения
  • Бухгалтерский учет и аудит
  • Ботаника и сельское хозяйство
  • Биржевое дело
  • Банковское дело
  • Астрономия
  • Архитектура
  • Арбитражный процесс
  • Безопасность жизнедеятельности
  • Административное право
  • Авиация и космонавтика
  • Кулинария
  • Наука и техника
  • Криминология
  • Криминалистика
  • Косметология
  • Коммуникации и связь
  • Кибернетика
  • Исторические личности
  • Информатика
  • Инвестиции
  • по Зоология
  • Журналистика
  • Карта сайта
  • Программа распознавания символов

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

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

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

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

    «МАГИ»

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

    Выполнил студент группы 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)

    if (Image1->Picture->Bitmap->PixelFormat != pf8bit)

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

    }

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

    -

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

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

    [pic]

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

    [pic]


    Приглашения

    09.12.2013 - 16.12.2013

    Международный конкурс хореографического искусства в рамках Международного фестиваля искусств «РОЖДЕСТВЕНСКАЯ АНДОРРА»

    09.12.2013 - 16.12.2013

    Международный конкурс хорового искусства в АНДОРРЕ «РОЖДЕСТВЕНСКАЯ АНДОРРА»




    Copyright © 2012 г.
    При использовании материалов - ссылка на сайт обязательна.