(в
пикселях)Потери (в
%)
|
|
|
|
ГПО
|
8628
|
8
|
0.1
|
АПО
|
8715
|
79
|
0.91
|
МДК
|
11252
|
2616
|
23.24
|
ЛПО
|
9294
|
658
|
7.07
|
Вывод: из результата видно, что глобальный
алгоритм лучше всего справляется со смазыванием на простых объектах, то есть
находит объект наиболее ближе всего к эталону. Очень хорошо справляется
адаптивная обработка. Хуже локальная, а обработка методом дискриминантного
критерия не справляется вовсе.
В большинстве результатов глобальная обработка
дает неплохие результаты только на искусственных простых изображениях. Однако,
говорить что этим ограничивается ее применение попросту нельзя. Например, на
рисунке 3.36 показано созданное на листке бумаги и сфотографированное изображение
и глобальная обработка на нем справляется лучше всего.
Исследование 9:
Цель: показать, что в некоторых изображениях
глобальная пороговая обработка, хоть и является самой простой, но показывает
самые лучшие результаты.
На рисунке 3.36 представлено сфотографированное
изображение. Слово RGB
резко выделяется из фона и, очевидно, является объектом интереса. Однако
изображение было нарисовано простым карандашом так, что, по сути, искусственно
созданные шумы имеют практически ту же яркость, что и слово RGB,
поскольку и те и те нарисованы одним и тем же графитом, а слово RGB
лишь немного было усилено интенсивностью. Очевидно, что при разбиении
изображения на части (как в адаптивной и локальной обработках) алгоритмы могут
начать сбиваться, несмотря на то, что гистограмма изображения (рисунок 3.36)
поддается весьма явному разделению на два класса.
Рисунок 3.36 - Исходное изображение
Рисунок 3.37 - Гистограмма изображения
Рисунок 3.38 - ГПО
Рисунок 3.39 - АПО
Рисунок 3.40 - МДК
Рисунок 3.41 - ЛПО
Вывод: как и ожидалось, глобальная пороговая
обработка сработала лучше всех остальных методов. Исключение составляет лишь
локальная обработка, но в результате этой обработки присутствуют лишние шумы,
которых нет на рисунке 3.38.
Рассмотрим теперь различные применения пороговой
обработки в реально существующих предметных областях.
3.2
Исследования на предметных изображениях
Теперь рассмотрим различные применения пороговой
обработки в задачах конкретных предметных областей.
Пороговая обработка часто применяется в
микробиологии. Например, при выделении микроорганизмов из их естественной среды
обитания. Примером такой сегментации может быть исследование 10.
Исследование 10:
Цель: сравнить работоспособность алгоритмов на
реально существующих задачах. Задача определения микроорганизма на изображении.
Изображение плохого качества, фон непростой структуры, вокруг «Хромосомы» также
имеется свечение, которое будет неблагоприятно реагировать на работу
алгоритмов.
Эталон был получен путем ручной «попиксельной»
обводки объекта черным маркером и его закрашиванием.
= 11473,
= 52787,
= 64260.
Рисунок 3.42 - Эталон
Рисунок 3.43- Изображение «Хромосома»
Рисунок 3.44 - ГПО Рисунок
3.45 - АПО
Рисунок 3.46 - МДК Рисунок
3.47 - ЛПО
Таблица 5 - Результаты исследования 10
Площадь
(в
пикселях)Потери (в
%)
|
|
|
|
ГПО
|
13497
|
2024
|
14.26%
|
АПО
|
12386
|
913
|
7.38%
|
МДК
|
12451
|
978
|
7.06%
|
ЛПО
|
12241
|
768
|
6.43%
|
Вывод: как видно из результатов сегментации,
лучше всего справляется локальная пороговая обработка, чуть хуже - адаптивная
и, затем, дискриминантная. Глобальная обработка слишком чувствительна к
множеству локальных минимумов, присутствующих на изображении.
В разделе 2.2.1 данной работы говорилось о том,
что работу глобального алгоритма можно улучшить, если изображение перед
обработкой инвертировать. Покажем, что это действительно так в следующем
исследовании.
Исследование 11:
Цель: проверить улучшение качества работы
глобального алгоритма путем предварительного инвертирования изображения.
Рисунок 3.48 - Инвертированное изображение
Рисунок 3.49 - ГПО Рисунок
3.50 - АПО
Рисунок 3.51 - МДК
Алгоритм методом локальной обработки изначально
не имеет смысла инвертировать. Потому что он работает с разбиением изображения
как с каждой отдельной областью, и, как показывают опыты, инвертирование
зачастую только ухудшает его работу.
Таблица 6 - Результаты исследования 11
Площадь
(в
пикселях)Потери (в
%)
|
|
|
|
ГПО
|
12641
|
1168
|
9.24
|
АПО
|
16258
|
4785
|
29.44
|
МДК
|
14878
|
3405
|
22.89
|
Вывод: из результатов работы алгоритма на
инвертированном изображении видно, что глобальная пороговая обработка улучшает
качество сегментирования на 5.02%, что весьма существенно. Однако, остальные
алгоритмы показывают себя хуже. Но так как глобальная обработка самая простая и
быстрая, то зачастую путем инвертирования можно добиться схожих с другими
методами результатов, а вычислительных затрат при этом получается в разы
меньше.
Исследование 12:
В данном исследовании демонстрируется применение
пороговой обработки в другой предметной задаче: в робототехнике. В
робототехнике пороговая обработка применяется в самых разнообразных задачах: от
машинного зрения в задачах определения лиц на изображении до узких предметных
областей. Одной из таких задач является автоматическое определение швов сварки
цветных металлов на производстве в системах автоматического управления.
Применяется как в микровеличинах, так и в макровеличинах.
На рисунке 3.52 представлен шов сварки цветных
листов между собой. Как видно, фон очень неоднородный, и само изображение
представляет собой очень сложную структуру. Очевидно, что сегментация такого
сложного изображения далеко не всегда будет корректна любым методом.
Рисунок 3.52 - Шов сварки цветных металлов
Рисунок 3.53 - Гистограмма изображения 3.35
Гистограмма, изображенная на рисунке 3.53
является сильно изрезанной, более того, она не унимодальная, что сразу говорит
о том, что простые алгоритмы пороговой обработки, например, глобальная
пороговая обработка, не справятся с таким изображением.
Рисунок 3.54 - ГПО
Рисунок 3.55 - АПО (3, 0.30)
Рисунок 3.56 - МДК
Рисунок 3.57 - ЛПО
К сожалению, в этом исследовании критерием
сравнения работы алгоритмов является только результирующее изображение и
субъективное мнение, потому что неизвестно, какой площадью обладает эталон
(выделить его практически невозможно, потому что даже «на глаз» на краях шва
непонятно, где же все-таки шов, а где фон), а значит точное сравнение провести
невозможно.
Вывод: по рисункам 3.54-3.57 можно сделать
вывод, что глобальная обработка, как и ожидалось, не дает совершенно никаких
результатов. Дискриминантная обработка тоже не показывает даже
удовлетворительной сегментации. А вот адаптивная и локальные обработки дают
весьма неплохие результаты на таком сложном изображении. Зрительно, они примерно
одинаково выделили шов. Адаптивную обработку можно «упрекнуть» лишь за
появившиеся в правой крайней части помехи.
Исследование 13:
Пороговую обработку часто применяют в задачах
сегментации изображений местности, полученных со спутника. Большинство таких задач
используют пороговую обработку в совокупности с другими методами, потому что
после пороговой обработки остается только нужная информация, следовательно,
обрабатывать нужно уже не все изображение. Примером может послужить уже
рассмотренное в разделе 2.4 изображение. Сравним с работой других алгоритмов.
Рисунок 3.58 - Исходное изображение
Рисунок 3.59 - ГПО Рисунок 3.60 -
АПО
Рисунок 3.61 - МДК Рисунок 3.62 -
ЛПО
Вывод: из результатов видно, что глобальная
обработка не справляется. Причина тому, как было уже сказано в разделе 2.4,
является тот факт, что гистограмма изображения сильно изрезана и не поддается
простому разбиению. Адаптивный алгоритм оказался более чувствительным к
локальным минимумам в данном случае, чем локальный алгоритм. В общем, алгоритмы
работают примерно одинаково.
Исследование 14:
Пороговая обработка активно применяется в
задачах сегментации радиолокационных изображений, в основном, радиолокационных
изображений нефтяных пятен на однородной морской поверхности.
На рисунке 3.63 представлено космическое
радиолокационное изображение акватории Северной Атлантики вблизи побережья
Испании. Темным шлейфом на снимке тянется пятно от того места, где тонет танкер
“Престиж”. Танкер ушел под воду 19 ноября, унеся с собой на дно более чем 50
тысяч тонн топлива.
Рисунок 3.63 - Исходное изображение
Рисунок 3.64 - ГПО
Рисунок 3.65 - АПО
Рисунок 3.66 - МДК
Рисунок 3.67 - ЛПО
Вывод: глобальная обработка в данной
ситуации справляется лучше других и предоставляет практически точное выделение
нефтяного пятна на поверхности воды. Причиной хорошей работы алгоритма является
то, что пятно весьма сильно выделяется из фона. Тогда, чтобы более сложные
алгоритмы «не отвлекались» на ненужные детали, вполне очевидно приходится
использовать глобальную обработку. Следует заметить, что степень детализации
адаптивной обработки можно уменьшить за счет регулирования параметра , но в таком
случае, можно потерять «тонкие» части нефтяного пятна.
Исследование 15:
Пороговая обработка очень часто
применяется в системах, основанных на биометрических параметрах человека.
Например, сканирование сетчатки, радужной оболочки глаза, отпечатка пальца. В
таких задачах пороговая обработка обладает неоспоримыми преимуществами.
Во-первых, она быстра по выполнению, во-вторых, в таких задачах обладает весьма
хорошими результатами. Приведем пример распознавания отпечатка пальца.
Рисунок 3.68 - Исходное изображение
Рисунок 3.69 - ГПО Рисунок
3.70 - АПО
Рисунок 3.71 - МДК Рисунок
3.72 - ЛПО
Вывод: все методы дают хорошую
сегментацию. Однако в дискриминантном и локальном методах появляется достаточно
много слияний между соседними линиями, чего в исходном изображении нет. С этой
точки зрения точнее определяет результат адаптивная обработка.
Исследование 16:
Пороговая обработка применяется в
робототехнике в самых разнообразных областях. Она также применяется для
автоматического распознавания разрывов (или пробоев) на листах металла. На
рисунке 3.73 показан пример такого разрыва на металлическом листе.
Рисунок 3.73 - Исходное изображение
Рисунок 3.74 - ГПО Рисунок
3.75- АПО
Рисунок 3.76 - МДК Рисунок
3.77 - ЛПО
Вывод: глобальный метод обработки
изображения справляется не очень хорошо со своей задачей ввиду плохого качества
изображения и множества локальных минимумов. Остальные алгоритмы справляются на
порядок лучше. Однако стоит отметить, что у адаптивного алгоритма разрыв не
прерывается, в то время как на исходном изображении можно заметить, что разрыв
в левой части все-таки есть.
В результате проведенных
исследований было показано, что глобальный алгоритм хорошо справляется с
изображениями, интересуемый объект на которых резко выделяется из фона.
Несмотря на то, что бывает это относительно редко, данный метод является самым
быстрым и поэтому часто используется. Плохо справляется с низкокачественными
изображениями, изображениями, содержащими шум и помехи и неоднородный фон.
Метод дискриминантного критерия
хорошо справляется с изображениями, гистограмма которых сильно изрезана.
Алгоритм дает очень хорошие результаты, когда площади двух классов и сравнимы по
величине.
Методы локальной и адаптивной
обработки являются более сложными методами, поэтому весьма неплохо справляются
с изображениями, содержащими неоднородный фон, фон сложной структуры, например,
как на рисунке 3.52. Отличие алгоритмов заключается в том, что в локальной
обработке используется информация о пространственном расположении пикселя на
объекте, а в адаптивной - о характеристике подобласти, в которой расположен
данный пиксель. В данных алгоритмах есть настраиваемые параметры, что делает
данные алгоритмы более гибкими. Возможна настройка уровня детализации путем
регулирования изменяемых параметров.
Данные методы хорошо подходят для
«сложных» по структуре изображений. Однако если на изображении присутствуют
сильные шумы, данные алгоритмы могут «реагировать» на них. Для самых простых
изображений применение данных методов нецелесообразно.
4. РАЗРАБОТАННОЕ ПРОГРАММНОЕ
ОБЕСПЕЧЕНИЕ
4.1 Общие
сведения
Разработанная программа называется
«Программа пороговой обработки изображений». Данное программное обеспечение
(далее ПО) написано на языке высокого уровня C++, с
использованием Microsoft Visual Studio 2008.
Программа написана с использованием набора компонент стандарта .NET Framework
версии 2.0. Для работы программы необходима операционная система Windows XP Sp3 и
установленная платформа не ниже версии .NET Framework 2.0.
Windows Forms - это
совершенно новый стиль построения приложения на базе классов .NET Framework. Основное
отличие Windows Forms от уже разработанных
ранее моделей построения приложений, таких как Win 32 API и MFC,
заключается в том, что Windows Forms создает
более однородную структуру программной модели. Также преимущество в том, что с
использованием Windows Forms легко можно
программировать на разных языках (C++, C# и так
далее).
Консольная версия программы написана
с использованием Open GL 1.1,
поэтому для использования консольной версии необходима видеокарта с поддержкой OpenGL не ниже
версии 1.1.
4.2
Входные данные
На входе подается 24-х-битное изображение
формата .bmp любого
разрешения. Также для работы программы следует выбрать файл результата в
формате .txt. Для выбора
этих файлов программа контактирует с пользователем посредством диалогового
режима5). Диалоговый режим работы с пользователем для выбора файлов представлен
на рисунке А.1
4.3
Выходные данные
Результатом работы программы является
сегментированное изображение, которое выводится на экран вместе с исходным
изображением. Результат работы программы представлен на рисунке А.2. Помимо
вывода изображения на экран в выбранный текстовый файл пишется также информация
о результате сегментации. Результирующий файл .txt
будет содержать следующую информацию:
1) координаты пикселей выделенного класса H1
(класс «интереса»);
2) значения составляющих исходного
изображения в этих пикселях;
) значение яркостей всех
пикселей объекта;
) общее количество пикселей
класса H0, класса H1 и всего
изображения.
4.4
Описание структуры ПО
Для создания данного ПО было написано две
отдельных программы, которые были впоследствии связаны друг с другом. Первая
программа была написана в консольном приложении и включала в себя все описанные
алгоритмы, а также все необходимые данные и параметры. Вторая программа была написана
с использованием средств Windows
Forms для создания
визуального интерфейса. Для работы с изображениями были использованы встроенные
средства Visual
Studio. Поэтому, в
итоговой программе Open
GL не используется,
он используется только в отдельной версии консольной программы.
При использовании Windows
Forms создается главное
окно. Главное окно приложения является формой. Любые другие окна приложения -
тоже формы. Приложения осуществляют полный контроль над событиями в собственных
окнах. Все события, коих великое множество, такие как нажатие кнопки, флажка,
наведение мышью на какой-либо объект и так далее, обрабатываются путем
наложения событий на эти действия. При создании какого-либо действия над
каким-либо объектом появляется новая функция, обрабатывающая эти события, и она
добавляется в общий класс формы, в которой находится данный объект.
На изображении А.3 Приложения А показан общий
вид главной формы. В левой верхней части находится область работы с файлами:
исходным файлом изображения и текстовым файлом результата.
Если какой-либо файл не был выбран, возникает
ошибка. Пример изображен на рисунке А.6.
В левой нижней части предоставлена работа
непосредственно с данными алгоритмов и управляющими элементами по запуску
сегментации. По нажатию на кнопку «Запуск!» выполняется работа алгоритма с
заданными параметрами.
В правой верхней части представлена «Помощь», в
которой содержится краткое описание программы и основных конструкций управления
работой. По нажатию на кнопку помощь запускается в отдельном окне, представленном
на рисунке А.5.
В правой части также представлена
область работы с гистограммами. Четыре кнопки отвечают за построение гистограмм
компонент . Все
гистограммы строятся в новом окне. Параметр масштаба гистограмм является
регулируемым. Чем больше масштаб, тем гистограмма становится мельче. Масштаб
изменяется в пределах от 1 до 100. Общий вид гистограмм был представлен на
протяжении всей работы.
При нажатии на красные маленькие
кнопки рядом с выбором методов сегментации и масштабом гистограмм можно вызвать
краткую подсказку, пример которой приведен на рисунке А.4.
Подробнее о программной реализации
можно узнать в Приложении Б.
ЗАКЛЮЧЕНИЕ
Были рассмотрены основные понятия
обработки изображений, основные задачи, связанные с обработкой изображений,
хорошо проанализированы и исследованы основные методы сегментации путем
пороговой обработки.
Основными результатами данной работы
являются:
· сегментация методом пороговой обработки, как в
автоматическом режиме, так и в ручном, а также создание программного
обеспечения, позволяющего проводить эту сегментацию;
· изучены и реализованы следующие
методы пороговой обработки:
o глобальная пороговая обработка;
o локальная пороговая обработка;
o пороговая обработка методом дискриминантного
критерия;
o адаптивная пороговая обработка.
· проведены сравнительные исследования работы
алгоритмов;
· проведены исследования влияния
характеристик изображения на работу алгоритмов;
· проанализировано практическое
применение пороговой обработки в реально существующих предметных областях.
В процессе работы были выяснены характеры
поведения алгоритмов на различного рода изображениях, отличающихся как по
структуре, так и по содержанию. Выявлены основные черты отличия алгоритмов друг
от друга, выявлены и продемонстрированы основные недостатки и достоинства
каждого из алгоритмов, подтверждающие теоретические предположения.
Продемонстрирована работа как на искусственно созданных изображениях, так и
применяемых практически. Сделаны общие выводы по каждому из алгоритмов
сегментации. В заключение хотелось бы еще раз отметить, что единого алгоритма,
который позволял бы проводить приемлемую сегментацию для любого изображения, не
существует.
СПИСОК ЛИТЕРАТУРЫ
1. Вудс,
Р. Цифровая обработка изображений / Р. Вудс, Р. Гонсалес. - Москва :
ТЕХНОСФЕРА, 2005. - 1072 с.
2. Визильтер,
Ю.В. Обработка и анализ цифровых изображений с примерами на LabVIEW и IMAQ
VIsion / Ю.В. Визильтер [и др.]. - Москва : ДМК, 2077. - 464 с.
. Яне,
Б. Цифровая обработка изображений / Б. Яне. - Москва : ТЕХНОСФЕРА, 2007. - 584
с.
. Грузман,
И.С Цифровая обработка изображений в информационных системах / И.С Грузман [и
др.]. - Новосибирск : НГТУ, 2002. - 352 с.
. Вудс,
Р. Цифровая обработка изображений в среде MATLAB / Р. Вудс, Р. Гонсалес, С.
Эддинс. - Москва : ТЕХНОСФЕРА, 2006. - 616 с.
. Вежневец
В. Выделение связных областей в цветных и полутоновых изображениях [Электронный
ресурс] / И.М. Журавель. - Режим доступа:
#"576679.files/image227.gif">
Рисунок А.1 - Диалоговый режим выбора файла
Рисунок А.2 -Результат сегментации
Рисунок А.3 - Главная форма программы
Рисунок А.4 - Общий вид подсказки
Рисунок А.5 - «Помощь»
Рисунок А.6 - Ошибка
ПРИЛОЖЕНИЕ Б
ПРОГРАММНАЯ РЕАЛИЗАЦИЯ
В данном приложении будут представлены только
основные выкладки из кода программы, чтобы сократить размерность данной
пояснительной записки.6)
Основная часть программы написана с
использованием Open
GL. Класс RGBPixmap
был взят и немного переработан из [13] с использованием приемов из [14].
Основная часть программы:
PROG.CPP
//--------------- основные
библиотеки для работы с программой -----//
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <math.h>
#include <assert.h>
#include <GL/gl.h> //библиотека
для
работы
с
Open GL
#include <GL/glu.h> //библиотека
для работы с Open GL
#include <GL/glaux.h> //библиотека
для работы с Open GL
#include "glut.h"
#include <fstream>
#include <iostream>
namespace std;
globa //вся программа заключена в область globa
{
//---------------------------------------------------------------------------//
//---------------------------------------------------------------------------//
//------------------- параметры обработки
изображения ------------------//
//---------------------------------------------------------------------------//
//---------------------------------------------------------------------------//
a_kol_razb; //количество областей при
разбиении изображенияloc2al_tochka_razbienija; //переменная,
отвечающая за определения порога разбиения области на принадлежащую фону или
объекту (локальная обработка)loc2al_dispers_fone; //перменная, отвечающая
за добавление яркости к пикселям фона (локальная
обработка)loc2al_dispers_object; //перменная,
отвечающая за добавление яркости к пикселям объекта (локальная оработка)
alfa=2./3.; //порог, для адаптивной локальной
обработкиKK=1; //праметр, определяющий область соседей
(адаптивная обработка)*filename; //имя файла с
изображением*rez; //результирующий файл с данными об
изображении
//---------------------------------------------------------------------------//
//----------------- конец параметры
обработки изображения ------//
//---------------------------------------------------------------------------//
//---------------------------------------------------------------------------//
screenWidth=1024, screenHeight=768; //размеры
рисуемого изначально окна
//************** переопределение
типов
*************************************//unsigned short ushort;unsigned long
ulong;unsigned char uchar;
int histogramma[256][4]; //область
памяти для хранения 4х гистограммwhat_draw=0, one_raz=0; //что
будем рисовать и флаг на копирование исходного изображенияadpt_porog[3]; //порог,
для локальной обработки
FILE *f1;
inf;i_flag=0,
loc2al_i_flag=0;j_flag=0, loc2al_j_flag=0;
whichPic=0,otstyp=10;
delRGB=40, delR=40; //для
наглядной
визуализации
гистограмм
int *a_peresek; //массив для определения
областей,содержащих и фон и объект.
//*************** вспомогательные
функции для чтения изображения **********//
ushort getShort()
{ic;ip;.get(ic);=ic;.get(ic);|=((ushort)ic
<< 8);ip;
}
getLong()
{ip=0;ic=0;char uc=ic;
.get(ic);=ic;=uc;.get(ic);=ic;
|=((ulong)uc <<
8);.get(ic);=ic;
|=((ulong)uc <<
16);.get(ic);=ic;
|=((ulong)uc << 24);
return ip;
}
//****************** класс RGB для каждого
пикселя ************************//
class mRGB{: uchar r,g,b;
mRGB() //конструкторы
{=0;=0;=0;
}(mRGB& p)
{=p.r;=p.g;=p.b;
}(uchar rr, uchar gg, uchar bb)
{=rr;=gg;=bb;
}set(uchar rr, uchar gg, uchar bb)
{=rr;=gg;=bb;
}
};
mmRGB{: double r,g,b;()
{=0;=0;=0;
}(mmRGB& p)
{=p.r;=p.g;=p.b;
}
};
mRGB* px1; //массив
пикселов, принадлежащих фону* px2; //массив
пикселов, принадлежащих объекту* pixel2; //массив пикселов
(вспомогательный)
//****************** класс пиксельной карты ******************************//RGBpixmap{
public:nRows, nCols;
()
{=nCols=0;=0;
}(int r, int c)
{= r;= c;= new mRGB[r*c];
}setPixel(int x, int y, mRGB color) //процедура
установки
пикселя
{(x>=0 && x<nCols
&& y>=0 && y<nRows)[nCols*y+x]=color;
}
getPixel(int x, int y) //процедура
получения
пикселя
{pixel[nCols*y+x];
}
draw() //процедура
рисования массива пикселей
{(nRows ==0 || nCols==0) return;(GL_UNPACK_ALIGNMENT,1);(nCols,
nRows, GL_RGB, GL_UNSIGNED_BYTE,pixel);
}
freeIt() //освобождение
памяти
{[]pixel;=0;=0;
}
copy(int x, int y, int wid, int ht) //копирование
пикселя
{(x,y,wid,ht,GL_COLOR);
}
readBMPFile(char * fname) //функция
чтения
BMP файла
{
.open(fname, ios::in | ios::binary);
(!inf)
{<< "can't open file:
" << fname << endl;0;
}k, row, col, numPadBytes,
nBytesInRow;ch1, ch2;.get(ch1);
inf.get(ch2);
//получение всей необходимой о файле информации
ulong fileSize = getLong();reserved1
= getShort();reserved2 = getShort();
offBits = getLong();
headerSize = getLong();
numCols = getLong();numRows =
getLong();
planes = getShort();
bitsPerPixel =
getShort();compression = getLong();
xPels = getLong();yPels = getLong();
numLUTentries = getLong();impColors
= getLong();(bitsPerPixel
!= 24) //если изображение не 24 бита, то ошибка
{<< "not a 24-bit pixel
image\n";.close();0;
}
= ((3*numCols+3)/4)*4;=
nBytesInRow-3*numCols;= numRows;= numCols;
= new mRGB[nRows * nCols]; //выделение
памяти=
new mRGB[nRows* nCols];= new mRGB[nRows* nCols];
//adapt = new
mRGB[adaptRows*adaptCols][3];
(!pixel) return 0;count = 0;
char dum;
//запись в основной массив пикселей (pixel)
считанных пикселей изображения
for (row=0; row<nRows;row++)
{(col=0; col<nCols; col++)
{r,g,b;.get(r);.get(b);.get(g);
[count].r=r;[count].g=g;[count].b=b;++;
}(k=0;k<numPadBytes;k++)>>
dum;
}.close();1;
}
copy_image(mRGB *copy_pixel, mRGB
*isxod_pixel)
{all;=nRows*nCols;
(int i=0;i<all;i++)
{_pixel[i].r = isxod_pixel[i].r;_pixel[i].g
= isxod_pixel[i].g;_pixel[i].b = isxod_pixel[i].b;
}
}
//************* функция определения
принадлежности пикселя фону или объекту *************************//
int func_glob_porog(int num, double
sr[3])
{min_porog=0, max_porog,rez=0;_porog=110;(pixel[num].r<=sr[0]
&& pixel[num].g<=sr[1] && pixel[num].b<=sr[2]) rez=1;
else rez=0;rez;
}
//****************** процедура для фонового
пикселя ***********************//
void pixel_in_fone(int num)
{[i_flag].r=pixel[num].r;[i_flag].g=pixel[num].g;[i_flag].b=pixel[num].b;
i_flag++;
}
//***************** процедура для пикселя
объекта ************************//
void pixel_in_object(int num)
{[j_flag].r=pixel[num].r;[j_flag].g=pixel[num].g;[j_flag].b=pixel[num].b;
j_flag++;
}
//********************* функция средней
яркости (по RGB) *********************//
int sred_rgb(int razm, int flg, int
what)
{a=0,b=0,c=0;(what==0)
{(int i=0;i<razm;i++)
{+=px1[i].r;+=px1[i].g;+=px1[i].b;
}
}
{(int i=0;i<razm;i++)
{+=px2[i].r;+=px2[i].g;+=px2[i].b;
}
}=a/razm;=b/razm;=c/razm;(flg==0)
return a;(flg==1) return b;(flg==2)
return c;
}
};
RGBpixmap
pic[1];
//элемент класса пиксельной карты, содержащий изображение
//----------------------------------------------------------------//
//************** процедура глобального порога ******************//
//----------------------------------------------------------------//glob_porog()
{ct=0;flag=0,pf=0,po=0,cvet_fon,cvet_object,fon_or_object=1;ch1='r',ch2='g',ch3='b';T0=1.0,argb[3],zrgb[3],Trgb[3],TTrgb[3],mxrgb=0.0,mnrgb=0.0;max_rgb[3],min_rgb[3],skok;
_fon=0; //цвет
фона
cvet_object=255;
//цвет объекта
skok=pic[whichPic].nCols*pic[whichPic].nRows; //количество
пикселей
for(int i=0;i<3;i++) //зануление
массивов
{[i]=0;_rgb[i]=0;_rgb[i]=0;
}
(int i=0;i<skok;i++)
{( max_rgb[0] < pixel[i].r )
max_rgb[0]=pixel[i].r;( max_rgb[1] < pixel[i].g ) max_rgb[1]=pixel[i].g;(
max_rgb[2] < pixel[i].b ) max_rgb[2]=pixel[i].b;( min_rgb[0] > pixel[i].r
) min_rgb[0]=pixel[i].r;( min_rgb[1] > pixel[i].g ) min_rgb[1]=pixel[i].g;(
min_rgb[2] > pixel[i].b ) min_rgb[2]=pixel[i].b;
}
(int i=0; i<3; i++)
{+=max_rgb[i];+=min_rgb[i];
}
=0.3*max_rgb[0]+0.59*max_rgb[1]+0.11*max_rgb[2];
//max яркость=0.3*min_rgb[0]+0.59*min_rgb[1]+0.11*min_rgb[2];
//min яркость
(int i=0; i<3;
i++)[i]=(mxrgb+mnrgb)/2;
=fopen("rezult.txt","w"); //файл
результата(rez,"Method:
global\n\n");
//алгоритм
автоматического
вычисления
порога(abs(TTrgb[0]-Trgb[0])>T0
&& abs(TTrgb[1]-Trgb[1])>T0 && abs(TTrgb[2]-Trgb[2])>T0 ) //итерационный
процесс
{=0;=0;=0;(int y=0;y<3;y++)[y]=Trgb[y];
(int i=0; i<pic[0].nRows;i++) //цикл
по
строкам
{(int j=0; j<pic[0].nCols; j++) //цикл
по
столбцам
{=pic[whichPic].func_glob_porog(ct,Trgb); //определение
принадлежности
пикселя
if (flag==1) //установка нового значения
пикселя
{[whichPic].pixel_in_fone(ct);
(rez,"x=%i\ty=%i\tR=%i\tG=%i\tB=%i\tRGB=%lf\n",j,i,pixel[ct].r,pixel[ct].g,pixel[ct].b,0.3*pixel[ct].r+0.59*pixel[ct].g+0.11*pixel[ct].b);
[ct].r=cvet_fon;[ct].g=cvet_fon;[ct].b=cvet_fon;
po++;
} //установка нового значения
пикселя (фон)
{[whichPic].pixel_in_object(ct);[ct].r=cvet_object;[ct].g=cvet_object;[ct].b=cvet_object;
++;
}++;
}
}(rez,"\n\nPixel_in_object =
%i\nPixel_in_fone = %i\nPixel_in_image =
%i\n",po,pf,ct);(rez);_flag=0;_flag=0;
(int q=0;q<3;q++)
{[q]=pic[whichPic].sred_rgb(pf,q,fon_or_object); //среднее
по
пикселям
фона
}
[0]*=0.3;[1]*=0.59;[2]*=0.11;
_or_object=0;(int q=0;q<3;q++)
{[q]=pic[whichPic].sred_rgb(pf,q,fon_or_object); //среднее
по
пикселям
объекта
}
[0]*=0.3;[1]*=0.59;[2]*=0.11;(int
u=0;u<3;u++)[u]=(argb[u]+zrgb[u])/2;
}
}
//конец класса пиксельная карта
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//+++++++++++++++++ начало класса локальная обработка
+++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++loc2al_class{
:aRows,aCols;raspred[255];dispers;mat_ozhid;**
loc2al_img;** px1;
mRGB** px2;* a_pixel; //массив
пикселов рисунка, подвергнувшегося адаптивной обработке*sksk;opred() //выделение
памяти, определение необходимых переменных и т.д.
{adaptRows,adaptCols,a,b;=pic[whichPic].nRows/a_kol_razb;=pic[whichPic].nCols/a_kol_razb;=adaptRows;=adaptCols;=adaptRows*adaptCols;=a_kol_razb*a_kol_razb;
_pixel = new
mRGB[pic[whichPic].nRows * pic[whichPic].nCols];al_img = new mRGB*[a];= new
mRGB*[a];= new mRGB*[a];= new int[b];(int i=0;i<a;i++)
{al_img[i] = new mRGB[b];[i] = new mRGB[b];[i]
= new mRGB[b];
}
}a_draw() //процедура рисования массива
пикселей (Open
GL)
{(pic[whichPic].nRows ==0 ||
pic[whichPic].nCols==0) return;(GL_UNPACK_ALIGNMENT,1);(pic[whichPic].nCols,
pic[whichPic].nRows, GL_RGB, GL_UNSIGNED_BYTE,a_pixel);
}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//Часть кода, расположенная ниже, была изменена
в отчете для лучшего восприятия основных моментов, которые выполнялись при
работе алгоритма
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//***** локальная пороговая обработка (главная
процедура локальной обработки)
void loc2al_glob_porog()
{cvet_fon=0, cvet_object=255, skok,
ct, fon_or_object=0, opred_prinadl_f=0,opred_prinadl_o=0;*only_oo,*only_ff,
razm, flag, po, pf;*mxrgb,*mnrgb, T0=5.0;*file;=
fopen("info.txt","w");=a_kol_razb*a_kol_razb;glob_pf=0,glob_po=0,glob_ct=0;
*max_rgb,*min_rgb,*Trgb,*TTrgb,*argb,*zrgb;_rgb
= new mRGB[razm];_rgb = new mRGB[razm];= new double[razm];= new
double[razm];_oo = new int[razm];_ff = new int[razm];= new mRGB[razm];= new
mRGB[razm];= new mRGB[razm];= new mRGB[razm];
=aCols*aRows;
(int i=0;i<razm;i++)
{_oo[i]=0;_ff[i]=0;
}
(int i=0;i<razm;i++)
{[i].r=0;[i].g=0;[i].b=0;
_rgb[i].r=0;_rgb[i].g=0;_rgb[i].b=0;_rgb[i].r=0;_rgb[i].g=0;_rgb[i].b=0;
[i]=0;
mnrgb[i]=0;
}
// ШАГ 1: определяем для каждой области максимум
и минимум по каждой из составляющей RGB(int k=0;k<razm;k++) //главный
цикл по всем областям
{(int i=0;i<skok;i++)
{( max_rgb[k].r <
loc2al_img[i][k].r ) max_rgb[k].r=loc2al_img[i][k].r;( max_rgb[k].g <
loc2al_img[i][k].g ) max_rgb[k].g=loc2al_img[i][k].g;( max_rgb[k].b <
loc2al_img[i][k].b ) max_rgb[k].b=loc2al_img[i][k].b;( min_rgb[k].r >
loc2al_img[i][k].r ) min_rgb[k].r=loc2al_img[i][k].r;( min_rgb[k].g >
loc2al_img[i][k].g ) min_rgb[k].g=loc2al_img[i][k].g;( min_rgb[k].b >
loc2al_img[i][k].b ) min_rgb[k].b=loc2al_img[i][k].b;
}
// ШАГ 1: конец.
// ШАГ 2: вычисляем максимальную и минимальную
яркость для каждой области
[k]=0.3*max_rgb[k].r+0.59*max_rgb[k].g+0.11*max_rgb[k].b;
mnrgb[k]=0.3*min_rgb[k].r+0.59*min_rgb[k].g+0.11*min_rgb[k].b;
// ШАГ 2: конец.
// ШАГ 3: вычисляем среднюю яркость для каждой
области (пишем их во все составляющие
RGB)[k].r=(mxrgb[k]+mnrgb[k])/2;[k].g=(mxrgb[k]+mnrgb[k])/2;[k].b=(mxrgb[k]+mnrgb[k])/2;
// ШАГ 3: конец.
//алгоритм автоматического вычисления
порога(abs(TTrgb[k].r-Trgb[k].r)>T0 &&
abs(TTrgb[k].g-Trgb[k].g)>T0 && abs(TTrgb[k].b-Trgb[k].b)>T0 )
{=0;=0;=0;
// ШАГ 4: вычисляем среднюю яркость для каждой
области (фиксирует ПРОШЛУЮ итерацию)
for(int kk=0;kk<razm;kk++)
{[kk].r=Trgb[kk].r;[kk].g=Trgb[kk].g;[kk].b=Trgb[kk].b;
}
// ШАГ
4: конец.
(int i=0; i<aRows; i++) //цикл
по
строкам
{(int j=0; j<aCols; j++) //цикл
по
столбцам
{=loc2al_func_glob_porog(ct,k,Trgb); //определение
принадлежности
пикселя
if (flag==1) //установка нового
значения пикселя (фон)
{al_pixel_in_fone(ct,k);
pf++;_prinadl_f++;
} //установка
нового значения пикселя (объект)
{al_pixel_in_object(ct,k);++;_prinadl_o++;
}++;
}
}(opred_prinadl_o==0) only_ff[k]++; //если
в области только фон(opred_prinadl_f<loc2al_tochka_razbienija) only_oo[k]++; //если
в области только объект
loc2al_i_flag=0;al_j_flag=0;
(file,
"opred_prinadl_o=%i\tonly_ff[%i]=%i\topred_prinadl_f=%i\tonly_oo[%i]=%i\n",opred_prinadl_o,k,only_ff[k],opred_prinadl_f,k,only_oo[k]);
// ШАГ 5: вычисляем среднюю яркость для каждой
области только по пикселям фона[k].r=loc2al_sred_rgb(pf,0,fon_or_object,k); //среднее
по пикселям фона
argb[k].g=loc2al_sred_rgb(pf,1,fon_or_object,k);[k].b=loc2al_sred_rgb(pf,2,fon_or_object,k);
[k].r*=0.3;[k].g*=0.59;
argb[k].b*=0.11;
// ШАГ 5: конец._or_object=1; //теперь
для объекта
// ШАГ 6: вычисляем среднюю яркость для каждой
области только по пикселям объекта
[k].r=loc2al_sred_rgb(pf,0,fon_or_object,k); //среднее
по пикселям объекта
zrgb[k].g=loc2al_sred_rgb(pf,1,fon_or_object,k);[k].b=loc2al_sred_rgb(pf,2,fon_or_object,k);
[k].r*=0.3;[k].g*=0.59;
zrgb[k].b*=0.11;
// ШАГ 6: конец.
// ШАГ 7: переход на следующую итерацию (мнимый,
естественно)
Trgb[k].r=(argb[k].r+zrgb[k].r)/2;[k].g=(argb[k].g+zrgb[k].g)/2;[k].b=(argb[k].b+zrgb[k].b)/2;
// ШАГ
7: конец._prinadl_o=0;_prinadl_f=0;
}
}(file);
//**************** ок
************************(int i=0;i<razm;i++)
{[i].r=0;[i].g=0;[i].b=0;_rgb[i].r=0;_rgb[i].g=0;_rgb[i].b=0;
_rgb[i].r=0;_rgb[i].g=0;_rgb[i].b=0;
[i]=0;[i]=0;
}
=fopen("rezult.txt","w");(rez,"Method:
adapt\n\n");
();_ozhida();();(int
k=0;k<razm;k++)
{(int i=0;i<skok;i++)
{( max_rgb[k].r <
loc2al_img[i][k].r ) max_rgb[k].r=loc2al_img[i][k].r;( max_rgb[k].g <
loc2al_img[i][k].g ) max_rgb[k].g=loc2al_img[i][k].g;( max_rgb[k].b <
loc2al_img[i][k].b ) max_rgb[k].b=loc2al_img[i][k].b;( min_rgb[k].r >
loc2al_img[i][k].r ) min_rgb[k].r=loc2al_img[i][k].r;( min_rgb[k].g >
loc2al_img[i][k].g ) min_rgb[k].g=loc2al_img[i][k].g;( min_rgb[k].b >
loc2al_img[i][k].b ) min_rgb[k].b=loc2al_img[i][k].b;
}
[k]=max_rgb[k].r + max_rgb[k].g +
max_rgb[k].b;[k]=min_rgb[k].r + min_rgb[k].g + min_rgb[k].b;
[k]=0.3*max_rgb[k].r+0.59*max_rgb[k].g+0.11*max_rgb[k].b;[k]=0.3*min_rgb[k].r+0.59*min_rgb[k].g+0.11*min_rgb[k].b;
//принимаем решение об изменении дисперсии
объекта или фона
if(only_oo[k]>=aCols*aRows*0.1)
{[k].r=(mxrgb[k]+mnrgb[k])/2+loc2al_dispers_object;[k].g=(mxrgb[k]+mnrgb[k])/2+loc2al_dispers_object;[k].b=(mxrgb[k]+mnrgb[k])/2+loc2al_dispers_object;
}
{[k].r=(mxrgb[k]+mnrgb[k])/2+loc2al_dispers_fone;[k].g=(mxrgb[k]+mnrgb[k])/2+loc2al_dispers_fone;[k].b=(mxrgb[k]+mnrgb[k])/2+loc2al_dispers_fone;
}=0;=0;=0;
(int kk=0;kk<razm;kk++)
{[kk].r=Trgb[kk].r;[kk].g=Trgb[kk].g;[kk].b=Trgb[kk].b;
}
(rez,"\n\n sector №%i
\n\n",k);(int i=0; i<aRows; i++) //цикл
по
строкам
{(int j=0; j<aCols; j++) //цикл
по
столбцам
{=loc2al_func_glob_porog(ct,k,Trgb); //определение
принадлежности
пикселя
if (flag==1) //установка нового значения
пикселя
{al_pixel_in_fone(ct,k);(rez,"x=%i\ty=%i\tR=%i\tG=%i\tB=%i\tRGB=%lf\n",j,i,pixel[ct].r,pixel[ct].g,pixel[ct].b,0.3*pixel[ct].r+0.59*pixel[ct].g+0.11*pixel[ct].b);
al_img[ct][k].r=cvet_fon;al_img[ct][k].g=cvet_fon;al_img[ct][k].b=cvet_fon;
po++;_pf++;
} //установка нового значения
пикселя
{al_pixel_in_object(ct,k);
al_img[ct][k].r=cvet_object;al_img[ct][k].g=cvet_object;al_img[ct][k].b=cvet_object;
++;_po++;
}++;_ct++;
}
}
(rez,"\n\nPixel_in_object =
%i\nPixel_in_fone = %i\nPixel_in_image = %i\n",po,pf,ct);
al_i_flag=0;al_j_flag=0;
[k].r=loc2al_sred_rgb(pf,0,fon_or_object,k);
//среднее
по
пикселям
фона[k].g=loc2al_sred_rgb(pf,1,fon_or_object,k);[k].b=loc2al_sred_rgb(pf,2,fon_or_object,k);[k].r*=0.3;[k].g*=0.59;[k].b*=0.11;
_or_object=0;
[k].r=loc2al_sred_rgb(pf,0,fon_or_object,k);
//среднее
по
пикселям
объекта[k].g=loc2al_sred_rgb(pf,1,fon_or_object,k);[k].b=loc2al_sred_rgb(pf,2,fon_or_object,k);
[k].r*=0.3;[k].g*=0.59;[k].b*=0.11;[k].r=(argb[k].r+zrgb[k].r)/2;[k].g=(argb[k].g+zrgb[k].g)/2;[k].b=(argb[k].b+zrgb[k].b)/2;
}(rez,"\n
VSEGO:\n\nPixel_in_object = %i\nPixel_in_fone = %i\nPixel_in_image =
%i\n",glob_pf,glob_po,glob_ct);
fclose(rez);
//**************************************************
// ШАГ 8: переписываем все области в сплошной
массив
int count,fun=0,sek=-1,ss=0;
(int k=0; k<razm; k++)
{=0;++;
(sek==a_kol_razb)
{=0;++;
}(int i=0; i<aRows; i++)
{(int j=0; j<aCols; j++)
{=j+aCols*a_kol_razb*i+k*aCols+fun*aCols*(aRows-1)*a_kol_razb; //вычисляем
нужную
область
пикселей_pixel[ss].r=loc2al_img[count][k].r;_pixel[ss].g=loc2al_img[count][k].g;_pixel[ss].b=loc2al_img[count][k].b;++;
}
}
}
// ШАГ
8: конец.
}
};
al_class loc2; //элемент
локальной
обработки
//******************************************************************************
//******************************************************************************//************* класс
дискриминантного критерия **************************//
//******************************************************************************
//******************************************************************************
//*** ТОЛЬКО ВЫЧИСЛЕНИЯ ПОРОГА!!!
class diskr_class{
:diskr_func[255];mat_ozhid_all_image;disp_all_image;p0,p1;m0,m1;klass_disp,raspred_func[255];porog[3];global_flag;
copy_histo(int flag)
{(flag) //выбираем для какой состовляющей
цветового пространства определяем порог
{0: for(int i=0;i<255;i++) raspred_func[i]=histogramma[i][0];
global_flag=0; break;1: for(int i=0;i<255;i++) raspred_func[i]=histogramma[i][1];
global_flag=1; break;2: for(int i=0;i<255;i++) raspred_func[i]=histogramma[i][2];
global_flag=2; break;
}
}
memory()
{= new mRGB[pic[0].nRows *
pic[0].nCols];= new mRGB[pic[0].nRows * pic[0].nCols];
}
mat_ozhid_all() //мат. ожидание
всего изображения
{_ozhid_all_image=0;(int
i=0;i<255;i++)_ozhid_all_image+=i*raspred_func[i];
}
disp_all() //дисперсия
всего изображения
{(int i=0;i<255;i++)
{_all_image+=(i-mat_ozhid_all_image)*(i-mat_ozhid_all_image);
}
}
void
info_everykadr(int
k) //информация
о всем кадре
{all=0;(int
i=0;i<255;i++)+=raspred_func[i];
(int
i=0;i<k;i++)+=raspred_func[i]; //вероятность
p0
(int
i=k+1;i<255;i++)+=raspred_func[i]; //вероятность
p1
0/=all; //нормировка
p1/=all;
for(int
i=0;i<k;i++)+=i*raspred_func[i];
=(mat_ozhid_all_image-m0)/p1; //мат.
ожидания(p0!=0) m0/=p0;
}
void
megklass_disp() //вычисление
межклассовой дисперсии
{_disp=p0*(m0-mat_ozhid_all_image)*(m0-mat_ozhid_all_image)+p1*(m1-mat_ozhid_all_image)*(m1-mat_ozhid_all_image);
}
int
diskrmnt_main(int
what) //главная
функция дискриминантной обработки
{max;porg=0;*f2;=fopen("diskr_info.txt","w");=0;=0;=0;=0;=0;_disp=0;
_histo(what); //получаем
распределение
mat_ozhid_all(); //мат.
ожидание всего изображения
disp_all(); //дисперсия
всего изображения
memory(); //выделение
памяти
for(int i=0;i<255;i++)
{=0;=0;=0;=0;_everykadr(i);_disp();_func[i]=klass_disp/disp_all_image;
}
for(int
i=0;i<255;i++) //вычисляем
абсолютный максимум дискриминантной функции
if(diskr_func[i]>max)
{=diskr_func[i];[global_flag]=i;
}(int i=0;i<3;i++)
{(f2,"porog[%i]=%i\n",i,porog[i]);
}(f2);porog[global_flag];
}
};
//******************************************************************************
//******************************************************************************
//**************** конец класс дискремининтного
критерия *******************//
//******************************************************************************//******************************************************************************
_class diskr; //элемент класса
дискриминантная обработка
//******************************************************************************
//******************************************************************************
//****************************************** класс
адаптивной обработки ******
//******************************************************************************//******************************************************************************adp_class{
public:pxmp;
copy_1D_to_2D()
{ct;** new_mass;_mass = new
mRGB*[pxmp.nRows];(int i=0;i<pxmp.nRows;i++)_mass[i] = new mRGB[pxmp.nCols];
=-1;(int i=0;i<pxmp.nRows;i++)
{(int j=0;j<pxmp.nCols;j++)
{++;_mass[i][j]=pixel[ct];
}
}
}
obl_vich_intensiv(int m, int n, int
obl) //вычисляем
текущее
территориальное
расположение
пикселя
{
int
ct=0;
switch(obl) //определяем
область вокруг центрального пикселя
{
for(int
j=n;j<n+KK+1;j++)
for(int i=m;i<m+1+KK;i++)
{(i!=m && j!=n)
mass_obl[ct]=pxmp.getPixel(i,j);++;
};
1: //нижняя
граница(int
j=n;j<n+KK+1;j++)(int i=m-KK;i<m+1+KK;i++)
{(i!=m && j!=n)
mass_obl[ct]=pxmp.getPixel(i,j);++;
};
3: //правая
граница(int
j=n-KK;j<n+KK+1;j++)(int i=m-KK;i<m+1;i++)
{(i!=m && j!=n)
mass_obl[ct]=pxmp.getPixel(i,j);++;
}
break;
case 2: //правый
нижний угол
for(int j=n;j<n+KK+1;j++)(int
i=m-KK;i<m+1;i++)
{(i!=m && j!=n)
mass_obl[ct]=pxmp.getPixel(i,j);++;
}
break;
case 4: //правый
верхний угол
for(int j=n-KK;j<n+1;j++)(int
i=m-KK;i<m+1;i++)
{(i!=m && j!=n)
mass_obl[ct]=pxmp.getPixel(i,j);++;
};
5: //верхняя
граница(int
j=n-KK;j<n+1;j++)(int i=m-KK;i<m+1+KK;i++)
{(i!=m && j!=n)
mass_obl[ct]=pxmp.getPixel(i,j);++;
}
break;
case 6: //левый
верхний угол
for(int j=n-KK;j<n+1;j++)(int
i=m;i<m+1+KK;i++)
{(i!=m && j!=n)
mass_obl[ct]=pxmp.getPixel(i,j);++;
};
7: //левая
граница(int
j=n-KK;j<n+1+KK;j++)(int i=m;i<m+1+KK;i++)
{(i!=m && j!=n)
mass_obl[ct]=pxmp.getPixel(i,j);++;
};
8: //центральная
область(int
j=n-KK;j<n+1+KK;j++)(int i=m-KK;i<m+1+KK;i++)
{(i!=m && j!=n &&
i>=0 && j>=0) mass_obl[ct]=pxmp.getPixel(i,j);++;
};
}
}
vich_loc_intensiv_tchk() //основная
процедура
адаптивной
обработки
{sred_intens, delta_max,
delta_min,t;*f5;tek;newcolor_o,newcolor_f;null;*px;= new mRGB[pic[0].nCols*pic[0].nRows];tek_intens;max=0,fflag;min=0;po=0,pf=0,ct=0;
_intens=0.0;
_o.r=255; //новый
цвет
объекта_o.g=255;_o.b=255;
_f.r=0; //новый
цвет
фона_f.g=0;_f.b=0;
.r=0;.g=0;.b=0;
oblast=(2*KK+1)*(2*KK+1); //вычисляем
область соседей
for(int i=0;i<oblast-1;i++)
{_obl[i]=null;
}=0;
=fopen("rezult.txt","w"); //файл
результата(rez,"Method:
adapt\n\n");
//обработка
всей
сетки(int
i=0;i<pic[0].nRows;i++)
{(int j=0;j<pic[0].nCols;j++)
{ //различные
ситуации(i==0
&& j==0) obl_vich_intensiv(j,i,0);(i==0
&& j==pic[0].nCols-1) obl_vich_intensiv(j,i,2);(i==0
&& j!=0) obl_vich_intensiv(j,i,1);(j==pic[0].nCols-1
&& i!=pic[0].nRows-1) obl_vich_intensiv(j,i,3);(j==pic[0].nCols-1
&& i==pic[0].nRows-1) obl_vich_intensiv(j,i,4);(i==pic[0].nRows-1
&& j!=0) obl_vich_intensiv(j,i,5);(j==0
&& i==pic[0].nRows-1) obl_vich_intensiv(j,i,6);(j==0
&& i!=0) obl_vich_intensiv(j,i,7);(i!=0
&& j!=0 && i!=pic[0].nRows-1 && j!=pic[0].nCols-1) obl_vich_intensiv(j,i,8);
=pic[0].getPixel(j,i);_intens=0.3*tek.r+0.59*tek.g+0.11*tek.b;
//яркость(int
k=0;k<oblast-1;k++)
{_intens+=0.3*mass_obl[k].r+0.59*mass_obl[k].g+0.11*mass_obl[k].b; //средняя
интенсивность
в
точке
}_intens/=oblast;(sred_intens>max)
max=sred_intens; //максимум(sred_intens<min)
min=sred_intens; //минимум
_max=abs(max-sred_intens); //приращение
max_min=abs(min-sred_intens); //приращение
min
(delta_max>delta_min) t=alfa*(2./3.*min+1./3.*sred_intens); //определяем
параметр
t t=alfa*(1./3.*min+2./3.*sred_intens);
ct++;
( (sred_intens-tek_intens)>t) //условие
принадлежности пикселя объекту
{[0].setPixel(j,i,newcolor_f);(rez,"x=%i\ty=%i\tR=%i\tG=%i\tB=%i\tRGB=%lf\n",j,i,tek.r,tek.g,tek.b,tek_intens);++;
}
{[0].setPixel(j,i,newcolor_o);++;
}++;
}
}
(rez,"\n\nPixel_in_object =
%i\nPixel_in_fone = %i\nPixel_in_image = %i\n",po,pf,ct);(rez);
}
everything()
{_1D_to_2D();_loc_intensiv_tchk();
}
};
//******************************************************************************
//******************************************************************************
//***********************************
конец
класс
адаптивной
обработки
*********
//******************************************************************************
//******************************************************************************
_class lc; //элемент класса адаптивная
обработка
//процедура непосредственного перераспределения
пикселей к классам для дискриминантного метода
int func_adpt_porog(int num,int
porog[3])
{rez=0;
(pixel[num].r<=porog[0]
&& pixel[num].g<=porog[1] && pixel[num].b<=porog[2])
rez=1;rez=0;rez;
}
adpt_segmentation()
{ct=0;cvet_fon,cvet_object,po,pf,flag;
_fon=0;_object=255;=0;=0;=0;_flag=0;_flag=0;(int
i=0; i<pic[0].nRows;i++) //цикл
по
строкам
{(int j=0; j<pic[0].nCols; j++) //цикл
по
столбцам
{=func_adpt_porog(ct,adpt_porog); //определение
принадлежности
пикселя
if (flag==1) //установка нового
значения пикселя (фон)
{[whichPic].pixel_in_fone(ct);
(rez,"x=%i\ty=%i\tR=%i\tG=%i\tB=%i\tRGB=%lf\n",j,i,pixel[ct].r,pixel[ct].g,pixel[ct].b,0.3*pixel[ct].r+0.59*pixel[ct].g+0.11*pixel[ct].b);[ct].r=cvet_fon;[ct].g=cvet_fon;[ct].b=cvet_fon;
po++;
} //установка
нового значения пикселя (объект)
{[whichPic].pixel_in_object(ct);
[ct].r=cvet_object;[ct].g=cvet_object;[ct].b=cvet_object;++;
}++;
}
}(rez,"\n\nPixel_in_object =
%i\nPixel_in_fone = %i\nPixel_in_image = %i\n",po,pf,ct);
}
//инвертирование изображения
void
invert()
{
int
ct;
int c=1;=-1;(int
i=0;i<pic[0].nRows;i++)
{(int j=0;j<pic[0].nCols;j++)
{++;[ct].r=255-pixel[ct].r;[ct].g=255-pixel[ct].g;[ct].b=255-pixel[ct].b;
}
}
}
//построение
гистограммbuild_histogramma()
{
(int i=0;i<256;i++)(int
j=0;j<3;j++)
{[i][j]=0;
}(int
i=0;i<pic[whichPic].nCols*pic[whichPic].nRows;i++)
{[pixel[i].r][0]++;[pixel[i].g][1]++;[pixel[i].b][2]++;
}
}
//****** обработка
вывода
на
экран
гистограммы
R (Open GL) *********************myDisplayHistoR(void)
{a=0;=256+otstyp;(1.0,1.0,1.0,0.0);(GL_COLOR_BUFFER_BIT);f(1.0,0.0,0.0);(GL_LINES);(int
i=otstyp;i<a;i++)
{i(i,0);i(i,histogramma[i-otstyp][0]/delR);
}();();
}
//********** обработка
действий
клавиатурой
(Open GL) *******//
//основная идея запуска каждой из обработок
void myKeys(unsigned char key, int
x, int y)
{(key)
{'q': exit(0);'s':
whichPic=1-whichPic; break;'p': pic[0].read(0,0,200,200); break;'a':
loc2.loc2al_glob_porog(); what_draw=2; break; //локальная
пороговая
обработка'i':
pic[whichPic].copy_image(pixel,pixel2); what_draw=1; break; //восстановление
исходного
изображения'g':
glob_porog(); what_draw=1; break; //глобальная
пороговая
обработка'l':
lc.everything(); what_draw=1; break; //адаптивная
пороговая
обработка'd':
rez=fopen("rezult.txt","w");(rez,"Method:
diskriminant\n\n");(int
i=0;i<3;i++)
//вычисляем порог для каждой из составляющих R,G
и B
adpt_porog[i]=diskr.diskrmnt_main(i);
_segmentation(); //дискриминантная
сегментация_draw=1;(rez);;'e':
etalon_videl_only_black(); what_draw=1; break; //выделение
эталона'o':
invert(); what_draw=1; break; //инвертирование
}(); //обновления
экрана
(Open GL)
}
}
Примеры обработки событий (Windows
Forms):
#pragma once
#include "windows.h"
#include "iostream"
#include <conio.h>
#include "PROG.CPP" //основной файл
со всеми важнейшими классами и обработками изображения
#include "FormHelp.h" //библиотека
ПОМОЩЬ
#include "stdafx.h"
#include "ShowImage.h" //библиотека
изображения (вывода на экран)
#include "ok.h" //библиотека
отдельной глобальной обработки
#include "histo.h" //библиотека
гистограмм
#include "loc.h" //библиотека
отдельной локальной обработки
#include "Diskr.h" //библиотека
отдельной обработки методом дискриминантного критерия
#include "Adapt.h" //библиотека
отдельной адаптивной обработки
using namespace std;
Interface { //пространство ИНТЕРФЕЙС
//использование функций, классов и т.д.
следующих компонент:namespace System;namespace System::ComponentModel;namespace
System::Collections;namespace System::Windows::Forms;namespace
System::Data;namespace System::Drawing;
ref class Form1 : public
System::Windows::Forms::Form
{:(void)
{
(); //параметры
основной формы
//
//TODO: Add the constructor code
here
//
}:
/// <summary>
/// Clean up any resources being
used.
/// </summary>
~Form1()
{(components)
{components;
}
}
private:
System::Windows::Forms::Button^ button1;: System::Windows::Forms::GroupBox^
groupBox1;: System::Windows::Forms::Button^ OpenImage;:
System::Windows::Forms::TextBox^ ImageTextBox;
:
System::Windows::Forms::OpenFileDialog^ openFileDialog1;:
System::Windows::Forms::GroupBox^ groupBox2;: System::Windows::Forms::GroupBox^
groupBox3;
//и так далее. Здесь определяются
все объекты, расположенные на форме.
#pragma region Windows Form Designer
generated code
/// <summary>
/// Required method for Designer
support - do not modify
/// the contents of this method with
the code editor.
/// </summary>
//генерируется код для обработки
всех свойств всех объектовInitializeComponent(void)
{
//инициализация всех
объектов>button1 = (gcnew System::Windows::Forms::Button());>groupBox1 =
(gcnew System::Windows::Forms::GroupBox());>OpenImage = (gcnew
System::Windows::Forms::Button());
// button1
//>button1->BackColor =
System::Drawing::Color::Azure;>button1->Location =
System::Drawing::Point(0, 14);>button1->Name = L"button1";>button1->Size
= System::Drawing::Size(139, 21);>button1->TabIndex =
0;>button1->Text = L"Описание
программы";>button1->UseVisualStyleBackColor =
false;>button1->Click += gcnew System::EventHandler(this, &Form1::button1_Click);
//и так далее. Здесь определяются
все основные свойства объектов, расположенных на форме.
//пример обработка нажатия кнопки
"кнопка помощь": System::Void button1_Click(System::Object^ sender,
System::EventArgs^ e) {
FormHelp ^f = gcnew FormHelp;>ShowDialog();
}
//пример обработки нажатия кнопки "показать
изображение": System::Void button2_Click(System::Object^ sender,
System::EventArgs^ e) {
//*************************************************
//”ручной” перевод из типа String^ в Char*
//*************************************************b=1;^
fn=openFileDialog1->FileName;(fn=="") b=0;z;*r1,*g1,*b1;
*qwerty,qw;wq;l;
=openFileDialog1->FileName->Length;=new
char[l];(int
i=0;i<l;i++){[i]=Convert::ToInt16(openFileDialog1->FileName[i]);
}
kol=0;=qwerty[2];(int i=0;i<l;i++)
{(qwerty[i]==qw)++;
}*ir;= new char[l+kol+1];(int
i=0,j=0;i<l+kol;i++,j++)
{[i]=qwerty[j];(ir[i]==qw) { i++; ir[i]=qw; }
}[l+kol]='\0';
//*************************************************
//конец ”ручного” перевода из типа String^ в
Char*
//*************************************************
::filename=ir; //передаем в
присоединенную PROG.CPP параметр
( checkBox1->Checked==1)
{=1;
g=globa::main2();
= new
int[globa::pic[globa::whichPic].nCols*globa::pic[globa::whichPic].nRows];= new
int[globa::pic[globa::whichPic].nCols*globa::pic[globa::whichPic].nRows];= new
int[globa::pic[globa::whichPic].nCols*globa::pic[globa::whichPic].nRows];
ct=-1;(int
i=0;i<globa::pic[globa::whichPic].nRows;i++) //если есть
инвертирование изображения
{(int
j=0;j<globa::pic[globa::whichPic].nCols;j++)
{++;::pixel[ct].r=255-globa::pixel[ct].r;::pixel[ct].g=255-globa::pixel[ct].g;::pixel[ct].b=255-globa::pixel[ct].b;
}
}=-1;(int
i=0;i<globa::pic[globa::whichPic].nRows;i++)
{(int j=0;j<globa::pic[globa::whichPic].nCols;j++)
{++;[ct]=globa::pixel[ct].r;[ct]=globa::pixel[ct].g;[ct]=globa::pixel[ct].b;
}
}
}
^si = gcnew
ShowImage(b,z,globa::pic[globa::whichPic].nRows,globa::pic[globa::whichPic].nCols,r1,g1,b1,fn); //создаем
изображение и вызываем функцию на другой форме(b==1) si->ShowDialog();
}
//пример вывода изображения на экран с
использованием Windows Forms и //сформированного массива pixel[] в программе
PROG.CPPref class ShowImage : public System::Windows::Forms::Form
{:(int a, int y,int CC, int RR,int *r, int *g,
int *b, String^ filename)
{H,W;(a==1)
{^ MyImage;= gcnew Bitmap(filename); //создаем
тип Bitmap^ MyImage2;= gcnew
Bitmap(filename);=MyImage->Height;=MyImage->Width;
(y==1)
{ct=RR*CC;(int i=0;i<CC;i++)
{(int j=0;j<RR;j++)
{-;>SetPixel(RR-j- //устанавливаем пиксели 1,i,Color::FromArgb(r[ct],g[ct],b[ct]));
}
}
}(W,H);>ClientSize = System::Drawing::Size(
W, H );>Image = dynamic_cast<Image^>(MyImage);
}
if(a==0) {^
message;="Ошибка!";::Show("Файл не был выбран!",message);
}
}
//пример вывода сообщения на экран: System::Void
Developer_Click(System::Object^ sender, System::EventArgs^ e) {^
message;="Разработчик:";::Show("Bachelor Version 2.2\nКартавцев
А.М., пм-51 (2009г.)",message);
}
//основная программа запуска
#include "stdafx.h"
#include "Form1.h"
namespace Interface;
[STAThreadAttribute]main(array<System::String
^> ^args)
{b;
// Enabling Windows XP visual effects before any
controls are created
//b=main2();
::EnableVisualStyles();::SetCompatibleTextRenderingDefault(false);
// Create the main window and run it::Run(gcnew
Form1()); //запускаем основную форму
0;
}