85595

Разработка системы компьютерной обработки и описания изображений

Курсовая

Информатика, кибернетика и программирование

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

Русский

2015-03-28

1.45 MB

28 чел.

PAGE   \* MERGEFORMAT7

ГОСУДАРСТВЕННОЕ ВЫСШЕЕ УЧЕБНОЕ ЗАВЕДЕНИЕ

«ДОНЕЦКИЙ НАЦИОНАЛЬНЫЙ ТЕХНИЧЕСКИЙ УНИВЕРСИТЕТ»

(полное название учебного заведения)

_________Факультет компьютерных наук и технологий_________

(полное название института, название факультета (отделения))

Кафедра программного обеспечения интеллектуальных систем

(полное название кафедры (предметной, цикловой комиссии))

Пояснительная записка

к курсовому проекту

по теме:

«Разработка системы компьютерной обработки и описания

изображений»

Выполнил: студент _5_курсу, группы _ПЗС-14м_

направления подготовки (специальности)          

 8.050103  Программная инженерия                    .

                      (шифр и название направления подготовки, специальности)

Шеремет Н.Н.

                                         (фамилия и инициалы)

Руководитель

Бочаров Д.М.

                                                    (фамилия и инициалы)

Донецк – 2015 год


Лист задания



РЕФЕРАТ

Пояснительная записка: с. 51, 8 рис., 16 формул, 1 таблица, 6 источников.

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

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

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

Система может быть использована в образовательных целях для демонстрации работы реализованных методов и алгоритмов, а также в области обработки фотографий.

ИЗОБРАЖЕНИЕ, ФИЛЬТР, МАСКА, КОНТУР, ПИКСЕЛЬ, ЯДРО МАСКИ, БИБЛИОТЕКА OPEN CV, БИБЛИОТЕКА EMGU CV, ФОН, ШУМ, ЭРОЗИЯ.
 

КП-8.050103–084.001 ПЗ

Фамилия

Подпись

Дата

Разработал

Шеремет Н.Н. 

19.01.15

«Разработка системы компьютерной обработки и описания изображений»

Литера

Лист

Листов

Рук.проекта

Бочаров Д.М.

19.01.15

У

3

Рук.проекта

19.01.15

ДонНТУ,

каф. ПОИС,

группа ПОС-1

Н.контроль

Бочаров Д.М.

19.01.15

Н.контроль

19.01.15

Зав. каф.

19.01.15


СОДЕРЖАНИЕ

[0.1] Пояснительная записка

[1]
ВВЕДЕНИЕ

[2]
1 ПОСТАНОВКА ЗАДАЧИ

[3]
2 ОПИСАНИЕ РЕАЛИЗУЕМЫХ МЕТОДОВ И АЛГОРИТМОВ

[4] 2.1 Методы обработки изображений. Поворот изображения, получение серого изображения из исходного

[5] 2.2 Алгоритмы подавления шума

[6] 2.2.1 Фильтр свертка с маской и медианный фильтр

[7] 2.2.2 Метод k-ближайших соседей

[8] 2.3 Методы обнаружения границ объектов на изображении

[9] 2.3.1 Пороговая сегментация

[10] 2.3.2 Алгоритм водораздела

[11] 2.4 Метод описания контуров объектов. Оператор Кирша, оператор Превитта, оператор Лапласа.

[12] 2.5 Метод цепного кодирования

[13] 3 ОПИСАНИЕ ПРОГРАММНОЙ РЕАЛИЗАЦИИ

[14] 3.1 Теоретические сведения о библиотеке OpenCV

[15] 3.2 Структуры данных, используемые в ПП

[16] 3.3 Описание функций и методов, используемых в ПП

[17] ВЫВОДЫ

[18]
СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ

[19]
Приложение А

[20] ТЕХНИЧЕСКОЕ ЗАДАНИЕ

[21] Приложение Б

[22] РУКОВОДСТВО ПОЛЬЗОВАТЕЛЯ

[23]
Приложение В

[24] ЭКРАННЫЕ ФОРМЫ

[25]
Приложение Г

[26] ЛИСТИНГ ПРОГРАММЫ

Разработал

Фамилия

Подпись

Дата

КП-8.050103–084.001 ПЗ

Лист

ст. гр. ПОС-14м

Шеремет Н.Н. 

19.01.15

4

перечень обозначений, символов, единиц

сокращений и терминов

BGR

Blue Green Red

BMP

Bitmap Picture

OpenCV

Open Source Computer Vision Library

ПП

Программный продукт

Разработал

Фамилия

Подпись

Дата

КП-8.050103–084.001 ПЗ

Лист

ст. гр. ПОС-14м

Шеремет Н.Н. 

19.01.15

5


ВВЕДЕНИЕ

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

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

Методы цифровой обработки широко применяются в промышленности, искусстве, медицине, космосе. Они применяются при управлении процессами, автоматизации обнаружения и сопровождения объектов, распознавании образов и во многих других приложениях.

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

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


1 ПОСТАНОВКА ЗАДАЧИ

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

Целью разработки данного ПП является создание эффективных алгоритмов для обработки изображений (методы обнаружения границ объектов на изображении, методы описания контура объекта, алгоритмы подавления шума)

В рамках этого курсового проекта необходимо решить следующие задачи:

  •  загрузка и сохранение файла в формате BMP;
  •  преобразование цветного изображения в оттенки серого;
  •  поворот изображения на угол 90 градусов;
  •  добавление к изображению аддитивного и импульсного шумов;
  •  фильтрация изображения при помощи медианной фильтрации, взвешенно-медианной фильтрации, свертки с маской, фильтра к-ближайших соседей;
  •  обнаружение границ на изображении при помощи пороговой сегментации, алгоритма водораздела;
  •  оконтуривание объекта при помощи операторов Превитта, Кирша, Лапласа;
  •  выделение контура объекта при помощи алгоритма «жука».


2 ОПИСАНИЕ РЕАЛИЗУЕМЫХ МЕТОДОВ И АЛГОРИТМОВ

2.1 Методы обработки изображений. Поворот изображения, получение серого изображения из исходного

Полутоновое изображение – это изображение, имеющее множество значений тона, и их непрерывное, плавное изменение.

Примерами полутоновых изображений могут быть рисунки, картины, выполненные красками, фотографии.

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

  •  2 бита – 4 полутона;
  •  3 бита – 8 полутонов;
  •  4 бита – 16 полутонов;
  •  8 бит – 256 и т. д.

При этом, однобитовое бинарное изображение (1 бит на 1 пиксел) можно считать вырожденным полутоновым, способным передать лишь 2 полутона (чёрный и белый, например), или же его частным случаем. Множество возможных полутонов называют уровнями серого (gray scale), независимо от того, полутона какого цвета или его оттенка передаются. (Аналогично тому, как бинарное изображение, часто называемое «чёрно-белым», может при отображении выглядеть «чёрно-зелёным».) Таким образом, уровни серого не отличаются по спектральному составу (оттенку цвета), но отличаются по яркости. Количество возможных полутонов в данном случае есть глубина цвета, которую часто передают не в количестве самих полутонов, а в количестве бит на пиксел.

Для того чтобы повернуть растровое изображение на градус кратный 90, можно использовать метод изменения положения пикселей. Каждая точка изображения имеет координаты X и Y (соответствующие координатам прямоугольника, но в отличии от геометрического прямоугольника, координаты по оси Y начинаются с левого верхнего угла). Пиксель - это наименьший элемент поверхности рисунка, соответствующий цвету отображаемой точки на экране монитора. Таким образом - пиксель это цвет точки с координатами X и Y внутри прямоугольника.

Этот подход к повороту изображения заключается в том, что для поворота изображения необходимо поменять местами пиксели в соответствии с направлением поворота.

2.2 Алгоритмы подавления шума

2.2.1 Фильтр свертка с маской и медианный фильтр

Свертка – это операция вычисления нового значения выбранного пикселя, учитывающая значения окружающих его пикселей. Для вычисления значения используется матрица, называемая ядром свертки. Обычно ядро свертки является квадратной матрицей n*n, где n – нечетное, однако ничто не мешает сделать матрицу прямоугольной. Во время вычисления нового значения выбранного пикселя ядро свертки как бы «прикладывается» своим центром (именно тут важна нечетность размера матрицы) к данному пикселю. Окружающие пиксели так же накрываются ядром. Далее высчитывается сумма, где слагаемыми являются произведения значений пикселей на значения ячейки ядра, накрывшей данный пиксель. Сумма делится на сумму всех элементов ядра свертки. Полученное значение как раз и является новым значением выбранного пикселя. Если применить свертку к каждому пикселю изображения, то в результате получится некий эффект, зависящий от выбранного ядра свертки.

Медианный фильтр – один из видов цифровых фильтров, широко используемый в цифровой обработке сигналов и изображений для уменьшения уровня шума. Медианный фильтр является нелинейным КИХ-фильтром.

Значения отсчётов внутри окна фильтра сортируются в порядке возрастания (убывания); и значение, находящееся в середине упорядоченного списка, поступает на выход фильтра. В случае четного числа отсчетов в окне выходное значение фильтра равно среднему значению двух отсчетов в середине упорядоченного списка. Окно перемещается вдоль фильтруемого сигнала и вычисления повторяются.

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

Последовательный алгоритм данного метода:

  •  фильтрация проводится построчно – для первого элемента строки заполняется массив окрестности (с учетом того, что искусственно добавляются три значения-соседи слева), этот массив сортируется быстрой сортировкой, затем среднее значение записывается в выходную матрицу;
  •  для каждого следующего элемента строки массив окрестности не заполняется заново – в него лишь добавляются новые три элемента, замещая старые три. Для того, чтобы это было возможно сделать за один проход (по массиву окрестности и новым трем элементам) введен специальный массив с «количеством жизней» элемента. Жизней может быть 1, 2 и 3;
  •  добавляемые 3 элемента предварительно сортируются и добавление производится слиянием: во время него элементы с 1й жизнью затираются, элементы, имевшие 2 и 3 жизни получают 1 и 2 соответственно, а добавляемые элементы становятся обладателями 3х жизней;
  •  средний элемент записывается в выходной массив.

Обработка последнего элемента производится повторением итерации предпоследнего шага.

На практике данный метод по сравнению с полной выборкой окрестности и ее сортировкой показывает превосходство по скорости в 3 раза.

2.2.2 Метод k-ближайших соседей

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

Для оценки усреднённых  нужно решить вопрос о соотношении между объёмом  ячейки и количеством попавших в эту ячейку объектов того или иного класса (образа). Вполне разумно считать, что чем меньше , тем более тонко будет охарактеризована. Но при этом тем меньше объектов попадёт в интересующую нас ячейку, а следовательно, тем меньше достоверность оценки. При чрезмерном увеличении  возрастает достоверность оценки, но теряются тонкости её описания из-за усреднения по слишком большому объёму, что может привести к негативным последствиям (увеличению вероятности ошибок распознавания). При небольшом объёме обучающей выборки  целесообразно брать предельно большим, но обеспечить при этом, чтобы внутри ячейки плотности  мало изменялись. Тогда их усреднение по большому объёму не очень опасно. Таким образом, вполне может случиться, что объём ячейки, уместный для одного значения , может совершенно не годиться для других случаев.

Предлагается следующий порядок действий (пока что принадлежность объекта тому или иному образу учитывать не будем).

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

,

(2.1)

Это сглаженный (усреднённый) вариант плотности распределения . Если взять выборку из  объектов (простым случайным выбором из генеральной совокупности), то  из них окажется внутри области . Вероятность попадания  из  объектов в  описывается биномиальным законом, имеющим резко выраженный максимум около среднего значения . При этом  является неплохой оценкой для .

Если теперь допустить, что  настолько мала, что  внутри неё меняется незначительно, то

,

(2.2)

где  – объём области ;

– точка внутри .

Тогда

,

(2.3)

Но

,

(2.4)

Следовательно:

(2.5)

Итак, оценкой  плотности  является величина

(2.6)

Без доказательства приведём утверждение, что условия

,

,

(2.7)

(2.8)

являются необходимыми и достаточными для сходимости  к  по вероятности во всех точках, где плотность  непрерывна.

Этому условию удовлетворяет, например, .

Теперь будем учитывать принадлежность объектов к тому или иному образу и попытаемся оценить апостериорные вероятности образов  

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

, а

(2.9)

.

(2.10)

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

2.3 Методы обнаружения границ объектов на изображении

2.3.1 Пороговая сегментация

Одной из основных задач обработки и анализа изображений является сегментация, т.е. разделение изображения на области, для которых выполняется определенный критерий однородности, например, выделение на изображении областей приблизительно одинаковой яркости. Понятие области изображения используется для определения связной группы элементов изображения, имеющих определенный общий признак (свойство).

Один из основных и простых способов – это построение сегментации с помощью порога. Порог – это признак (свойство), которое помогает разделить искомый сигнал на классы. Операция порогового разделения заключается в сопоставлении значения яркости каждого пикселя изображения с заданным значением порога.

Операция порогового разделения, которая в результате дает бинарное изображение, называется бинаризацией. Целью операции бинаризации является радикальное уменьшение количества информации, содержащейся на изображении. В процессе бинаризации исходное полутоновое изображение, имеющее некое количество уровней яркости, преобразуется в черно-белое изображение, пиксели которого имеют только два значения – 0 и 1.

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

Бинаризация с нижним порогом является наиболее простой операцией, в которой используется только одно значение порога:

.

(2.11)

Все значения вместо критерия становятся 1, в данном случае 255 (белый) и все значения(амплитуды) пикселей, которые больше порога t – 0 (черный).

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

Операция бинаризации с верхним порогом:

.

(2.12)

Бинаризация с двойным ограничением. Для выделения областей, в которых значения яркости пикселей может меняться в известном диапазоне, вводится бинаризация с двойным ограничением (t1<t2):

.

(2.13)

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

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

.

(2.14)

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

.

(2.15)

2.3.2 Алгоритм водораздела

Метод водораздела, также называемый преобразованием водораздела – это основанный на областях метод математической морфологии. В географии, водораздел – это хребет, который делит области различных речных систем. Рассматривая изображения, как геологический ландшафт, можно сказать, что линии водораздела - это границы, разделяющие участки изображений. В топографическом представлении изображения I, численные значения (например, уровни серого) каждого пикселя выступают в качестве высоты этой точки. Преобразование водораздела вычисляет водосборные бассейны и линии хребтов, при том что водосборные бассейны – соответствующие области изображения, а линии хребтов – это границы этих областей. Основной проблемой данного алгоритма является чрезмерная сегментация, поскольку все границы и шумы отображаются в градиенте, что делает необходимым процесс удаления шума.

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

2.4 Метод описания контуров объектов. Оператор Кирша, оператор Превитта, оператор Лапласа.

Оператор Превитта – метод выделения границ в обработке изображений, который вычисляет максимальный отклик на множестве ядер свёртки для нахождения локальной ориентации границы в каждом пикселе. Он был создан доктором Джудит Прюитт (Judith Prewitt) для обнаружения границ медицинских изображений.

Этот метод выделения границ также называется подстановкой шаблонов границ (англ. edge template matching), поскольку изображению сопоставляется набору шаблонов, и каждый представляет некоторую ориентацию границы. Величина и ориентация границы в пикселе тогда определяется шаблоном, который лучше всех соответствует локальной окрестности пикселя.

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

С другой стороны, набор ядер нуждается в 8 свёртках для каждого пикселя, тогда как набор ядер градиентного метода требует только 2: чувствительных по вертикали и по горизонтали. Результат для изображения мощности границ очень похож у обоих методов, если в них используются те же ядра свёртки.

Оператор использует два ядра 3×3, свёртывая исходное изображение для вычисления приближённых значений производных: одно по горизонтали и одно по вертикали. Положим А исходным изображением, и Gx, Gy  – двумя изображениями, в которых каждая точка содержит горизонтальное и вертикальное приближение производной, которая рассчитывается как

.

(2.16)

Оператор Кирша. Обнаружение границ этим методом было введено Киршем в 1971 году. Алгоритм основан на использовании всего одной маски, которую вращают по восьми главным направлениям: север, северо-запад, запад, юго-запад, юг, юго-восток, восток и северо-восток. Маски имеют следующий вид:

Величина границы определена как максимальное значение, найденное с помощью маски. Определенное маской направление выдает максимальную величину. Например, маска k0 соответствует вертикальной границе, а маска k5 – диагональной. Можно также заметить, что последние четыре маски фактически такие же, как и первые, они являются зеркальным отражением относительно центральной оси матрицы.

Оператор Лапласа. Для одномерных, двухмерных и трёхмерных сигналов дискретный лапласиан можно задать как свёртку со следующими ядрами:

Фильтр 1D:

Фильтр 2D:

или с диагоналями:

Фильтр 2D:

Фильтр 3D:

для первой плоскости =

для второй плоскости =

для третьей плоскости =

Эти ядра выводятся с помощью дискретных частных производных.

2.5 Метод цепного кодирования

Цепные коды применяются для представления границы в виде последовательности отрезков прямых линий определённой длины и направления. В основе этого представления лежит 4- или 8- связная решётка. Длина каждого отрезка определяется разрешением решётки, а направления задаются выбранным кодом. Для представления всех направлений в 4-связной решётке достаточно 2-х бит, а для 8-связной решётки цепного кода требуется 3 бита.

Для алгоритма «жука» используется 4-связная решетка с простым алгоритмом действий.

Допустим, что на исследуемом изображении используется только два уровня полутонов: черные области описывающие объект, и белые – где объект отсутствует. «Жук» ползет по изображению до тех пор, пока не наткнется на черную область (границу объекта). Если жук находится в границах объекта – он начинает свое движение на право и прямо до тех пор, пока не выберется за границу объекта. Если «жук» покинул границу объекта – он начинает двигаться на лево и прямо, для возвращение на в границы объекта. Иллюстрация описания контура объекта алгоритмом «жука» показана на рисунке 2.1.

Рисунок 2.1 – Иллюстрация работы алгоритма «жука».

3 ОПИСАНИЕ ПРОГРАММНОЙ РЕАЛИЗАЦИИ

3.1 Теоретические сведения о библиотеке OpenCV

OpenCV (англ. Open Source Computer Vision Library, библиотека компьютерного зрения с открытым исходным кодом) – библиотека алгоритмов компьютерного зрения, обработки изображений и численных алгоритмов общего назначения с открытым кодом. Реализована на C/C++, также разрабатывается для Python, Java, Ruby, Matlab, Lua и других языков. Может свободно использоваться в академических и коммерческих целях – распространяется в условиях лицензии BSD.

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

Основные модули библиотеки:

  1.  cxcore – ядро* содержит базовые структуры данных и алгоритмы:
  •  базовые операции над многомерными числовыми массивами;
  •  матричная алгебра, математические ф-ции, генераторы случайных чисел;
  •  запись/восстановление структур данных в/из XML;
  •  базовые функции 2D графики.
  1.  CV – модуль обработки изображений и компьютерного зрения:
  •  базовые операции над изображениями (фильтрация, геометрические преобразования, преобразование цветовых пространств и т. д.);
  •  анализ изображений (выбор отличительных признаков, морфология, поиск контуров, гистограммы);
  •  анализ движения, слежение за объектами;
  •  обнаружение объектов, в частности лиц;
  •  калибровка камер, элементы восстановления пространственной структуры.
  1.  Highgui – модуль для ввода/вывода изображений и видео, создания пользовательского интерфейса:
  •  захват видео с камер и из видео файлов, чтение/запись статических изображений;
  •  функции для организации простого UI (все демо приложения используют HighGUI).
  1.  Cvaux – экспериментальные и устаревшие функции:
  •  пространств. зрение: стерео калибрация, самокалибрация;
  •  поиск стерео-соответствия, клики в графах;
  •  нахождение и описание черт лица.

Рисунок 3 – Диаграмма классов OpenCV

Для использования OpenCV на платформе .Net – используется кросс-платформенная обертка EmguCV. Реализация функции OpenCV для вызова из .NET совместимых языках, таких как C #, VB, VC ++, IronPython и т.д. обертки может быть скомпилирована и работать на Windows, Linux, Mac OS X, iPhone, IPAD и устройств Android.

3.2 Структуры данных, используемые в ПП

  •  Image <Bgr, byte> – переменая изображения, хранимого в трех цветовых каналах RGB палитры в значениях типа byte;
  •  Image <Bgr, float> ProcessedIMG – переменая изображения, хранимого в трех цветовых каналах RGB палитры в значениях типа float;
  •  Image <Gray, byte> GreyIMG – переменая изображения, хранимого в одном цветовом канале, показывающем яркость пикселя, в значениях типа byte.


3.3 Описание функций и методов, используемых в ПП

Таблица 3 – Описание функций и методов

Название функции.

Набор методов

Описание методов

1

Перевод цветного изображения в полутоновое.

ConvertToGray(Image<Bgr, byte> Img)

 

Преобразование изображения в оттенки серого. Параметры Bgr и Byte – цвет и глубина входящего изображения.

2

Поворот изображения на право.

RotateRight(Image<Bgr, byte> Img)

Поворот изображения на лево на 90 градусов. Аргументы: входящее изображение.

3

Поворот изображения на лево.

RotateLeft(Image<Bgr, byte> Img)

Поворот изображение на право на 90 градусов. Аргументы: входящее изображение.

4

Добавление аддитивного шума.

ANoise(Image<Bgr, byte> Img)

Добавление аддитивного шума к входящему изображению со среднеквадратическим отклонением шума = 20. Аргументы: входящее изображение.

5

Добавление импульсного шума.

INoise(Image<Bgr, byte> Img)

Добавление импульсного шума к входящему изображению, зашумление 100 пикселей. Аргументы: входящее изображение.

6

Фильтр-свертка.

MaskFilter(Image<Bgr, byte> Img, float[,] k)

Наложение фильтра-свертки на изображение. Аргументы метода: входящее изображение и размеры матрицы свертки.

Продолжение таблицы 3

7

Медианный фильтр.

MedianFilter(Image<Bgr, byte> Img)

Наложение медианного фильтра на изображение. Аргументы: входящее изображение.

8

Фильтр К-ближайших соседей.

KNearestFilter(Image<Bgr, Byte> Img)

 

Наложение фильтра К-ближайших соседей на изображение. Аргументы: входящее изображение.

9

Взвешенно-медианный фильтр.

WeightedMedianFilter(Image<Bgr, Byte> Img)

Наложение взвешенно-медианного фильтра на изображение. Аргументы: входящее изображение.

10

Пороговая сегментация.

Segmentation(Image<Bgr, Byte> Img, int LowLevel, int HightLevel)

Пороговая сегментация входящего изображения на два значения: 0 и 255. Аргументы: входящее изображение, нижний и верхний порог (принимается за 255).

11

Обнаружение границ. Водораздел.

WaterFilter(Image<Bgr, Byte> Img)

Применение фильтра водораздела к входящему изображению. Аргументы: входящее изображение.

12

Обнаружение границ. Оператор Превита.

PrevitContur(Image<Bgr, Byte> Img)

Применение оператора Превита к входящему изображению. Аргументы: входящее изображение.

13

Обнаружение границ. Оператор Лапласа.

LaplasContur(Image<Bgr, Byte> Img)

Применение оператора Лапласа к входящему изображению. Аргументы: входящее изображение.

Продолжение таблицы 3

14

Обнаружение границ. Оператор  Кирша.

KirshContur(Image<Bgr, Byte> Img)

Применение оператора Кирша к входящему изображению. Аргументы: входящее изображение.

15

Оконтуривание объекта. Алгоритм «жука».

Bug(Point Start,Image<Bgr,byte> Img)

Применение к изображению функции нахождения контура алгоритмом «жука».

Аргументы: входящее изображение.


ВЫВОДЫ

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

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

Разработанная система может применяться для фильтрации изображения с целью подавления шума, для обнаружения границ изображения, а также для оконтуривания объектов на изображении.


СПИСОК ИСПОЛЬЗОВАННЫХ ИСТОЧНИКОВ

  1.  Википедия – Open CV [Ел.ресурс]. – Режим доступа: https://ru.wikipedia.org/wiki/OpenCV.
  2.  Робокрафт – Open CV [Ел.ресурс]. – Режим доступа: http://robocraft.ru/page/opencv/.
  3.  Хабрахабр – Обработка изображений [Ел.ресурс]. – Режим доступа: http://habrahabr.ru/hub/image_processing/.
  4.  Крашенинников В. Р. Основы теории обработки изображений: Учебное пособие. – Ульяновск: УлГТУ, 2003. – 150 с.
  5.  Яншин. Обработка изображений на языке СИ для IBM PC: Учебник. – Санкт-Петербург, 2010. – 200 с.
  6.  Лукьяница А. А. Цифровая обработка изображений: Учебное пособие. – Москва: УлГТУ, 2009. – 518 с.


Приложение А

ТЕХНИЧЕСКОЕ ЗАДАНИЕ

Б.1 Общие сведения

Полное наименование разрабатываемой системы – «Разработка системы компьютерной обработки и описания изображения».

Б.2 Основания для разработки и цель создания системы

Основанием для разработки программного обеспечения является задание на курсовой проект, выданное кафедрой ПОИС ст. группы ПОС14-м Шеремету Николаю Николаевичу.

Б.3 Требования к системе

Б.3.1 Требование к системе в целом

Разрабатываемое ПО должно выполнять следующие задачи:

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

Б.3.2 Требования к функциям, которые реализуются системой

Разрабатываемое ПО должно иметь следующие функциональные части:

  •  загрузка и сохранение файла в формате BMP;
  •  преобразование цветного изображения в оттенки серого, поворот изображения на угол кратный 90 градусов;
  •  добавление к изображению аддитивного и импульсного шумов;
  •  фильтрация изображения при помощи медианной фильтрации, свертки с маской, фильтра к-ближайших соседей и взвешенно-медианного фильтра;
  •  обнаружение границ на изображении при помощи пороговой сегментации, алгоритма водораздела;
  •  оконтуривание объекта при помощи цепного кода Фримана, оператора Превитта, Кирша, Лапласа.

Б.3.4 Требования к среде разработки ПО

Программный продукт разрабатывается на языке С# c использованием библиотеки OpenCV и EmguCV.

Б.3.4.1 Требования к техническому обеспечению

Требования к рабочей станции следующие:

  •  IBM-совместимый персональный компьютер;
  •  ЦП с тактовой частотой от 2 GHz;
  •  оперативная память не меньше 2GB;
  •  видеокарта с объемом памяти не менее 64 MB;
  •  цветной графический TFT-монитор;
  •  клавиатура – стандартная – 104 клавиши;
  •  мышь – стандартная.

Б.3.4.2 Требования к программному обеспечению

Для функционирования системы необходим компьютер архитектуры х86 под управление ОС Windows 7/8.

Б.4 Стадии и этапы разработки

Курсовой проект выполняется относительно следующего календарного плана (табл. В.1).

Таблица В.1 – Календарный план выполнения курсового проекта

Наименование этапа работы

Срок выполнения

Примечание

Получение задания

10 октября 2014

Изучение теоретических сведений

12 октября 2014

Постановка задачи

14 октября 2014

Выбор способов программной реализации

17 октября 2014

Изучение алгоритмов обработки изображений

25 октября 2014

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

4 декабря 2014

Оформление пояснительной записки

18 декабря 2014

Защита курсового проекта

19 января 2015

Приложение Б

РУКОВОДСТВО ПОЛЬЗОВАТЕЛЯ

Для начала работы с приложением, необходимо загрузить картинку, с которой вы будете работать. Для этого выберите Файл/Открыть. Далее будет открыто диалоговое окно загрузки файла, и после выбора необходимой картинки она загрузится в приложение  и отобразится на экране. Главное окно приложения имеет несколько вкладок редактирования, на левой панели формы: «Редактировать», «Фильтрация», «Сегментация», «Жук».

После того как изображение было загружено в приложение, его можно обработать, выбрав любой из вышеперечисленных пунктов. Каждый из пунктов имеет свои подпункты:

  1.  «Редактировать»: «Градации серого», «Повернуть на право», «Повернуть на лево», «добавить аддитивный шум», «Добавить импульсный шум»;
  2.  «Фильтрация»: «Медианный фильтр», «Фильтр К-ближайших соседей», «Взвешенно-медианный фильтр», «Фильтр с маской».
  3.  «Сегментация»: «Пороговая сегментация», «Фильтр водораздела», «Оператор Превита», «Оператор Кирша», «Оператор Лапласа»;
  4.  «Жук»: «Жук».

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

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


Приложение В

ЭКРАННЫЕ ФОРМЫ

Рисунок В.1 – Исходное изображение

Рисунок В.2 – Перевод изображения в полутоновое

Рисунок В.3 – Применение медианного фильтра

Рисунок В.4 – Применение оператора Кирша

Рисунок В.5 – Применение алгоритма водораздела

Рисунок В.6 – Демонстрация алгоритма «жука»


Приложение Г

ЛИСТИНГ ПРОГРАММЫ

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

using System.Threading;

using Emgu.CV;

using Emgu.Util;

using Emgu.CV.Structure;

using Emgu.CV.CvEnum;

using Emgu.CV.UI;

namespace RI_Csharp

{

   public partial class Form1 : Form

   {

       public Form1()

       {

           InitializeComponent();

           dataGridView1.ColumnCount = 3;

           dataGridView1.RowCount = 3;

           dataGridView1.RowHeadersVisible = false;

           dataGridView1.ColumnHeadersVisible = false;

           button3.Enabled = false;

           for (int i = 0; i < 3; i++)

           {

               for (int j = 0; j < 3; j++)

               {

                   dataGridView1.Rows[i].Height = 39;

                   dataGridView1.Columns[j].Width = 39;

               }

           }

           label2.Text = trackBar1.Value.ToString();

           trackBar1.Enabled = false;

           tabControl1.Enabled = false;

           Steps = 0;

           button1.Enabled = false;

           button2.Enabled = false;

           

       }

       //-----------ГЛОБАЛЬНЫЕ-ПЕРЕМЕННЫЕ----------------------------------

       Image<Bgr, byte> Picture;

       List<Image<Bgr, byte>> PictureSet = new List<Image<Bgr,byte>>();

       int Steps = 0;

       String TheWayToFile;

       System.String TheWayToSave;

       Random Rnd = new Random();

       double[,] Mask = new double[3, 3];

       float[,] kern = new float[3, 3];

       

       //-----------ФУНКЦИОНАЛ---------------------------------------------

       /// <summary>

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

       /// </summary>

       /// <param name="TheWay"></param>

       /// <returns></returns>

       private Image<Bgr, byte> OpenTheImage()

       {

           Image<Bgr, byte> Img;

           if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)

           {

               TheWayToFile = openFileDialog1.FileName.ToString();

               Img = new Image<Bgr, byte>(TheWayToFile);

               return Img;

           }

           else

           {

               Img = new Image<Bgr, byte>(200,200);

               return Img;

           }

       }

       

       /// <summary>

       /// Сохранение изображения

       /// </summary>

       /// <param name="Img"></param>

       private void SaveTheImage(Image<Bgr, byte> Img)

       {

           if (saveFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK && saveFileDialog1.FileName != "")

           {

               TheWayToSave = saveFileDialog1.FileName.ToString();

               Picture.Save(TheWayToSave);

           }

       }

       /// <summary>

       /// Перевод изображения в серые тона

       /// </summary>

       /// <param name="Img"></param>

       /// <returns></returns>

       private Image<Bgr, byte> ConvertToGray(Image<Bgr, byte> Img)

       {

           Image<Gray, byte> Gray;

           Image<Bgr, byte> NotGray;

           Gray = Img.Convert<Gray, byte>();

           NotGray = Gray.Convert<Bgr, byte>();

           return NotGray;

       }

       /// <summary>

       /// Поворот изображения на право

       /// </summary>

       /// <param name="Img"></param>

       /// <returns></returns>

       private Image<Bgr, byte> RotateRight(Image<Bgr, byte> Img)

       {

           Image<Bgr, byte> Rotated = new Image<Bgr, byte>(Img.Height, Img.Width);

           for (int i=0; i< Img.Height - 1;i++)

           {

               for (int j=0; j< Img.Width - 1;j++)

               {

                   Rotated[j, Img.Height - i - 1] = Img[i, j];

               }

           }

           return Rotated;

       }

       /// <summary>

       /// Поворот изображения на лево

       /// </summary>

       /// <param name="Img"></param>

       /// <returns></returns>

       private Image<Bgr, byte> RotateLeft(Image<Bgr, byte> Img)

       {

           Image<Bgr, byte> Rotated = new Image<Bgr, byte>(Img.Height, Img.Width);

           for (int i = 0; i < Img.Height - 1; i++)

           {

               for (int j = 0; j < Img.Width - 1; j++)

               {

                   Rotated[Img.Width - j - 1, i] = Img[i, j];

               }

           }

           return Rotated;

       }

       /// <summary>

       /// Аддитивный шум

       /// </summary>

       /// <param name="Img"></param>

       private void ANoise(Image<Bgr, byte> Img)

       {

           int[,] Generation = new int[Img.Width, Img.Height];

           Bgr Q;

           for (int i = 0; i < Img.Width; i++)

           {

               for (int j = 0; j < Img.Height; j++)

               {

                   Generation[i, j] = Rnd.Next(-100,100);

               }

           }

           double SKO = 0;

           for (int i = 0; i < Img.Width; i++)

           {

               for (int j = 0; j < Img.Height; j++)

               {

                   SKO = SKO + Generation[i, j] * Generation[i, j];

               }

           }

           SKO = SKO / (Img.Width * Img.Height);

           SKO = Math.Sqrt(SKO);

           for (int i = 0; i < Img.Width; i++)

           {

               for (int j = 0; j < Img.Height; j++)

               {

                   Generation[i, j] = Generation[i,j] * 20 / Convert.ToInt32(SKO);

               }

           }            

           for (int i = 0; i < Img.Width - 1; i++)

           {

               for (int j = 0; j < Img.Height - 1; j++)

               {

                   Q = new Bgr(Img[j, i].Blue + Generation[i, j], Img[j, i].Green + Generation[i, j], Img[j, i].Red + Generation[i, j]);

                   Img[j, i] = Q;

               }

           }

       }

       /// <summary>

       /// Импульсный шум 

       /// </summary>

       /// <param name="Img"></param>

       private void INoise(Image<Bgr, byte> Img)

       {

           double Sum = Img.Height * Img.Width;

           double N = 100;

           for (int i = 0; i < Img.Height - 1; i++)

           {

               for (int j = 0; j < Img.Width - 1; j++)

               {

                   if (Rnd.NextDouble() > (Sum - N) / (Sum))

                   {

                       Img[i, j] = new Bgr(255, 255, 255);

                   }                 

               }

           }

       }

       /// <summary>

       /// фильтр свертки с маской (Цветное изображение)

       /// </summary>

       /// <param name="Img"></param>

       /// <param name="k"></param>

       /// <returns></returns>

       private Image<Bgr, byte> MaskFilter(Image<Bgr, byte> Img, float[,] k)

       {

           ConvolutionKernelF kernel = new ConvolutionKernelF(k);

           Image<Bgr, float> Res0 = Img * kernel;

           Image<Bgr, byte> Result = Res0.Convert<Bgr, byte>();

           return Result;

       }

       /// <summary>

       /// медианный фильтр

       /// </summary>

       /// <param name="Img"></param>

       /// <returns></returns>

       private Image<Bgr, byte> MedianFilter(Image<Bgr, byte> Img)

       {

           Image<Bgr, byte> Result = new Image<Bgr, byte>(Img.Width, Img.Height);

           Result = Img.SmoothMedian(3);

           return Result;

       }

        

       /// <summary>

       /// фильтр к-ближайших соседей

       /// </summary>

       /// <param name="Img"></param>

       /// <returns></returns>

       private Image<Bgr, byte> KNearestFilter(Image<Bgr, Byte> Img)

       {

           Image<Bgr, byte> Result = new Image<Bgr, byte>(Img.Width, Img.Height);

           int[] Box = new int[3];

           int Steps = 0;

           byte Level = 20;

           for (int i = 1; i < (Img.Height - 2); i++)

           {

               for (int j = 1; j < (Img.Width - 2); j++)

               {

                   Steps = 0;

                   Box[0] = 0;

                   Box[1] = 0;

                   Box[2] = 0;

                   for (int k = -1; k < 2; k++)

                   {

                       for (int z = -1; z < 2; z++)

                       {

                           if (Math.Abs(Img[i, j].Red - Img[i + k, j + z].Red) < Level && Math.Abs(Img[i, j].Blue - Img[i + k, j + z].Blue) < Level && Math.Abs(Img[i, j].Green - Img[i + k, j + z].Green) < Level)

                           {

                               Steps++;

                               Box[0] += Convert.ToInt32(Img[i + k, j + z].Blue);

                               Box[1] += Convert.ToInt32(Img[i + k, j + z].Green);

                               Box[2] += Convert.ToInt32(Img[i + k, j + z].Red);

                           }

                       }

                   }

                   Result[i, j] = new Bgr(Box[0] / Steps, Box[1] / Steps, Box[2] / Steps);

               }

           }

           for (int i = 0; i < Img.Height - 1; i++)

           {

               Result[i, 0] = Img[i, 0];

               Result[i, Img.Width - 1] = Img[i, Img.Width - 1];

           }

           for (int j = 0; j < Img.Width - 1; j++)

           {

               Result[0, j] = Img[0, j];

               Result[Img.Height - 1, j] = Img[Img.Height - 1, j];

           }

           return Result;

       }

       /// <summary>

       /// взвешенный медианный фильтр

       /// </summary>

       /// <param name="Img"></param>

       /// <returns></returns>

       private Image<Bgr, byte> WeightedMedianFilter(Image<Bgr, Byte> Img)

       {

           Image<Bgr, byte> Result = new Image<Bgr, byte>(Img.Width, Img.Height);

           List<double> BoxRed = new List<double>();

           List<double> BoxGreen = new List<double>();

           List<double> BoxBlue = new List<double>();

           for (int i = 1; i < (Img.Height - 2); i++)

           {

               for (int j = 1; j < (Img.Width - 2); j++)

               {

                   BoxRed.Clear();

                   BoxRed.Add(Img[i - 1, j - 1].Red);

                   BoxRed.Add(Img[i + 1, j - 1].Red);

                   BoxRed.Add(Img[i - 1, j + 1].Red);

                   BoxRed.Add(Img[i + 1, j + 1].Red);

                   BoxRed.Add(Img[i, j - 1].Red);

                   BoxRed.Add(Img[i, j + 1].Red);

                   BoxRed.Add(Img[i - 1, j].Red);

                   BoxRed.Add(Img[i + 1, j].Red);

                   BoxRed.Add(Img[i, j - 1].Red);

                   BoxRed.Add(Img[i, j + 1].Red);

                   BoxRed.Add(Img[i - 1, j].Red);

                   BoxRed.Add(Img[i + 1, j].Red);

                   BoxRed.Add(Img[i, j].Red);

                   BoxRed.Add(Img[i, j].Red);

                   BoxRed.Add(Img[i, j].Red);

                   BoxGreen.Clear();

                   BoxGreen.Add(Img[i - 1, j - 1].Green);

                   BoxGreen.Add(Img[i + 1, j - 1].Green);

                   BoxGreen.Add(Img[i - 1, j + 1].Green);

                   BoxGreen.Add(Img[i + 1, j + 1].Green);

                   BoxGreen.Add(Img[i, j - 1].Green);

                   BoxGreen.Add(Img[i, j + 1].Green);

                   BoxGreen.Add(Img[i - 1, j].Green);

                   BoxGreen.Add(Img[i + 1, j].Green);

                   BoxGreen.Add(Img[i, j - 1].Green);

                   BoxGreen.Add(Img[i, j + 1].Green);

                   BoxGreen.Add(Img[i - 1, j].Green);

                   BoxGreen.Add(Img[i + 1, j].Green);

                   BoxGreen.Add(Img[i, j].Green);

                   BoxGreen.Add(Img[i, j].Green);

                   BoxGreen.Add(Img[i, j].Green);

                   BoxBlue.Clear();

                   BoxBlue.Add(Img[i - 1, j - 1].Blue);

                   BoxBlue.Add(Img[i + 1, j - 1].Blue);

                   BoxBlue.Add(Img[i - 1, j + 1].Blue);

                   BoxBlue.Add(Img[i + 1, j + 1].Blue);

                   BoxBlue.Add(Img[i, j - 1].Blue);

                   BoxBlue.Add(Img[i, j + 1].Blue);

                   BoxBlue.Add(Img[i - 1, j].Blue);

                   BoxBlue.Add(Img[i + 1, j].Blue);

                   BoxBlue.Add(Img[i, j - 1].Blue);

                   BoxBlue.Add(Img[i, j + 1].Blue);

                   BoxBlue.Add(Img[i - 1, j].Blue);

                   BoxBlue.Add(Img[i + 1, j].Blue);

                   BoxBlue.Add(Img[i, j].Blue);

                   BoxBlue.Add(Img[i, j].Blue);

                   BoxBlue.Add(Img[i, j].Blue);

                   BoxRed.Sort();

                   BoxGreen.Sort();

                   BoxBlue.Sort();

                   Result[i, j] = new Bgr(BoxBlue[8], BoxGreen[8], BoxRed[8]);

               }

           }

           for (int i = 0; i < Img.Height-1; i++)

           {

               Result[i, 0] = Img[i, 0];

               Result[i, Img.Width - 1] = Img[i, Img.Width - 1];

           }

           for (int j = 0; j < Img.Width-1; j++)

           {

               Result[0, j] = Img[0, j];

               Result[Img.Height - 1, j] = Img[Img.Height - 1, j];

           }

           return Result;

       }

       /// <summary>

       /// пороговая сегментация

       /// </summary>

       /// <param name="Img"></param>

       /// <param name="LowLevel"></param>

       /// <param name="HightLevel"></param>

       /// <returns></returns>

       private Image<Bgr, byte> Segmentation(Image<Bgr, Byte> Img, int LowLevel, int HightLevel)

       {

           Image<Gray, byte> Result = new Image<Gray, byte>(Img.Width, Img.Height);

           Result = Img.Convert<Gray,byte>();

           Result = Result.ThresholdBinary(new Gray(LowLevel), new Gray(HightLevel));

           return Result.Convert<Bgr, byte>();

       }

       /// <summary>

       /// алгоритм водораздела

       /// </summary>

       /// <param name="Img"></param>

       /// <returns></returns>

       private Image<Bgr, byte> WaterFilter(Image<Bgr, Byte> Img)

       {

           Image<Bgr, byte> Result = new Image<Bgr, byte>(Img.Width, Img.Height);

           Result = Img;

           Image<Bgr, byte> Water = new Image<Bgr, byte>(Img.Width, Img.Height);

           Water = MedianFilter(Img.Erode(6));

           Water = MedianFilter(Img.Dilate(3));

           Water = Water / 86;

           Water = Water.Convert<Bgr, Int32>().Convert<Bgr, byte>() * 86;

           Water = MedianFilter(Water);

           Image<Gray, byte> Kenny = new Image<Gray, byte>(Img.Width, Img.Height);

           Kenny = Water.Canny(0, 250);

           Result = Water - Kenny.Convert<Bgr, byte>();

           return Result;

       }

       /// <summary>

       /// оконтуривание Превита (Для входящего цветного изображения)

       /// </summary>

       /// <param name="Img"></param>

       /// <returns></returns>

       private Image<Bgr, byte> PrevitContur(Image<Bgr, Byte> Img)

       {

           Image<Gray, byte> Result = new Image<Gray, byte>(Img.Width, Img.Height);

           float[,] PrevitMask = new float[3, 3] { { 1f, 0f, -1f }, { 1f, 0f, -1f }, { 1f, 0f, -1f } };

           Result = MaskFilter(Img, PrevitMask).Convert<Gray,byte>();

           return Result.Convert<Bgr,byte>();

       }

       /// <summary>

       /// оконтуривание Лапласа (Для входящего цветного изображения)

       /// </summary>

       /// <param name="Img"></param>

       /// <returns></returns>

       private Image<Bgr, byte> LaplasContur(Image<Bgr, Byte> Img)

       {

           Image<Gray, byte> Result = new Image<Gray, byte>(Img.Width, Img.Height);

           Result = Img.Convert<Gray,byte>();

           Result = Result.Laplace(3).Convert<Gray,byte>();

           return Result.Convert<Bgr, byte>();

       }

       /// <summary>

       /// оконтуривание Кирша (Для входящего цветного изображения)

       /// </summary>

       /// <param name="Img"></param>

       /// <returns></returns>

       private Image<Bgr, byte> KirshContur(Image<Bgr, Byte> Img)

       {

           Image<Gray, byte> Result = new Image<Gray, byte>(Img.Width, Img.Height);

           float[,] KirshMask = new float[3, 3] { { -3f, 5f, 5f }, { -3f, 0f, 5f }, { -3f, -3f, -3f } };

           Result = MaskFilter(Img, KirshMask).Convert<Gray,byte>();

           return Result.Convert<Bgr,byte>();

       }

       /// <summary>

       /// Жук

       /// </summary>

       /// <param name="Start">Первая точка контура</param>

       /// <param name="Img"></param>

       /// <returns></returns>

       private Image<Bgr,byte> Bug(Point Start,Image<Bgr,byte> Img)

       {

           Image<Gray, byte> Contur = new Image<Gray, byte>(Img.Width, Img.Height);

           int lastMove = 2;

           byte positionColor = 0;

           Point P = Start;

           int NullElements = 55555;

           Contur[P.Y, P.X] = new Gray(255);

           do

           {

               if (lastMove == 0)

               {

                   if (positionColor == 0)

                   {

                       P.X = P.X;

                       P.Y = P.Y + 1;

                       Contur[P.Y, P.X] = new Gray(255);

                       lastMove = 3;

                       positionColor = (byte)Img[P.Y, P.X].Blue;

                   }

                   else

                   {

                       P.X = P.X;

                       P.Y = P.Y - 1;

                       Contur[P.Y, P.X] = new Gray(255);

                       lastMove = 1;

                       positionColor = (byte)Img[P.Y, P.X].Blue;

                   }

               }

               if (lastMove == 1)

               {

                   if (positionColor == 0)

                   {

                       P.X = P.X - 1;

                       P.Y = P.Y;

                       Contur[P.Y, P.X] = new Gray(255);

                       lastMove = 0;

                       positionColor = (byte)Img[P.Y, P.X].Blue;

                   }

                   else

                   {

                       P.X = P.X + 1;

                       P.Y = P.Y;

                       Contur[P.Y, P.X] = new Gray(255);

                       lastMove = 2;

                       positionColor = (byte)Img[P.Y, P.X].Blue;

                   }

               }

               if (lastMove == 2)

               {

                   if (positionColor == 0)

                   {

                       P.X = P.X;

                       P.Y = P.Y - 1;

                       Contur[P.Y, P.X] = new Gray(255);

                       lastMove = 1;

                       positionColor = (byte)Img[P.Y, P.X].Blue;

                   }

                   else

                   {

                       P.X = P.X;

                       P.Y = P.Y + 1;

                       Contur[P.Y, P.X] = new Gray(255);

                       lastMove = 3;

                       positionColor = (byte)Img[P.Y, P.X].Blue;

                   }

               }

               if (lastMove == 3)

               {

                   if (positionColor == 0)

                   {

                       P.X = P.X + 1;

                       P.Y = P.Y;

                       Contur[P.Y, P.X] = new Gray(255);

                       lastMove = 2;

                       positionColor = (byte)Img[P.Y, P.X].Blue;

                   }

                   else

                   {

                       P.X = P.X - 1;

                       P.Y = P.Y;

                       Contur[P.Y, P.X] = new Gray(255);

                       lastMove = 0;

                       positionColor = (byte)Img[P.Y, P.X].Blue;

                   }

               }

               NullElements--;

           }

           while (NullElements > 0);

           return Contur.Convert<Bgr, byte>();

       }

       //-----------РАБОТА-ПРИЛОЖЕНИЯ--------------------------------------

       private void открытьToolStripMenuItem_Click(object sender, EventArgs e)

       {

           Picture = OpenTheImage();

           PictureSet.Clear();

           PictureSet.Add(Picture);

           Steps = 1;

           button1.Enabled = false;

           button2.Enabled = false;

           imageBox.Image = Picture;

           tabControl1.Enabled = true;

       }

       private void сохранитьToolStripMenuItem_Click(object sender, EventArgs e)

       {

           SaveTheImage(Picture);

       }

       private void dataGridView1_CellEndEdit(object sender, DataGridViewCellEventArgs e)

       {

           Mask[e.ColumnIndex, e.RowIndex] = Convert.ToDouble(dataGridView1[e.ColumnIndex, e.RowIndex].Value);

           kern[e.ColumnIndex, e.RowIndex] = (float) Mask[e.ColumnIndex, e.RowIndex];

           for (int i = 0; i < 3; i++)

           {

               for (int j = 0; j < 3; j++)

               {

                   if (dataGridView1[i, j].Value == null)

                   {

                       button3.Enabled = false;

                       i = 3;

                       j = 3;

                   }

                   else

                   {

                       button3.Enabled = true;

                   }

               }

           }

       }

       private void button4_Click(object sender, EventArgs e)

       {

           Picture = ConvertToGray(Picture);

           AddToSet();            

           imageBox.Image = Picture;

       }

       private void button5_Click(object sender, EventArgs e)

       {

           Picture = RotateRight(Picture);

           AddToSet();

           imageBox.Image = Picture;

       }

       private void button6_Click(object sender, EventArgs e)

       {

           Picture = RotateLeft(Picture);

           AddToSet();

           imageBox.Image = Picture;

       }

       private void button7_Click(object sender, EventArgs e)

       {

           ANoise(Picture);

           AddToSet();

           imageBox.Image = Picture;

       }

       private void button8_Click(object sender, EventArgs e)

       {

           INoise(Picture);

           AddToSet();

           imageBox.Image = Picture;

       }

       private void button9_Click(object sender, EventArgs e)

       {

           Picture = MedianFilter(Picture);

           AddToSet();

           imageBox.Image = Picture;

       }

       private void button10_Click(object sender, EventArgs e)

       {

           Picture = KNearestFilter(Picture);

           AddToSet();

           imageBox.Image = Picture;

       }

       private void button11_Click(object sender, EventArgs e)

       {

           Picture = WeightedMedianFilter(Picture);

           AddToSet();

           imageBox.Image = Picture;

       }

       private void button3_Click(object sender, EventArgs e)

       {

           Picture = MaskFilter(Picture,kern);

           AddToSet();

           imageBox.Image = Picture;

       }

       private void trackBar1_Scroll(object sender, EventArgs e)

       {

           label2.Text = trackBar1.Value.ToString();

           imageBox.Image = Segmentation(Picture, trackBar1.Value, 255);

       }

       private void radioButton1_CheckedChanged(object sender, EventArgs e)

       {

           trackBar1.Enabled = true;

           if (radioButton1.Enabled == true)

           {

               imageBox.Image = Segmentation(Picture, trackBar1.Value, 255);

           }

       }

       private void radioButton2_CheckedChanged(object sender, EventArgs e)

       {

           trackBar1.Enabled = false;

           if (radioButton2.Enabled == true)

           {

               imageBox.Image = WaterFilter(Picture);

           }

       }

       private void radioButton3_CheckedChanged(object sender, EventArgs e)

       {

           trackBar1.Enabled = false;

           if (radioButton3.Enabled == true)

           {

               imageBox.Image = PrevitContur(Picture);

           }

       }

       private void radioButton4_CheckedChanged(object sender, EventArgs e)

       {

           trackBar1.Enabled = false;

           if (radioButton4.Enabled == true)

           {

               imageBox.Image = LaplasContur(Picture);

           }

       }

       private void radioButton5_CheckedChanged(object sender, EventArgs e)

       {

           trackBar1.Enabled = false;

           if (radioButton5.Enabled == true)

           {

               imageBox.Image = KirshContur(Picture);

           }

       }

       private void button12_Click(object sender, EventArgs e)

       {

           if (radioButton1.Checked == true)

           {

               Picture = Segmentation(Picture,trackBar1.Value,255);

           }

           if (radioButton2.Checked == true)

           {

               Picture = WaterFilter(Picture);

           }

           if (radioButton3.Checked == true)

           {

               Picture = PrevitContur(Picture);

           }

           if (radioButton4.Checked == true)

           {

               Picture = LaplasContur(Picture);

           }

           if (radioButton5.Checked == true)

           {

               Picture = KirshContur(Picture);

           }

           AddToSet();

           imageBox.Image = Picture;

       }

       private void AddToSet()

       {

           if (Steps != PictureSet.Count())

           {

               PictureSet.RemoveRange(Steps, (PictureSet.Count() - Steps));

           }

           PictureSet.Add(Picture);

           Steps++;

           if (Steps > 1)

           {

               button1.Enabled = true;

           }

           else

           {

               button1.Enabled = false;

           }

           button2.Enabled = false;

       }

       private void button1_Click(object sender, EventArgs e)

       {

           if (Steps > 1)

           {

               Steps--;

               Picture = PictureSet[Steps - 1];

               button2.Enabled = true;

           }

           

           if (Steps == 1)

           {

               button1.Enabled = false;

           }

           imageBox.Image = Picture;

       }

       private void button2_Click(object sender, EventArgs e)

       {

           if (Steps < PictureSet.Count)

           {

               Steps++;

               Picture = PictureSet[Steps-1];        

               button1.Enabled = true;

           }

           if (Steps >= PictureSet.Count)

           {

               button2.Enabled = false;

           }

           imageBox.Image = Picture;

       }

       private void button13_Click(object sender, EventArgs e)

       {

           Point P = new Point(1,Picture.Height / 2);

           while (Picture[P.Y, P.X].Blue != 0)

           {

               P.X++;

           }

           imageBox.Image = Bug(P, Picture);

       }

   }

}


 

А также другие работы, которые могут Вас заинтересовать

35026. Система шифрования Цезаря 1.09 MB
  Криптография представляет собой совокупность методов преобразования данных, направленных на то, чтобы сделать эти данные бесполезными для противника. Такие преобразования позволяют решить две главные проблемы защиты данных: проблему обеспечения конфиденциальности (путем лишения противника возможности извлечь информацию из канала связи)
35027. Алгоритм шифрования XOR 131.96 KB
  XOR – это функция булевой алгебры, носящей название «исключающее или», данная функция используется для работы с данными представленными в двоичной системе исчисления. Основным достоинством, позволяющим использовать эту функцию в шифровальных алгоритмах является ее обратимость, при отсутствии потери информации.
35028. ФОРМИРОВАНИЕ ИНСТИТУТА АДВОКАТУРЫ В КОНЦЕ XVIII - НАЧАЛЕ XIX ВВ. ВО ФРАНЦИИ, ГЕРМАНИИ И РОССИИ 118 KB
  Внутриорганизационные правоотношения в сфере деятельности адвокатской корпорации и правоотношения, возникавшие по поводу правового статуса адвоката в период становления адвокатуры в России, Германии и Франции.
35029. Основы работы в AutoCAD 1.16 MB
  На сегодняшний день AutoCAD – самая мощная система автоматизированного проектирования (САПР) из тех, что могут работать на персональных компьютерах. Она способна выполнять практически все виды чертежных работ, необходимых в разнообразных областях технического проектирования.
35030. Настройка линейных и угловых единиц измерения 1.19 MB
  В AutoCAD при вычерчивании линий, а также объектов, состоящих из сегментов линий, используется одна из пяти систем линейных единиц. Угловые величины также могут измеряться в одной из пяти систем. Пользователь может выбрать самостоятельно как тип линейных
35031. Защита баз данных на примере MS ACCESS 441.3 KB
  Для защиты БД Ассеss использует файл рабочих групп systеm.mdw (рабочая группа - это группа пользователей, которые совместно используют ресурсы сети), к которому БД на рабочих станциях подключаются по умолчанию. Файл рабочих групп содержит учётные записи пользователей и групп, а также пароли пользователей.
35032. CADElectro + Search 190.5 KB
  Архивное хранилище документов [2. Различные типы документов [2. Согласование и утверждение документов [2. Проведение изменений утвержденных документов [2.
35033. Системы автоматизированного проектирования ЕLECTRICS Light 1.0. 50 KB
  К существенным преимуществам системы заметно отличающим ее от программ аналогичного назначения следует отнести: прямой расчет освещенности с использованием кривых силы света светильников с отслеживанием затенений и отражений от поверхностей; возможность расчета освещенностей в помещениях произвольной конфигурации прямоугольной овальной Г или Tобразной и т.; получение сводного результата по расчету множества помещений и всего здания проекта; возможность детального анализа распределения освещенности по области расчета построение...
35034. WinELSO 232.5 KB
  Работа с программой Для модуля Схема Электрооборудование А Компонуем модель электроснабжения промышленного общественного или жилого сооружения из элементов базы данных Расчетная схема ИСТОЧНИКИ ПИТАНИЯ Генераторы ПРЕОБРАЗОВАТЕЛИ Силовые трансформаторы КОММУТАЦИОННАЯ АППАРАТУРА Автоматические выключатели Дифференциальные автоматические выключатели УЗО Предохранители Контакторы Пускатели Переключатели Разъединители ЭЛЕКТРОПРИЕМНИКИ Силовые Электроосветительная нагрузка Розетки бытовые Квартиры Дома одноквартирные Дома садовые Сооружения...