2 РАСПОЗНАВАНИЕ СИМВОЛОВ
2.1 ТЕОРЕТИЧЕСКИЕ СВЕДЕНИЯ
Под распознаванием объекта будем понимать его узнавание, т.е. определение его как элемента некоторой совокупности объектов, называемой классом.Под образом (классом) будем понимать множество объектов, объединённых общими свойствами.
Признаки – это характеристики объекта, которыми определяются его свойства. Множеству образов соответствует алфавит, а множеству признаков соответствует словарь признаков.
Все ситемы и модели распознавания можно классифицировать следующим образом.
|
По заданию курсового проекта определён алфавит объектов – множество, состоящее из пяти прописных и пяти строчных букв латинского алфавита. Необходимо построить простую детерминированную систему распознавания.
Под простой будем понимать систему, алгоритм работы которой определён на основе априорной информации.
Сложные системы состоят из нескольких подсистем и уровней распознавания. Примером такого вида систем являются медицинские диагностические системы.
Работа систем без обучения осуществляется на основе априорной информации о признаках. В обучающиеся системы заложен алгоритм обучения по специально подобранной обучающей выборке. В самообучающихся системах заключены правила, по которым система сама определяет множество классов(алфавит классов).
Детерминированная система – это такая система, в которой связь между значениями признаков и классами жесткая, определенная.
Существует три подхода к задаче распознавания текстовых символов.
Первый – шаблонная (растровая) классификация. При её использовании считанный символ сравнивают со всеми шаблонами, хранящимися в базе. Критерии совпадения символов:
а) Q=S fш(xi,yj) XOR fs (xi,yj) min( по всем шаблонам );
б) Корреляция между шаблоном и считываемым символом
R(t,z)=òx òy fш(x,y) . fs (x -t, y -z) max
Преимущества: малая чувствительность к дефектам (разрывы, шумы…)
Недостатки: необходимо обучение новым шрифтам и типам размеров шрифтов.
Второй – признаковая классификация.
Преимущества: изображение символа преобразуется в простой набор признаков.
Недостатки: уход от истинного изображения.
При использовании этого метода можно использовать следующие признаки:
- размеры и соотношения размеров символов (длина, высота, площадь);
- проекции на различные оси;
- моменты относительно различных осей и соотношения между ними;
Третий – структурная классификация. Заключается в анализе топологии символов.
Обнаружение: углов, окрестностей, линий, пересечений, конечных точек и их взаимное расположение.
В своей работе наиболее приемлемым я счел использование шаблонной классификации на основе корреляционной функции. Использование других признаков я счёл лишним, т.к. они обладают меньшей эффективностью, а следовательно, уменьшают эффективность распознавания.
2.2 ОПИСАНИЕ ПРОГРАММЫ
Для моделирования системы распознавания я разработал программу на языке Borland Pascal.
В программу вхолят следующие процедуры и функции.
Процедура Init_Graph_Mode осуществляет вход в графический режим при использовании графического драйвера видеоадаптера SVGA. Т.к. драйвер svga256.bgi не является встроенным в таблицу BGI, то для его использования необходимо обратиться к стандартной процедуре InstallUserDriver. Кроме того, эта процедура инициализирует палитру GrayScale путем обращения к стандартной процедуре SetRGBPalette.
Процедура ShowList служит для отображения на экране картинки со строкой символов. Отображение идет с увеличением в 9 раз, т.е. каждый пиксель исходной картинки отображается на экране окном 3*3 одинаковых пикселей. В процедуру в качестве параметров передается x и y точки-начала координат, относительно которой и происходит отображение.
Процедура Init_Data служит для заполнения массивов данных: массивов, где содержатся считанные в память картинки.
Процедура Deranges вносит в исходную картинку помехи.
Внесение помех осуществлялось из расчёта 20% от общего веса символов. Координаты пикселей-помех являются случайными числами в пределах ширины и высоты картинки. Пиксель со случайными координатами инвертируется, т.е. при попадании на белый фон ставится чёрная точка, а при попадании на символ – белая точка.
Процедура Filter производит посильное удаление внесённых помех. Для этого используются 16 видов масок: для удаления помех, “залезших” на символ, для удаления групп из двух помех, для удаления помех, “пристроившихся” к символу. При совпадении маски с фрагментом изображения происходит изменение соответствующих пикселей.
Процедура Ramka служит для нахождения координат минимально описанного прямоугольника. Соответствующие переменные являются глобальными, процедура изменяет их значения и значение текущей координаты x. В зависимости от значения переменной flag происходит рисование полученной рамки на картинке.
Распознавание по корреляции оформлено в основном блоке программы. В процессе распознавания происходит поочерёдное выделение минимально описанных прямоугольников вокруг “испорченных” помехами символов. Затем идет цикл сравнения очередного символа со всеми шаблонами. После проверки того, что символ по размерам не меньше очередного шаблона, идет вычисление корреляционной функции. Если символ больше шаблона, то вычисляется несколько значений со смещениями по x и y, а затем из них берётся максимальное. Полученные значения сравниваются между собой. Номер шаблона, с которым получено наибольшее сходство, и будет распознанным символом.
ЗАКЛЮЧЕНИЕ
В работе были разработаны модели канала связи и системы распознавания. Моделирование было произведено с учётом возможного наличия помех. Моделирование показало работоспособность построенных моделей при достаточно высоком уровне помех.
ЛИТЕРАТУРА1. Теоретические основы информационной техники/Темников Ф.Е.и др.- М.:Энергия, 1971
2. Орлов В.А., Филлипов Л.И. Теория информации в упражнениях и задачах. - М.:Высш.шк., 1976
3. Сигорский В.П. Математический аппарат инженера - Киев:Техника, 1975
4. Солодов А.В. Теория информации и её
применение к задачам автоматического управления и контроля - М.: Наука, 1967.
2.3 ВЫВОД
Во второй части была рассмотрена модель распознавания, основанная на шаблонной классификации. Программное моделирование показало неплохие результаты. Модель распознаёт строку практически в 100% случаев при уровне помех до 40%. Однако данный подход может использоваться только в том случае, если заранее известно, что распознаваемые символы будут одинакового шрифта.
ПРИЛОЖЕНИЕ А
Текст программы моделирования канала связи.
Program final_of_work;
uses crt,graph;
const a=5;
b=0;
m=10+(a mod 6); {15}
r=trunc((m+a-b)/2); {10}
var
n, {n для (n,1) - кода}
temp,ent,out,symb,decode:byte; {буферы для кодирования}
p:array[1..m] of real; {вероятности}
p01,p10:real; {p единичной ошибки}
z,dl:array[1..m] of byte; {код, длина кода}
mask: array[1..8] of byte; {маски для декодирования}
data_n,data_p
:array[1..100] of integer; {данные для графика}
i,j, {счетчики}
count_of_errors, {счетчик ошибок восстановления}
dlina,sh, {длина массива сообщений}
count:integer; {счетчик для построения графика}
range,c,s,l:byte;
fl:boolean;
function flag(px:real):boolean;
{---осуществляет событие с вероятностью p---}
var ww,wq : word;
begin
ww := round(px * 100);
wq := random(100);
if ww > wq then flag := true else flag := false;
end;
procedure ver; {------------расчет вероятностей---------}
var s,i3,j3: integer;
tmp,s1:real;
begin
s:=0;tmp:=0; {вычисляем вероятности}
for j3:=1 to m do
s:=s+sqr(j3-r);
s:=s+m;
for i3:=1 to m do
p[i3]:=(1+sqr(i3-r))/s;
{-------упорядочиваем вероятности--------}
for i3:=1 to m-1 do {внешний цикл}
begin
tmp := p[i3]; {локальный максимум}
for j3:=i3 to m do
if p[j3] >= tmp then
begin
tmp := p[j3]; {максимум на i шаге}
s:=j3 {его номер}
end;
p[s] := p[i3]; {обмен}
p[i3] := tmp
end;
end;
procedure deranges; {----------внесение помех------------}
var tmp : byte;
c0,c1 : integer; {счетчики 0 и 1 для декодирования}
begin
out := 0; {выходной код после помех}
for i := 0 to 7 do {цикл по разрядам}
begin
c0 := 0; {сброс счетчиков}
c1 := 0;
tmp := (z[ent] shr i) and 1; {выделяем разряд}
for j := 1 to n do {цикл по разрядам (n,1)-кода}
case tmp of {определяемм помеху}
0 : if flag(p01) then inc(c1) else inc(c0);
1 : if flag(p10) then inc(c0) else inc(c1)
end;
if c1 > c0 then out := out or (1 shl i)
end; {вносим помеху в выходной код}
end;
procedure set_codes; {-----по алгоритму Шеннона - Фэно-----}
var i3,j2 : byte;
function numb(v:real):byte;{номер вероятности, находящейся}
var i2 : byte; {"" той, что передается как параметр}
begin
for i2 := 1 to m do {цикл по вероятностям}
if(v >= p[i2 + 1]) and (v <= p[i2]){если нашли границы}
then
numb := i2; {присваиваем номер "верхнего"}
end;
begin {-------------of procedure------------}
for i := 1 to m do {обнуляем коды и длины}
begin
z[i] := 0;
dl[i] := 0
end;
range := 8; {разряд - в максимальное значение}
c := 0; {счетчик по "вертикали" - на начало}
repeat {внешний цикл по кодам......}
if c = 0 {если в начале...}
then
dec(range); {... уменьшаем текущий разряд}
inc(c); {увеличиваем внутренний счетчик}
if (z[c] = z[c + 1]) and (c <= m)
{если два кода равны...}
then
begin {...то цикл деления}
fl := false; {флаг дальнейшего деления}
i := c; {"верхняя" граница}
j := c + 1; {"нижняя" граница}
if (z[j] = z[j + 1]) or (j + 1 < m)
{если ещё есть равные...}
then
fl := true; {...то ещё делим}
while fl do {пока можно делить...}
begin
inc(j); {...увеличиваем нижнюю границу}
if (z[j] <> z[j - 1]) or (j > m - 1) then
fl := false
end;
if((j - i) > 1) and (j < m)
{если > 2 элементов...}
then
dec(j); {...корректируем нижнюю границу}
s := numb((p[i] + p[j])/2); {делим}
if p[i] = p[j] {если два элемента...}
then
s := i; {середину - на "верхний"}
if j <= m {если не за пределами кодов...}
then
for l := i to j do {...цикл по группе}
if l <= s then {устанавливаем коды и длины}
begin
z[l] := z[l] or (1 shl range);
dl[l] := dl[l] + 1
end
else
dl[l] := dl[l] + 1;
if j < m then {устанавливаем текущий счетчик}
c := j
else
c := 0
end
else if c = m then c := 0;
until range = 0;{...пока не дойдем до последнего разряда}
{--------------инициализация масок--------------}
temp := 0;
for i := 1 to 8 do
begin
temp := temp or (1 shl (7 - (i - 1)));
mask[i] := temp
end
end;
function sourse:byte; {-----генерирует число из 1..15-----}
var cou : byte;
tu,ttu : real;
begin
cou := 1; {начальное значение}
ttu := p[cou]; {случайное число из 0..1}
tu := random;
while ttu < tu do begin {пока не превысили random...}
inc(cou);
ttu := ttu + p[cou]; {увеличиваем счетчик}
end;
sourse := cou; {присваиваем число из 1..15}
end;
procedure decoder; {---для неравномерного кода---}
var
code:byte;
begin
code:=out;
for i:=1 to 8 do {цикл со старшего разряда}
begin
temp:=code and mask[i]; {выделяем код}
for j:=1 to m do
if (temp=z[j]) and (i=dl[j]){если совпадает}
then
decode:=j; {...декодируем}
end;
end;
procedure graphiki; {-----------построение графика----------}
const x0=250; {начало координат}
y0=400;
var nn,ss,ii:integer;
sr:string;
driver,mode,errcode:integer;
begin
driver:=detect;
initgraph(driver, mode,''); {инициализация графики}
errcode:=graphResult;
if errcode<>grOk then
begin
Writeln(' Ошибка графики. ');
writeln(GraphErrorMSG(Errcode));
halt
end;
setcolor(white); {контуры фигур и текст}
line(x0,y0,x0,y0-300); {------ось y-----}
line(x0,y0,x0+200,y0); {------ось x-----}
SetTextStyle(DefaultFont, HorizDir, 1); {установка шрифта}
OutTextXY(x0,y0+40,'Количество повторений , n');
SetTextStyle(DefaultFont, VertDir, 1);
SetTextJustify(LeftText,TopText);{--способ выравнивания--}
OutTextXY(x0-50,180,'Количество ошибок , %');
SetTextStyle(DefaultFont, HorizDir, 1);
for i:=1 to 5 do
line(x0+i*35,y0,x0+i*35,y0-5);{делительные штрихи оси x}
outtextxy(x0+35,y0+10,'20');
outtextxy(x0+5*35,y0+10,'100');
for i:=1 to 4 do
line(x0,y0-i*65,x0+5,y0-i*65);{делительные штрихи оси y}
outtextxy(x0-20,y0-65,'15');
outtextxy(x0-20,y0-3*65,'45');
for nn:=1 to 33 do
begin {рисуем график}
setcolor(2);
line(x0+(nn+1)*5,round((y0-data_n[nn])),
x0+(nn+2)*5,round((y0-data_n[nn+1])));
end;
setcolor(15);
outtextxy(50,460,'Press any key...');
readkey;
ClearViewPort;
line(x0,y0,x0,y0-360); {------ось y-----}
line(x0,y0,x0+200,y0); {------ось x-----}
SetTextStyle(SmallFont, HorizDir, 5); {---установка шрифта--}
OutTextXY(x0,y0+40,'Значения p01 и p10 , %');
SetTextStyle(SmallFont, VertDir, 5);
SetTextJustify(LeftText,TopText); {-----способ выравнивания-----}
OutTextXY(x0-50,140,'Количество ошибок , %');
SetTextStyle(DefaultFont, HorizDir, 1);
for i:=1 to 5 do
line(x0+i*35,y0,x0+i*35,y0-5); {----делительные штрихи оси x---}
outtextxy(x0+35,y0+5,'20');
outtextxy(x0+5*35,y0+5,'100');
for i:=1 to 4 do
line(x0,y0-i*75,x0+5,y0-i*75); {----делительные штрихи оси y---}
outtextxy(x0-25,y0-75,'25');
outtextxy(x0-25,y0-2*75,'50');
outtextxy(x0-25,y0-3*75,'75');
outtextxy(x0-25,y0-4*75,'100');
{line(x0,y0-4*75,x0+200,y0-4*75);}
setcolor(2);
for nn:=1 to 13 do
{рисуем график}
line(x0+(nn+1)*12,round((y0-data_p[nn])),
x0+(nn+2)*12,round((y0-data_p[nn+1])));
end;
{=====================ОСНОВНОЙ БЛОК=======================}
Begin
clrscr;
p10:=0.2+0.02*a;
p01:=0.2+0.02*b;
randomize; {--инициализация генератора случайных чисел--}
ver; {инициализация и упорядочивание вероятностей}
set_codes; {--------инициализация кодов---------}
TextColor(15);
gotoxy(10,1);
write('ПАРАМЕТРЫ КАНАЛА :');
gotoxy(1,2);write('Вероятности одиночных ошибок :');
gotoxy(3,5);write('при передаче нуля : ',p01:4:3);
gotoxy(3,6);write('при передаче единицы : ',p10:4:3);
gotoxy(40,1);write('НЕРАВНОМЕРНЫЕ КОДЫ СООБЩЕНИЙ : ');
for i := 1 to m do {--------вывод кодов--------}
begin
gotoxy(45,1+i);
write(' z(',i,') = ');
gotoxy(55,1+i);
for j := 1 to dl[i] do
write((z[i] shr (8 - j)) and 1); {побитно}
end;
gotoxy(10,19);
write('Ввести длину передаваемого массива сообщений : ');
read(dlina);
write(' Ввести n для (n,1) - кода : ');
read(n);
count_of_errors := 0;
for sh := 1 to dlina do
begin {--------передача сообщений----------}
ent := sourse; {--случайное сообщение из ансамбля---}
deranges; {-----------внесение помех-----------}
decoder; {----декодирование двоичного кода----}
if ent <> decode then inc(count_of_errors);
end;
gotoxy(10,23);
write('РЕЗУЛЬТАТ ПЕРЕДАЧИ СООБЩЕНИЙ : ');
TextColor(12);
write( 'КОЛИЧЕСТВО ОШИБОК = ',count_of_errors);
TextColor(15);
gotoxy(10,24);
write('Please wait...');
{---------расчет count_of_errors для разных n-----------}
n := 0;count := 0;dlina := 100;
repeat
n := n + 3;
inc(count);
count_of_errors := 0;
for sh := 1 to dlina do
begin
ent := sourse;
deranges;
decoder;
if ent <> decode then inc(count_of_errors);
end;
data_n[count] := round(count_of_errors*3) ;
until n >= 96;
{---расчет count_of_errors для разных p01 и p10---}
n:=3;count:=0;dlina := 100;p01:=0;p10:=0;
repeat
p01:=p01+0.07;
p10:=p10+0.07;
inc(count);
count_of_errors := 0;
for sh := 1 to dlina do
begin
ent := sourse;
deranges;;
decoder;
if ent <> decode then inc(count_of_errors);
end;
data_p[count] := round(count_of_errors*3) ;
until p01 >= 0.98;
gotoxy(10,24);
writeln('Press any key to continue...');
readkey;
graphiki;
readkey;
closegraph;
End.
ПРИЛОЖЕНИЕ Б
Текст программы распознавания символов
Program Final_of_work;
uses graph;
const BiH=50; {-------высота картинки в пикселях------}
BiW=160; {-------ширина картинки в пикселях------}
stroka:array[1..10] of char=
('I','h','i','G','F','k','H','g','J','j');
{-----эталонная строка для установления соответствия-----}
type arr=array[1..BiW,1..BiH] of byte; {тип массива-картинки}
const
path0='work.bmp'; {путь к bmp-файлу с исходной строкой}
var file0,file1:file of byte; {файловые переменные для связи}
counter, {счетчик текущей позиции распознавания}
rasp:byte; {номер текущего распознанного символа}
f0, {массив с эталонной картинкой}
f:arr; {массив с картинкой, содержащей помехи}
x,y, {счетчики хода по массивам}
xmin, ymin,xmax, ymax , {минимально описанный прямоугольника}
xt, {текущая позиция x при движении по картинке}
xsav,{для сохранения текущего x при использовании корреляции}
i,j, {вспомогательные счетчики}
xm,xk,ym,yk,
{для сохранения текущего м.о.п. при использовании корреляции}
k,{счетчик шаблонов при использовании корреляции}
di,dj : integer;
{смещения шаблона и символа по x и y при наложении}
flag :boolean; {признак отображения на экране рамки}
kfmax, {глобальный максимум корреляции для символа}
max, {значение корреляции для текущего шаблона}
kf, {текущая переменная для вычисления корреляции}
smin:longint; {минимально возможная площадь шаблона}
Procedure Init_Graph_Mode; {-----инициализация графики-----}
var
Driver, {код драйвера графического устройства}
Mode, {код графического режима}
TestDriver, {внутренний номер драйвера в таблице BGI}
ErrCode: Integer; {код ошибки}
function TestDetect: Integer; far;
{функция определения параметров графического режима драйвера}
{полный адрес точки входа в функцию, т.е. = сегмент+смещение}
begin
TestDetect := 3; {разрешение экрана 800*600 точек}
end;
begin
TestDriver := InstallUserDriver('svga256', @TestDetect);
{устанавливает новый драйвер в таблицу BGI}
if GraphResult <> grOk then
begin
Writeln('Ошибка при установке драйвера:',
GraphErrorMSG(ErrCode));
Halt(1);
end;
Driver := Detect;{автоматическое определение драйвера-SVGA}
InitGraph(Driver, Mode, '');
{инициализация графического режима;}
{драйвер - в текущем каталоге}
ErrCode := GraphResult;
if ErrCode <> grOk then
begin
Writeln('Ошибка графического режима:',
GraphErrorMSG(ErrCode));
Halt(1);
end;
SetTextStyle(DefaultFont, HorizDir, 1); {текущий шрифт}
OutTextXY(120,20,'Идет инициализация графического режима...');
for x := 0 to 255 do {инициализация палитры grayscale}
SetRGBPalette(x,x,x,x);
OutTextXY(450,20,'Ok.');
end;
Procedure showlist(xn,yn:integer);
{---отображение картинки c масштабированием в 9 раз---}
{xn,yn-начало координат при отображении}
begin
x := 1; {текущие координаты-в начало}
y := 1;
repeat {внешний цикл-по высоте}
for i := -1 to 1 do
for j := -1 to 1 do {текущий пиксель - окном 3*3}
PutPixel((3*x+i)+xn,(3*BiH-3*y+j)+yn,f[x,y]);
x := x + 1; {приращение по x}
if x = BiW then {если с краю...}
begin
x := 1; {...то переходим в следующий ряд}
y := y + 1
end;
until y = BiH; {пока не окажемся в последней строке}
end;
procedure Init_Data; {-----заполнение массивов данных-----}
var t:byte;
begin
assign(file0,path0);
reset(file0);
seek(file0,$436);
for y:=1 to BiH do
for x:=1 to BiW do
begin
read(file0,t); {заполняем массив шаблонов}
f0[x,y]:=t;
end;
for x := 1 to BiW do{заполняем массив для внесения помех}
for y := 1 to BiH do
f[x,y]:=f0[x,y];
end;
Procedure Deranges; {-----------внесение помех-----------}
const u=20; {---уровень помех в % от общего веса символов---}
var count, {количество внесенных помех}
w : integer; {суммарный вес символов}
begin
count := 0;
w:=0;
randomize; {инициализация генератора случайных чисел}
for x := 1 to BiW do {подсчитываем суммарный вес}
for y := 1 to BiH do
if f[x,y] = 0 then w:= w+1;
repeat {------вносим помехи...------}
x := random(BiW); {случайные координаты}
y := random(BiH);
if (x in [3..BiW-2]) and (y in [3..BiH-2]) then
begin
if (f[x,y] = 255) then {если на белом фоне...}
f[x,y] := 1; {...то черная точка}
if (f[x,y] = 0) then {если на черном фоне...}
f[x,y] := 255 {...то белая точка}
end;
count := count + 1; {ув. счетчик помех}
until 100*count >= u * w; {пока не получим данный уровень}
for x := 1 to BiW do {перекрашиваем в 0-й цвет}
for y := 1 to BiH do
if f[x,y] = 1 then
f[x,y] := 0
end;
Procedure Filter; {-----фильтрация изображения от помех-----}
{специальные маски для удаления помех;}
{если при наложении маска совпала с фрагментом изображения,}
{то изменяем соответствующие пиксели}
const mask1:array[1..4,-1..1,-1..1] of byte =
(((1,1,0),(1,0,0),(1,1,0)),
((1,1,1),(1,0,1),(0,0,0)),
((0,1,1),(0,0,1),(0,1,1)),
((0,0,0),(1,0,1),(1,1,1)));
{для удаления помех, "залезших" на символ}
mask2:array[5..12,-2..2,-2..2] of byte =
(((0,0,0,0,0),(0,0,0,0,0),(0,0,1,0,0),(0,1,0,0,0),(0,0,0,0,0)),
((0,0,0,0,0),(0,0,0,0,0),(0,1,1,0,0),(0,0,0,0,0),(0,0,0,0,0)),
((0,0,0,0,0),(0,1,0,0,0),(0,0,1,0,0),(0,0,0,0,0),(0,0,0,0,0)),
((0,0,0,0,0),(0,0,1,0,0),(0,0,1,0,0),(0,0,0,0,0),(0,0,0,0,0)),
((0,0,0,0,0),(0,0,0,1,0),(0,0,1,0,0),(0,0,0,0,0),(0,0,0,0,0)),
((0,0,0,0,0),(0,0,0,0,0),(0,0,1,1,0),(0,0,0,0,0),(0,0,0,0,0)),
((0,0,0,0,0),(0,0,0,0,0),(0,0,1,0,0),(0,0,0,1,0),(0,0,0,0,0)),
((0,0,0,0,0),(0,0,0,0,0),(0,0,1,0,0),(0,0,1,0,0),(0,0,0,0,0)));
{для удаления групп одиночных помех}
mask3:array[13..14,-2..2,-1..1] of byte =
(((1,0,0),(1,0,0),(1,1,0),(1,0,0),(1,0,0)),
((0,0,1),(0,0,1),(0,1,1),(0,0,1),(0,0,1)));
mask4:array[15..16,-1..1,-2..2] of byte =
(((1,1,1,1,1),(0,0,1,0,0),(0,0,0,0,0)),
((0,0,0,0,0),(0,0,1,0,0),(1,1,1,1,1)));
{для удаления помех, "пристроившихся" к символу}
var m,n,l : integer; {вспомогательные счетчики}
flg : boolean; {признак выхода из цикла}
su : array[1..16] of longint; {массив сумм для масок}
begin
for i := 3 to BiW-2 do {внешний цикл по изображению}
for j := 3 to BiH-2 do
begin
l := 0; {если белая точка окружена черными...}
for m:=-1 to 1 do
for n:= -1 to 1 do
l := l + f[i+m,j+n];
if (l = 255) and (f[i,j] = 255) then
f[i,j] := 0; {...то делаем и её черной}
{если черная точуа окружена белыми...}
if (l >= 255*8) and (f[i,j] = 0) then
f[i,j] := 255; {...то делаем и её белой}
{обнуляем суммы для масок}
for l := 1 to 16 do
su[l] := 0;
{суммируем по всем видам масок}
for l := 1 to 4 do
for m:=-1 to 1 do
for n:= -1 to 1 do
su[l] := su[l] + ((not f[i+m,j+n]) xor mask1[l,m,n]) and 1;
for l := 5 to 12 do
for m:=-2 to 2 do
for n:=-2 to 2 do
su[l] := su[l] + ((not f[i+m,j+n]) xor mask2[l,m,n]) and 1;
for l := 13 to 14 do
for m:=-2 to 2 do
for n:=-1 to 1 do
su[l] := su[l] + ((not f[i+m,j+n]) xor mask3[l,m,n]) and 1;
for l := 15 to 16 do
for m:=-1 to 1 do
for n:=-2 to 2 do
su[l] := su[l] + ((not f[i+m,j+n]) xor mask4[l,m,n]) and 1;
{---проверяем по очереди каждый вид масок---}
{для первого вида - зачерняем центральную точку}
l := 0;
flg := false;
repeat
l := l + 1;
if su[l] = 0 then
flg := true;
until (flg) or (l = 4);
if flg then
f[i,j] := 0;
{для второго - делаем белым окно 3*3}
l := 4;
flg := false;
repeat
l := l + 1;
if su[l] = 0 then
flg := true;
until (flg) or (l = 12);
if flg then
for m := -2 to 2 do
for n := -2 to 2 do
f[i+m,j+n] := 255;
{для третьего и четвертого - делаем белой центральную точку}
l := 12;
flg := false;
repeat
l := l + 1;
if su[l] = 0 then
flg := true;
until (flg) or (l = 16);
if flg then
f[i,j] := 255;
end
end;
{-----------минимально описанный прямоугольник----------}
procedure ramka(zx:arr;flagx:boolean);
var
c : integer; {счетчик черных точек}
begin
xmin:=BiW;xmax:=0;ymin:=BiH;ymax:=0;
{начальные значения координат м.о.п.}
c:=0; {начальное значение счетчика}
xt := xt + 1; {сдвигаем текущую координату}
repeat {цикл увеличения xt по картинке...}
xt := xt + 1;
for y := 3 to BiH-2 do {просмотр по высоте}
if zx[xt,y] = 0 then
c:= c+1;
until (c <> 0) or (xt > BiW - 6);
{...пока не встретим черную точку}
c:= 0; {начальное значение счетчика}
repeat {цикл по символу...}
c := 0;
for y := 3 to BiH - 2 do {просмотр по высоте}
if zx[xt,y] = 0 then {если черная точка...}
begin
c:=c+1; {...то ув. счетчик}
if xt < xmin then xmin := xt; {изм.коорд.м.о.п.}
if xt > xmax then xmax := xt;
if y < ymin then ymin := y;
if y > ymax then ymax := y
end;
if xt <> 0 then xt := xt + 1; {ув. текущий x}
until (c=0) or (xt > BiW - 2);{...пока не дойдем до белого}
if flagx then {если признак...}
begin {...то рисуем рамку;100-цвет}
for x:=xmin-1 to xmax+1 do f[x,ymin-1]:=100;
for x:=xmin-1 to xmax+1 do f[x,ymax+1]:=100;
for y:=ymin-1 to ymax+1 do f[xmin-1,y]:=100;
for y:=ymin-1 to ymax+1 do f[xmax+1,y]:=100
end
end;
{=====================ОСНОВНОЙ БЛОК=======================}
BEGIN
Init_Graph_Mode;
OutTextXY(120,30,'Идет инициализация данных... ');
Init_Data;
OutTextXY(345,30,'Ok.');
flag := false;
smin:=BiH*BiH; {max возможная площадь символа}
For counter := 1 to 10 do {цикл по шаблонам}
begin {определяем min возможную площадь символа}
Ramka(f0,flag);
if (xmax-xmin)*(ymax-ymin) <= smin then
smin:= (xmax-xmin)*(ymax-ymin)
end;
OutTextXY(300,50,'Исходная строка символов : ');
Deranges;
ShowList(170,70);
Filter;
OutTextXY(270,260,'Строка символов после фильтрации : ');
xt := 2;
ShowList(170,280);
OutTextXY(120,500,'Идет распознавание строки символов : ');
SetTextStyle(DefaultFont, HorizDir, 4);
flag := true; {рисовать рамку}
counter := 0;
Repeat {---цикл по картинке с помехами---}
counter := counter + 1;{ текущий символ}
Ramka(f,flag);
{---------Распознавание по корреляции---------}
kfmax:=0; {min возможное значение Kf}
xsav:=xt; {сохраняем текущий x в картинке с помехами}
xm:=xmin; {сохраняем текущие координаты м.о.п.}
xk:=xmax;
ym:=ymin;
yk:=ymax;
xt:=2; {текущий x - в начало картинки с шаблонами}
for k := 1 to 10 do {---цикл по шаблонам---}
begin
Ramka(f0,not flag);
di:=0; {смещение шаблона и символа по x}
dj:=0; {смещение шаблона и символа по y}
max:=0; {min возможное значение текущей Kf}
if (xk-xm >= xmax-xmin) and (yk-ym >= ymax-ymin)
{если шаблон <= текущего символа...}
then {...тогда сравниваем с текущим шаблоном}
repeat
kf:=0; {min возможное значение temp - Kf}
{---цикл по текущему шаблону---}
for i:=xmin to xmax do
for j:=ymin to ymax do
kf := kf +
(f0[i+di,j+dj] * f[i-xmin+xm,j-ymin+ym]) and 1;
if kf > max then max := kf; {локальный max}
di:=di+1; {ув. смещение по x}
if xmax-xmin+di>=xk-xm {если сместили по x}
then {...то смещаем по y}
begin
di:=0;
dj:=dj+1
end;
until (ymax-ymin+dj>=yk-ym);
{...пока не сместим по y}
if max > kfmax {ищем глобальный max...}
then
begin
kfmax:=max;
rasp:=k {...и его номер}
end
end;
xt:=xsav; {восстанавливаем текущий x}
ShowList(170,280);
if (xk-xm)*(yk-ym) >= smin{если допустимая площадь}
then {...то выводим распознанный символ}
OutTextXY(190 + 35*counter,520,stroka[rasp]);
Until xt >= BiW - 15;
ShowList(170,280);
ReadLn;
CloseGraph; {сбрасываем графичесий режим}
END.
... модуляцией, можно сделать вывод, что помехоустойчивость приемника, использующего в качестве информационного параметра фазу, почти приближена к вероятности ошибки приемника Котельникова. 3. Оптимальная фильтрация. Отметим, что оптимальный приемник, является корреляционным, сигнал на его выходе представляет собой функцию корреляции принимаемого и ожидаемого сигналов, благодаря чему ...
... : 2.4 Расчет энергетического потенциала Энергетическим потенциалом радиолинии называется отношение средней мощности сигнала к спектральной плотности шума, пересчитанное ко входу приемника. В задании курсового проектирования задана линия с расстоянием между приемником и передатчиком 200 км. Зададимся, что это линия Земля - управляемый объект. Линия связи подобного типа предназначена для ...
... работы необходимо начинать с приобретения методических руководств к курсовой работе Ниеталина Ж.Н. и Ниеталиной Ж.Ж. «Электрлiк байланыс теориясы» выпущенной в Алма-Ате в 1999 году, Ниеталина Ж.Н. и Ниеталиной Ж.Ж. «Теория электрической связи» учебное пособие к курсовой работе. Алма-Ата 2001г., а также учебное пособие Зюко А.Г. и др. «Теория передачи сигналов» – М.; «Связь» 1988г., «Теория ...
... имеет минимальное влияние. Таким диапазоном оказался диапазон от 200 кГц и выше, в котором устройство имеет характеристики удовлетворяющие условиям проведения измерений и организации передачи данных. Таким образом, для определения усредненной амплитудно-частотной характеристики сетей электропитания, провелся ряд экспериментальных измерений. Измерения проводились в условиях наиболее приближенным ...
0 комментариев