Docsity
Docsity

Подготовься к экзаменам
Подготовься к экзаменам

Учись благодаря многочисленным ресурсам, которые есть на Docsity


Получи баллы для скачивания
Получи баллы для скачивания

Заработай баллы, помогая другим студентам, или приобретай их по тарифом Премиум


Руководства и советы
Руководства и советы

Программная система обработки и анализа изображений курсовая по программированию и компьютерам , Дипломная из Программирование

Программная система обработки и анализа изображений курсовая по программированию и компьютерам

Вид: Дипломная

2016/2017

Загружен 11.04.2017

refbank7240
refbank7240 🇷🇺

10 документы

1 / 16

Toggle sidebar

Сопутствующие документы


Частичный предварительный просмотр текста

Скачай Программная система обработки и анализа изображений курсовая по программированию и компьютерам и еще Дипломная в формате PDF Программирование только на Docsity! Содержание 1 Возможности системы......................................................... 3 2 Аппаратное обеспечение..................................................... 3 3 Программное обеспечение.................................................. 3 4 Описание метода.................................................................. 5 5 Описание программы........................................................... 5 6 Структура базы для хранения эталонных символов......... 7 7 Текст программы.................................................................. 10 Введение В настоящее время, с ростом числа персональных компьютеров, огромное количество информации вводится с бумажных носителей на магнитные диски компьютеров. Разумеется это очень утомительная работа. И было бы неплохо иметь в своем распоряжении программное средство, которое было бы способно воспринимать входное изображение документа, которое вообще говоря является картинкой, и преобразовывать его в текст, отбрасывая при этом все лишнии детали изображения ( такие как линии разметки, обрамления и т.п. ). Этот вопрос волнует многие фирмы по разработке программного обеспечения и сейчас в мире разработано несколько программ для распознавания машинописного текста. Но это только начальный этап на пути решения данной задачи. Данные программные продукты распознают текст с довольно большой вероятностью ошибки при условии некачественного изображения. О том, чтобы распознавать рукописный текст пока даже не приходится и говорить. Целью разработки данной программной системы является детальное изучение данного вопроса и создание алгоритма, позволяющего преобразовывать графическое изображение в текст. Единственное отличие данной системы от разработанных ранее это то, что распознавать предстоит иероглифы. Эти знаки имеют существенное отличие от привычной нам кириллицы и латинских символов. Уже одно то, что они состоят из множества различных узоров отбрасывает идею строить распознавание на апроксимировании изображения символа с помощью какой либо функции. Хотя здесь можно попробовать использовать фрактальные преобразования, с помощью которых можно описать любое сколь угодно сложное изображение. Но теория, описывающая применение данных преобразований является коммерческой тайной и является недоступной. Так в нем планировалось белые пикселы кодировать 0, а черные - 1 и рассматривать их ни как отдельные а группой, т.е. группа белых пикселов - это 0, далее группа черных - 1 и т.д. В результате, символ, заключенный в прямоугольную ( рис. 1 ) рамку дает следующий код: 010 01010 01010 0101010 010 01010 01010 0101010 010 01010 01010 0101 010 010 01010 0101 01 010 Но на практике оказалось, что данный способ не подходит для решаемой задачи, т.к. он очень сильно привязан к начертанию символа. При изменении размера символа или при немного отличном начертании его код изменяется очень существенно. При увеличении размера символа появляются дополнительные строки, а значит и дополнительные символы кода. Следовательно однозначное декодирование символа при данных обстоятельствах не представляется возможным. Но данный опыт не прошел даром. Были сделаны соответствующие выводы, а именно: Нельзя привязываться к начертанию символа, т.е. к отдельным пикселам. Нужно анализировать изображение не по пикселам, а по отдельным элементам, таким как линии, кружочки, крючечки. Альтернативой предыдущему выводу является определение плотности изображения в отдельных его частях. Описание метода В разрабатываемой системе используется именно третий метод, т.е. определение плотности изображения в отдельных его частях. Его суть заключается в следующем: Вначале на всем изображении выделяется область, ограничивающая отдельный символ. Затем эта область делится на 9 равных частей ( рис. 2 ). рис. 2 В каждом из 9 квадратов подсчитывается число черных пикселов и делится на площадь данного квадрата, т.е. определяется плотность заполнения в каждом квадрате. Все 9 определенных плотностей преобразуются в формат Х.ХХХ и далее в строку типа Х.ХХХ Х.ХХХ Х.ХХХ Х.ХХХ Х.ХХХ Х.ХХХ Х.ХХХ Х.ХХХ Х.ХХХ. Преобразование в строку производится для более удобного хранения данных в базе данных ( структура базы описана в приложении ), так как это намного удобнее, чем делать в базе 9 полей для хранения 9 значений плотности. Декодирование символа производится аналогичным способом, только полученные данные сравниваются со значениями хранимыми в базе данных. Описание программы Все операции осуществляются посредством главного меню программы. Главное меню состоит из следующих пунктов: Файл Открыть файл Открывается окно выбора файла. Возможные маски для выбора ( BMP, PCX, JPG ). Если выбранный файл является правильным графическим файлом, то хранимое в нем изображение выводится в окно программы. Выделить линии Перед пользователем появляется диалоговое окно, в котором ему предоставляется возможность выбрать какие линии выделять ( вертикальные или горизонтальные ). Операции Очистить Тот файл, который был открыт открывается снова и все линии появившиеся в процессе работы удаляются. Определить плотность ( учеба ) Этот пункт меню предназначен для обучения системы. В окне должен находится эталонный текст. С помощью “мышки” выделяется нужный символ и выбирается данный пункт. Вслед за этим пользователю предоставляется возможность указать уникальный код для выбранного символа. Определенная плотность и код записываются в базу данных. Распознать Этот пункт противоположен предыдущему. С помощью “мышки” выделяется нужный символ и выбирается данный пункт. Происходит определение плотности выбранного символа и далее в базе осуществляется поиск записи, у которой поле с эталонной строкой более сходно с плотностью выделенного символа. Сравнение происходит следующим образом: Определяется и складываются между собой разности между плотностями эталонного и выделенного символами для каждого квадрата. Тот эталонный символ, у которого полученная сумма окажется наименьшей считается эквивалентом для выделенного. Преобразования Эти преобразования являются экспериментальными и не являются целью поставленной задачи. Полученные результаты при более глубоком исследовании могут быть в дальнейшем использованы для обработки изображений. Афинное преобразование Узоры Эти два пункта строят изображение пользуясь афинными преобразованиями с различными коэффициентами. В зависимости от этих коэффициентов изображения получаются различными. Лист папоротника Опять же основываясь на афинных преобразованиях строится лист папоротника. Данное преобразование имеет огромное практическое значение, так как относительно сложное изображение ( лист папоротника ) строится с помощью одной формулы. Выход Выход из программы. Приложение Структура базы для хранения эталонных символов Код символа Эталонная строка Код символа - однозначно идентифицирует хранимый символ. Так как в базе хранятся эталоны иероглифов, для которых в русском алфавите нет примера начертания, то для замены распознанного символа нужно еще хранить и его эталонное изображение. Но так как целью данной работы является не замена распознанных символов на эталонные, а только соотнесение с эталоном, то для экономии дискового пространства решено хранить не эталонное изображение символа, а только его уникальный код, с помощью которого можно однозначно идентифицировать символ. Эталонная строка - строка, содержащая в себе все 9 плотностей выделенной области. Текст программы {$I CdBase.inc} {$I CdComp.inc} unit Main; interface uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, Reg_imag, Menus, Options, CmplSign, DBTables, DB; type TMainForm = class(TForm) MainMenu: TMainMenu; N1: TMenuItem; N2: TMenuItem; Image: TMultiImage; N3: TMenuItem; NFileOpen: TMenuItem; OpenDialog: TOpenDialog; NSelect: TMenuItem; N4: TMenuItem; N5: TMenuItem; N6: TMenuItem; N7: TMenuItem; Onemore1: TMenuItem; N8: TMenuItem; N9: TMenuItem; DataTable: TTable; N10: TMenuItem; DataTableOpis: TStringField; DataTableID: TFloatField; procedure N2Click(Sender: TObject); procedure NFileOpenClick(Sender: TObject); procedure NSelectClick(Sender: TObject); procedure FormCreate(Sender: TObject); procedure ImageMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure ImageMouseUp(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); procedure ImageMouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer); procedure N4Click(Sender: TObject); procedure N7Click(Sender: TObject); procedure Onemore1Click(Sender: TObject); procedure N8Click(Sender: TObject); procedure N9Click(Sender: TObject); procedure N5Click(Sender: TObject); procedure N10Click(Sender: TObject); private DetectRectX, DetectRectY: real; { Угол, под которым выделять линии } xStart, xEnd, yStart, yEnd: word; BegSelect: boolean; procedure DefGradient(var Gx, Gy: real; x,y: word); procedure SetRect; procedure DefPlotn; procedure AfinConvert; procedure OneMore; procedure Mandel; procedure Paporotnik; function GetDensity: string; public { Public declarations } end; var MainForm: TMainForm; implementation {$R *.DFM} procedure TMainForm.N2Click(Sender: TObject); begin Application.Terminate; end; procedure TMainForm.NFileOpenClick(Sender: TObject); begin if OpenDialog.Execute then begin Image.ImageName := OpenDialog.FileName; NSelect.Enabled := True; end else NSelect.Enabled := False; end; procedure TMainForm.NSelectClick(Sender: TObject); var Result: word; begin OptionForm := nil; try OptionForm := TOptionForm.Create(Self); with OptionForm do begin RectXEdit.Text := FloatToStr(DetectRectX); RectYEdit.Text := FloatToStr(DetectRectY); X1Edit.Text := IntToStr(xStart); X2Edit.Text := IntToStr(xEnd); Y1Edit.Text := IntToStr(yStart); Y2Edit.Text := IntToStr(yEnd); Result := ShowModal; DetectRectX := StrToInt(RectXEdit.Text); DetectRectY := StrToInt(RectYEdit.Text); xStart := StrToInt(X1Edit.Text); xEnd := StrToInt(X2Edit.Text); yStart := StrToInt(Y1Edit.Text); yEnd := StrToInt(Y2Edit.Text); end; { with } finally OptionForm.Free; end; { try } if Result = mrOK then SetRect; end; { Определение градиентов Gx и Gy в точке [x,y] } procedure TMainForm.DefGradient(var Gx, Gy: real; x,y: word); var a, b, c, d, e, g, h, i: byte; begin with Image.Canvas do begin if Pixels[x-1,y-1] = clBlack then a := 0 else a := 1; if Pixels[x,y-1] = clBlack then b := 0 else b := 1; if Pixels[x+1,y-1] = clBlack then c := 0 else c := 1; if Pixels[x-1,y] = clBlack then d := 0 else d := 1; if Pixels[x+1,y] = clBlack then e := 0 else e := 1; if Pixels[x-1,y+1] = clBlack then g := 0 else g := 1; if Pixels[x,y+1] = clBlack then h := 0 else h := 1; if Pixels[x+1,y+1] = clBlack then i := 0 else i := 1; { Градиент по X } Gx := g + 2*h + i - a - 2*b - c; if Gx < 0 then Gx := 0; if Gx = 0 then Gx := 0.000001; { Градиент по Y } Gy := c + 2*e + i - a - 2*d - g; if Gy < 0 then Gy := 0; end; { with Image } end; procedure TMainForm.SetRect; var x, y: word; Gx, Gy, Qx, Qy: real; OutF: TextFile; S1,S2: string; begin AssignFile(OutF, 'tangs.000'); Rewrite(OutF); { Сканируем все изображение } with Image.Canvas do begin for y := yStart+1 to yEnd-1 do begin for x := xStart+1 to xEnd-1 do begin DefGradient(Gx,Gy,x,y); { Определить градиент в точке [x,y] } {if Gx+Gy > 0 then Pixels[x,y+200] := clRed;} Qx := ArcTan(Gy/Gx); Qx := Round(Qx*180/Pi); { Qx := Round(90*Gx/4); Qy := Round(90*Gy/4);} Str(Qx:2:0, S1); { Str(Qy:2:0, S2); } Write(OutF, S1+{' '+S2+}' | '); { if (Q <= -Pi/3) or (Q >= Pi/3) then Pixels[x,y+200] := clRed;} if (Qx > { DetectRectX}80) and (Qx < 100){ and (Q > DetectRect*Pi/180) }then Pixels[x,y+200] := clRed; end; { for x } WriteLn(OutF, 'End Line'); end; { for y } end; { with Image.Canvas } CloseFile(OutF); end; procedure TMainForm.DefPlotn; var i, j, x, y, dx, dy, Range, x1, y1: word; Count: word; begin x := xStart; y := yStart; dx := Round((xEnd-xStart+1) div 3); dy := Round((yEnd-yStart+1) div 3); x1 := x; y1 := y; { Три квадрата по вертикали } for i := 1 to 3 do begin if i = 2 then Range := (yEnd-yStart+1) - 2*dy else Range := dy; { Три квадрата по горизонтали } for j := 1 to 3 do begin if j = 2 then Range := (xEnd-xStart+1) - 2*dx else Range := dx; { Сканируем внутри квадрата по y } for y := y1 to y1+Range do begin { Сканируем внутри квадрата по x } for x := x1 to x1+Range do begin { Подсчитываем число не белых пикселов } if Image.Canvas.Pixels[x,y] <> clWhite then Inc(Count); end; { for x } end; { for y } x1 := x1+dx; { Следующий квадрат по горизонтали } end; { for j } y1 := y1+dy; { Следующий квадрат по вертикали } end; { for i } end; procedure TMainForm.FormCreate(Sender: TObject); begin OpenDialog.FileName := 'c:\delphi\mydir\diplom\pict\pict1.bmp'; Image.ImageName := OpenDialog.FileName; end; procedure TMainForm.ImageMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer); begin if Button = mbRight then begin Image.ImageName := OpenDialog.FileName; Exit; end; BegSelect := True; with Image.Canvas do begin Pen.Mode := pmXor; Pen.Color := clGreen; Pen.Style := psDot; b: array[1..15000] of word; k, n, i: word; newX, newY, z, x, y: real; Color: longint; begin x := 0; y := 0; z := 0; Randomize; for k := 1 to 15000 do begin b[k] := Random(10); if b[k] > 3 then b[k] := 1; end; { for k } i := 1; { b[i] := 1;} for i := 1 to 10000 do begin newX := (a[b[i],0,0]*x + a[b[i],0,1]*y + a[b[i],0,2]*z) / 100+ a[b[i],0,3]; newY := (a[b[i],1,0]*x + a[b[i],1,1]*y + a[b[i],1,2]*z) / 100+ a[b[i],1,3]; z := (a[b[i],2,0]*x + a[b[i],2,1]*y + a[b[i],2,2]*z) / 100+ a[b[i],2,3]; x := newX; y := newY; Color := Random(65535); Color := Color*100; Image.Canvas.Pixels[Round(300-x+z), Round(350-y)] := clGreen; end; { for k } end; procedure TMainForm.N9Click(Sender: TObject); begin Paporotnik; end; function TMainForm.GetDensity: string; var i, j: byte; LenX, LenY, x, y, xOld, yOld, dx, dy: word; BlackCnt, TotCnt: word; P: real; { Плотность пикселов в квадранте } S, S1: string; begin { Определяем плотность в 9 квадрантах } { выделенного диапазона } S := ''; LenX := xEnd-xStart+1; LenY := yEnd-yStart+1; xOld := xStart; yOld := yStart; for j := 1 to 3 do begin if j = 2 then dy := LenY-2*Round(LenY/3) else dy := Round(LenY/3); for i := 1 to 3 do begin if i = 2 then dx := LenX-2*Round(LenX/3) else dx := Round(LenX/3); {------------------------------------------------------------------} BlackCnt := 0; { Кол-во черных пикселов в квадранте } for y := yOld to yOld+dy-1 do begin for x := xOld to xOld+dx-1 do begin if Image.Canvas.Pixels[x,y] <> clWhite then Inc(BlackCnt); end; { for x } end; { for y } {------------------------------------------------------------------} TotCnt := dx*dy; P := BlackCnt/TotCnt; { Плотность пикселов в квадранте } Str(P:1:3, S1); S := S+S1+' '; xOld := xOld+dx; end; { for i } yOld := yOld+dy; end; { for j } Result := S; end; { TMainForm.GetDensity } procedure TMainForm.N5Click(Sender: TObject); var S: string; ID: word; begin S := GetDensity; ID := DataTable.RecordCount; DataTable.AppendRecord([ID+1, S]); end; procedure TMainForm.N10Click(Sender: TObject); var SValue: string[5]; S, DStr1, DStr2, OldS: string; Value, NewValue: real; i: byte; ID: word; begin S := GetDensity; OldS := S; DataTable.First; Value := 100; ID := 0; while not DataTable.EOF do begin NewValue := 0; {-----------------------------------------------------------} for i := 1 to 9 do begin DStr1 := Copy(S, (i-1)*6+1, 5); DStr2 := Copy(DataTableOpis.Value, (i-1)*6+1, 5); NewValue := NewValue + Abs(StrToFloat(DStr2)-StrToFloat(DStr1)); end; { for i } {-----------------------------------------------------------} if NewValue < Value then begin Value := NewValue; ID := DataTableID.AsInteger; end; DataTable.Next; end; { while } ShowMessage(IntToStr(ID)); end; end.
Docsity logo