Разработка и написание программы

Алгоритмы работы программы

Перед написанием программы необходимо продумать алгоритм ее работы, построить соответствующие блок-схемы (Рис.10).

Для начала необходимо загрузить изображение карты в программу. Любое изображение в MatLab представляется в виде массива с числами. После получения этого массива нам необходимо нужным образом его обработать. Топографическая карта обычно выполнена в полно цветном варианте, линии рельефа и все цифры выполнены одним цветом. Поэтому, зная цвета линий и цифр, мы можем их выделить из числа других объектов на карте, и преобразовать наше растровое изображение в логический формат, то есть в новую матрицу. Эта матрица будет представлять собой значения только 1 и 0 – там, где находиться линия или число – 1, а там, где остальные объекты 0.

Картинку вставить

Далее очистим новую матрицу от шумов. Это необходимо сделать, так как до преобразования на ней было множество посторонних элементов, ненужных нам, и которые могли остаться на карте.

Далее, из этой новой матрицы, с помощью специальных функций MatLab, мы определим все отдельные объекты и пронумеруем их. Затем выделим из всех найденных объектов линии по их свойствам (например, малая площадь самого объекта в области этого объекта). И если вычесть получившуюся матрицу линий из нашей первоначальной матрицы – получим матрицу цифр.

Распознаем каждую цифру по ее особенным свойствам (например, число Эйлера, эксцентриситет, центр масс и так далее), а затем соединим все полученные цифры в числа, составим новую матрицу чисел.

Следующим шагом, необходимо сопоставить все полученные нами данные – линии и числа, и также сформировать новую матрицу Z. Эта матрица будет содержать все высоты на карте.

По полученной матрице можно будет построить 3-D модель.

Разработка и написание программы - student2.ru

Рис. 10. Блок-схема работы программы

Обработка изображения

Для начала нам потребуется загрузить карту в MatLab для дальнейшей работы с ней. Для этого используем функцию imread.

f=imread('топографическая карта 1.jpg');

Теперь наша карта представлена с помощью массива f, в каждой ячейке которого указана интенсивность каждого пикселя. Топографические карты выполняются в цветном варианте, но рельеф и цифры изображаются черным цветом. Компьютеру в данном случае будет намного проще работать с черно-белым изображением, поэтому с помощью специальных функций программы переведем изображение в черно-белый вариант:

fR = f(:, : , 1);

fG = f(: , : , 2);

fB = f(:, : , 3);

gray=((fR>150)&(fG<150)&(fB<150));

Мы просто исключили красный, зеленый и синий цвета и сохранили новый массив. Далее с помощью функции size мы определяем размер изображения, который нам пригодиться в будущем. И найдем отдельные объекты на изображении используя специальную функцию bwlabel и найдем свойства этих объектов с помощью regionprops, то есть площадь Area и область объекта BoundingBox. только второй раз через пару страниц

[Ny,Nx]=size(gray);

[labeled,num] = bwlabel(gray,8);

stats = regionprops(labeled, 'Area','BoundingBox');

Очистим изображение от шума. Если есть в нашем изображении отдельные пиксели, вокруг которых нет других элементов, то он их удалит. И сохраним новый массив без шумов.

for i=1:num

if stats(i).Area<15

for xx=min(ceil(stats(i).BoundingBox(1)),Nx):min(ceil(stats(i).BoundingBox(1)+stats(i).BoundingBox(3)-1),Nx)

for yy=min(ceil(stats(i).BoundingBox(2)),Ny):min(ceil(stats(i).BoundingBox(2)+stats(i).BoundingBox(4)-1),Ny)

if labeled(yy,xx)==i

gray(yy,xx)=0;

end

end

end

end

end

grayN=gray;

Распознавание линий

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

Для начала найдем все объекты на карте и с помощью специальной функции пронумеруем их:

clearvars labeled num stats;

[labeled,num] = bwlabel(gray,8);

stats = regionprops(labeled, 'Area','BoundingBox');

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

У каждого объекта есть своя область, в которой он находится (Рис. 3.). Мы будем очень часто использовать их в своей работе.

Разработка и написание программы - student2.ru Разработка и написание программы - student2.ru

Рис. 3. Области различных объектов.

У каждого объекта также есть свой объем. После рассуждений можно прийти к выводу, что линия занимает очень малый объем в своей области. По этому свойству ее можно легко определить. Но есть мы будем уже выделенный нами элемент (например первый), затем вычисляем его площадь и сравниваем эту площадь с площадью его области. Если это отношение большое, то перед нами линия, если маленькое, то цифра. Линии мы стираем и образуем матрицу чисел.

for i=1:num

if (stats(i).Area/(stats(i).BoundingBox(3)*stats(i).BoundingBox(4)))<0.1

for xx=min(ceil(stats(i).BoundingBox(1)),Nx):min(ceil(stats(i).BoundingBox(1)+stats(i).BoundingBox(3)-1),Nx)

for yy=min(ceil(stats(i).BoundingBox(2)),Ny):min(ceil(stats(i).BoundingBox(2)+stats(i).BoundingBox(4)-1),Ny)

if labeled(yy,xx)==i

grayN(yy,xx)=0;

end

end

end

end

end

Затем получаем карту линий, из общей карты вычитаем карту цифр.

grayL=gray.*~grayN;

[labeledL,numL] = bwlabel(grayL,8);

statsL = regionprops(labeledL, 'EulerNumber');

enumL=zeros(numL,1);

for i=1:numL

enumL(i)=statsL(i).EulerNumber;

end

Распознавание цифр

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

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

Лучше применим метод ................................ Все цифры - 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 разные. Они имеют разные свойства, по разному нарисованы, каждая из ни индивидуальна, поэтому для каждой можно придумать свойство, которое отличало бы ее от других, причем эти свойства не должны зависеть от угла наклона цифры.

Среда программирования MatLab имеет множество функций, которые бы помогут нам в реализации задуманного. А сейчас выявим эти свойства.

Во первых стоит заметить цифру 8, ее можно легко определить из ряда других чисел по числу Эйлера. Число Эйлера равно числу объектов на изображении минус количество дыр в этих объектах. В цифре 8 две дыры и больше таких цифр нет. Для определения числа Эйлера в MatLab есть специальные функции:

enum(i)=stats(i).EulerNumber;

if (enum(i)==-1)

definenum=8; sign=1;

end

Из части кода мы видим, что если программа вычислила число Эйлера и оно равно -1, то перед ней цифра 8.

Далее будем работать с теми цифрами, число Эйлера у которых 0, то есть 1 дыра - это 4, 6, 9, 0. У каждой из цифр есть своя область, в которой она находится, в зависимости от наклона эти области меняются (Рис 3.).

Разработка и написание программы - student2.ru

Рис. 3. Области цифр, в зависимости от наклона.

Далее мы будем использовать области ццифр для выявления индивидуальных свойств 4 и 0, у этих цифр разное отношение заполненной части к незаполненной в своей области, в которой находится цифра.

if (enum(i)==0)&&(extent(i)>0.72)&&(sign==0)

definenum=4; sign=1;

end

if (enum(i)==0)&&(extent(i)<0.62)&&(sign==0)

definenum=0; sign=1;

end

Из кода мы видим, что у 4 это отношение не зависимо от угла наклона больше 0.72, а у 0 меньше 0.62.

Самое сложное - это найти отличия 6 от 9. Эти числа абсолютно одинаковые по форме, объему и прочим показателям. 6 есть перевернутая 9. Поэтому мы придумаем новый способ. У 6 и 9 заполенность входит в границы от 0.63 до 0.71. И если компьютер вычислил место на карте с числом Эйлера 0 и входящией в границы заполненностью, то мы будем рисовать в области цифры круг (Рис. 4.).

Разработка и написание программы - student2.ru

Рис. 4. Свойства 9 и 6.

После этой операции, как мы видим на рисунке, у 9 остается число Эйлера равным 0, а у 6 оно изменяется и становиться -1, то есть дырка пропадает.

Для рисования круга мы используем код:

if (enum(i)==0)&&(extent(i)>0.63)&&(extent(i)<0.71)&&(sign==0)

[rr cc] = meshgrid(1:Nx,1:Ny);

centrx=xx(i)+cos(orient(i))*rad(i)/3.5;

centry=yy(i)-sin(orient(i))*rad(i)/3.5;

C2 = (sqrt((rr-centrx).^2+(cc-centry).^2)<=(rad(i)/2.5));

newnumb=C2|numb;

[labeled3,num3] = bwlabel(newnumb,8);

stats3 = regionprops(labeled3, 'EulerNumber');

А затем, с помощью нового числа Эйлера мы определим что за цифра перед нами - 6 или 9.

if stats3(i).EulerNumber==1

definenum=6; sign=1;

end

if stats3(i).EulerNumber<1

definenum=9; sign=1;

end

Следующие цифры, которые мы будем искать на карте - это 1, 7, 5, 3, то есть те, у кого число Эйлера = -1, нет дыр.

С помощью эксцентриситета из оставшихся цифр выделим 1 и 7. Эксцентриситет — числовая характеристика объекта, показывающая степень его отклонения от окружности. У окружности эксцентриситет равен 0, а у линии 1. 1 и 7 очень вытянутые цифры. Далее, чтобы отличить их между собой мы ???? бред

if (enum(i)==1)&&(eccen(i)>0.93)&&(meanN(i)==-1)

meanN(i)=1;orient(i)=orient(i)-0.1015;

end

if (enum(i)==1)&&(eccen(i)>0.85)&&(convex(i)>0.44)&&(meanN(i)==-1)

meanN(i)=7; orient(i)=orient(i)+0.1881;

end

Остались только 2, 3 5. 2 и 3 также круглишочками. в уголке 2ки рисуем.

Сопоставление данных

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

Сначала соединим цифры в числа. Для этого

Построение 3D моделей

Разработка интерфейса

Наши рекомендации