Как создать свою ГИС с помощью GIS ToolKit Active

Урок 9. Функции для работы c мультиспектральными изображениями

Автор: Дарья Лунченко

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

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

В данном уроке мы попробуем разобраться, как с помощью функций MAPAPI работать с такими изображениями.

По окончанию урока наше приложение будет уметь:

  • импортировать мультиспектральные снимки в формат .rsw;
  • выбирать текущий редактируемый растр;
  • получать значение яркости пикселя растра в каждом канале;
  • преобразовывать панхроматический растр к натуральным цветам;
  • строить гистограмму распределения значений яркостей пикселей мультиспектрального растра по его каналам;
  • экспортировать гистограмму в файл .xls, .xlsx;

Внешний вид приложения представлен на рис. 1.

Рисунок 1 - Внешний вид приложения

Скачать рабочий образец программы, и ее исходный код можно на страничке "Дополнительные материалы к уроку 9". Если у вас не установлен GIS ToolKit Active, то для запуска приложения вам потребуется загрузить библиотеки GIS ToolKit, и выполнить их регистрацию. Все необходимые библиотеки и короткая инструкция размещены на этой же странице.

 

1. Добавление кнопок на панель инструментов

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

Рисунок 2 - Внешний вид панели инструментов

2. Описание событий, соответствующих кнопкам на панели инструментов

2.1.Открыть мультиспектральный растр

Данная функция является аналогом функции загрузки обычного графического изображения (урок №8,п. 2.1) и позволяет загрузить мультиспектральный снимок в растровый формат ГИС "Панорама" RSW (рис. 3). При добавлении мультиспектральных снимков в диалоге загрузки необходимо отметить поле "Не копировать исходное изображение в RSW файл", для прямого доступа к исходному снимку.

Рисунок 3 - Диалог загрузки растровой карты

Для загрузки растра:

  • создадим новый класс FMultiSpecImage.cs, в который поместим функции по работе с мультиспектральными растрами;
  • при нажатии на кнопку "Открыть мультиспектральный растр", создадим событие ButtonActionMultiSpecTool, в котором определяем функцию OpenMultiSpecImageFunc;
  • используем, импортируемую ранее (урок№8) функцию загрузки графического изображения в растровую карту DialogLoadImageToRsw;
  • если был выбран формат растровых карт, в функции OpenMultiSpecImageFunc, вызываем диалог открытия данных OpenMapFileDialog, и с помощью импортируемой функции mapRstIsAccessTiff, запрашиваем тип растра (0- обычный растра, 1 - растр-пустышка с прямым доступом к TIFF файлу);

  • если был выбран мультиспектральный снимков в формате TIFF, то вызываем диалог загрузки графического изображения в растровую карту RSW, после чего отрываем или добавляем данные;

2.2 Выбор текущего мультиспектрального растра

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

Рисунок 4 - Выбор текущего растра

Реализация данной функции:

  • добавляем на форму из панели элементов стандартный компонент для отображения рамки и подписи вокруг элемента GroupBox, и помещаем в него компонент - раскрывающийся список ComboBox;
  • определяем функцию SetCurrentMultiSpecFunc, в которой при нажатии на кнопку "Выбор текущего мультиспектрального растра", отображаем выпадающий список, заполненный с помощью функции MultiSpecComboBox.Items.Insert;

  • при изменении текущего растра в выпадающем списке, определяем выбранное значение MultiSpecComboBox.SelectedItem, и устанавливаем соответствующий номер растра;

2.3 Получение значения яркости пикселя в каждом канале растра

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

  • добавляем на форму в элементе StatusStrip, который используем для отображения координат, toolStripStatusLabel для отображения реально записанных значений яркости пикселя;
  • в классе FMapAPI.cs импортируем функции mapGetRstMeterInElementX, mapGetRstMeterInElementY -для определения размера элемента растра по оси X и Y, а также функцииmapGetRstBandPixel_Tiff - для определения яркости пикселя изображения в канале растра, mapGetRstBandCount_Tiff - для определения количества каналов растра;

  • определяем координаты точки нахождения курсора в метрах, габариты растра и размер элемента растра по оси X и Y, для расчета значения текущей точки в пикселях растра;

  • в функцию mapGetRstBandPixel_Tiff передаем номер текущего растра и координаты точки в пикселях растра, меняя местами X, Y, так как в системе координат в метрах оси расположены Y(слева направо), X (сверху вниз), а в системе координат в пикселях наоборот;
  • с помощью функции mapGetRstBandCount_Tiff определяем количество каналов и выводим значения яркостей пикселя в каждом канале в окно статуса;

2.4 Преобразование панхроматического растра к натуральным цветам

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

Данная функция требует наличия двух растров одной и той же территории: мультиспектральный растр с более низким разрешением и панхроматический растр с более высоким разрешением с одного и того же аппарата ДЗЗ или двух разных аппаратов. При этом исходное панхроматическое изображение может быть растром rsw или растром в формате GeoTiff. В результате преобразования пользователь получит растровое изображение в формате .rsw, с разрешением панхроматического растра но в естественных цветах (рис. 5).

Рисунок 5 - Преобразование панхроматического растра к натуральным цветам

Данный алгоритм основывается на преобразовании Бровея, в котором используется красный R, зеленый G, синий B каналы мультиспектрального снимка и канал панхроматического снимка для вычисления новых значений RGB:

R_out=R_in/((R_in+G_in+B_in))*Pan ,(1.1)

G_out=G_in/((R_in+G_in+B_in))*Pan ,(1.2)

B_out=B_in/((R_in+G_in+B_in))*Pan ,(1.3)

гдеR_out,G_out,B_out- новые значения для каналов R,G,B;

R_in,G_in,B_in- значения каналов R,G,B мультиспектрального снимка;

Pan-значение канала панхроматического снимка.

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

  • выбрать исходный мультиспектральный, панхроматический растр и растр для сохранения результата из растров загруженных в проект;
  • выбрать каналы мультиспектрального снимка, которые будут использоваться в преобразовании как красный R, зеленый G и синий B.
  • запустить преобразование, нажав кнопку "Выполнить" (рис. 6).

Рисунок 6 - Диалог преобразования панхроматического растра

Реализация:

  • создадим новую форму MultiPanchrom.cs, добавим на неё стандартные элементы Label, ComboBox, TextBox, Button (рис. 7);

Рисунок 7 - Добавление элементов на форму

  • в классе FMultiSpecImage.cs определим функцию GetTransformPanParam, в которой, используя свойствоComboBoxBox.Items.Insert, заполняем списки для выбора растров, после чего отображаем форму диалога MultiPanchrom;

  • при выборе пользователем в диалоге панхроматического растра, с помощью функции mapRstIsAccessTiff определяем тип растра, если растр не "пустышка", узнаем количество каналов - mapGetRstBandCount_Tiff, если их не больше одного, то устанавливаем флаг успешного выбора панхроматического растра;

  • при выборе пользователем в диалоге мультиспектрального растра, с помощью функции mapRstIsAccessTiff определяем тип растра, если растр не "пустышка", узнаем количество каналов - mapGetRstBandCount_Tiff, если их больше или равно 3, то устанавливаем флаг успешного выбора мультиспектрального растра и заполняем ComboBox для выбора пользователем каналов R,G,B;

  • добавляем на форму компонент диалога для сохранения файлаsaveFileDialog1, и вызываем его, при нажатии на кнопку ChooseResultImage, после успешного выбора файла, устанавливаем в TextBox имя растра и делаем активной кнопку "Выполнить";

  • по нажатию на кнопку "Выполнить" запускаем функцию по созданию нового растра CreateResultRst;
  • в классе FMapAPI.cs импортируем функцию mapGetRstProjectionData- для получения данных о проекции панхроматического растра, mapGetRstPrecision - для запроса разрешения растра, mapCreateAndAppendRstEx - для создания файла растрового изображения;

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

  • запрашиваем данные о проекции панхроматического растра, его разрешении, масштабе и создаем на их основе с помощью функции mapCreateAndAppendRstEx результирующий растр;

  • определяем функцию для преобразования панхроматического изображения к натуральным цветам TransformPanFunc;

Примечание: так как спутниковые изображения могут иметь радиометрическое разрешение большее, чем 8 бит/пиксель (0-255 оттенков), например, как в нашем случае - 16 бит/пиксель (0-65536 оттенков), что невозможно отобразить на экране компьютера, то для показа таких изображений в ядре системы реализована специальная функция, которая создает таблицы подмены реальных значений яркости пикселей снимка, значениями вычисленными по гистограмме (табл. 1). Программисту эта возможность доступна посредством функции mapGetRstLookupTable_Tiff;

Таблица 1 - Таблица подмены реальных значений яркости пикселей снимка

  • в классе FMapAPI.cs импортируем функцию mapGetRstLookupTable_Tiff;

  • получаем таблицы преобразования цветов для R,G,B каналов мультиспектрального растра и для канала панхроматического растра;

  • определяем цикл по ширине и высоте созданного растра в пикселях, в котором определяем координаты x, y в метрах, соответствующие текущему положение центра пикселя y(h), x(w) панхроматического растра;

  • далее делаем обратное преобразование и определяем значение в пикселях мультиспектрального растра y(hm), x(wm), соответствующие рассчитанным координатам центров пикселей x1, y1 панхроматического растра;

Примечание: данное преобразование необходимо в связи с тем, что панхроматический и мультиспектральный растры имеют разное разрешение, таким образом, взяв в анализ цвет двух пикселей панхроматического растра с разрешением 15 м, необходимо исследовать один пиксель мультиспектрального снимка с разрешением 30 м;

  • ранее мы запомнили является ли панхроматический растр "пустышкой", если не является, то определяем яркость пикселя, используя функцию mapGetRstPoint, в другом случае mapGetRstBandPixel_Tiff;

  • определяем значение яркостей пикселя по выбранным пользователем каналам для R,G,B и подсчитываем их сумму;

  • рассчитываем по формулам (1.1-1.3) новые значения яркостей пикселя для результирующего растра, подставляя при этом, в случае если растр является с прямым доступом к TIFF файлу, значения яркостей в каналах R, G, B и панхроматического канала в таблицы преобразования цвета, полученные нами ранее;

  • определяем полученное новое значение цвета в формате COLORREF (урок 8, п.2.8 ), с помощью функций mapPutRstPoint, mapSaveRst записываем новое значение яркости пикселя в результирующий растр и сохраняем изменения.

2.5 Построение гистограммы участка растра

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

Гистограмма представляет собой график по оси X, которого определены значения реально записанных яркостей пикселей растра на границах диапазонов, по оси Y - количество попаданий соответствующих значений яркости анализируемого участка в данные диапазоны (рис.8).

Рисунок 8 - Диалог гистограммы выбранного участка растра

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

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

При нажатии на кнопку "Назад", пользователю предлагается заново выбрать область для анализа (рис.9).

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

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

Рисунок 9 - Выбор области для построения гистограммы

Реализация данной функции:

  • создадим новую форму Gisrogramma.cs, добавим на неё стандартные элементы Label, ComboBox, Chart, CheckedListBox, Button (рис. 10);

Рисунок 10 - Добавление элементов на форму

  • добавляем на главную форму элемент GroupBox и два CheckBox, для меню выбора области при построении гистограммы;
  • при нажатии на кнопку выбора по области GistoBySetArea с помощью функции mapCreateAndAppendTempSite создаем и добавляем временную карту, и активируем режим выбора области MapSelectRect1.StartAction;

  • при успешном выборе области, определяем габариты растра и проверяем находится ли выбранный фрагмент в пределах растра;

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

  • переходим к функции построения гистограммы Gistogramm, в которой рассчитываем ширину и высоту выбранной области и записываем в список ColorList начальное нулевое значение яркости пикселя, полученного с помощью mapGetRstBandPixel_Tiff;

  • определяем цикл по высоте и ширине выбранного участка, в котором с помощью функции mapGetRstBandPixel_Tiff получаем значение яркости пикселя, далее проверяем содержит ли список ColorList данное значение, если да, то увеличиваем счетчик количества данного значения, в другом случаем добавляем новое значение в список;

  • находим максимальное и минимальное значения в списке ColorList;

  • рассчитываем шаг гистограммы по оси X, интервалы гистограммы и записываем значения диапазонов в список ShagList, определяем количество значений, попадающих в каждый диапазон в %, и записываем их в cписок KolList;

  • устанавливаем ширину столбцов гистограммы, и заполняем график Chart значениями из полученных списков ShagList, KolList;

  • при нажатии на кнопку выбор по объекту, активируем режим выбора в точке, далее определяем габариты объекта mapObjectFrame и растра mapGetActualRstFrame, проверяя чтобы объект находился внутри поля снимка;

  • вызываем функцию установки параметров как при выборе объекта по области;
  • в классе FMapAPI.cs вызываем функцию mapCheckInsidePoint для определения взаимного нахождения объекта и точки, которая возвращает: 1 - точка внутри объекта(подобъекта), 2 - точка за пределами объекта(подобъекта), 3 - точка совпадает с точкой метрики, 4 - точка лежит на отрезке;
  • в функции построения гистограммы Gistogramm, рассчитываем значение ширины и высоты объекта по его габаритам, и с помощью функции mapCheckInsidePoint определяем начальное значение списка ColorList;

  • с помощью функции mapCheckInsidePoint проверяем в цикле, входит ли точка в объект, если да, продолжаем заполнять массив ColorList также как при выборе объекта по области.

3. Экспорт гистограммы в файл Microsoft Excel

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

Для начала нам необходимо добавить ссылку на COM объект Excel. Для этого заходим в меню "Проекты"->"Добавить ссылку"->Вкладка "COM"->"Microsoft.Office.Interop.Excel" (рис.11).

Рисунок 11 - Добавление ссылки на объект Excel

При использовании .Net сборок взаимодействия с приложениями Microsoft Office нам, после добавления ссылки на Microsoft.Office.Interop.Excel , потребуется введение псевдонима пространства имен Excel: using Excel = Microsoft.Office.Interop.Excel, что в будущем позволит нам избежать конфликта между пространствами имен.

Теперь нам стала доступна работа с объектной моделью Excel.В Excel есть большое количество объектов, но начнем мы свое знакомство с следующих базовых объектов: Application, Workbook, Worksheet, Range.

Объект Application является оболочкой всего приложения, а каждый объект Workbook (книга) содержит набор объектов Worksheet (лист). В свою очередь объект Range является основным абстрактным представлением ячеек, позволяющим работать с отдельными ячейками или группами ячеек.

В нашем приложении экспорт в файл Excel, происходит посредством нажатия кнопки в диалоге построения гистограммы "Экспорт в .xls". После чего в соседнем окне открывается приложение Microsoft Excel, содержащее один лист с таблицей значений диапазонов построения гистограммы и количеством попадания яркостей в %, и график гистограммы по выбранному каналу (рис. 12).

Рисунок 12 - Вид экспортируемого файла

Перейдем к реализации данной функции:

  • добавляем на форму Gistogramm.cs элемент - диалог сохранения данных saveFileDialog1;
  • запускаем диалог saveFileDialog1, при успешном сохранении файла, создаем объект Application, представляющий доступ к другим объектам Excel;
  • так как некоторые методы Excel принимают необязательные параметры, которые не поддерживаются в C#, то создаем объект с отсутствующим значением Type.Missing;
  • создаем новую рабочую книгу xlWorkBook и получаем ссылку на первый лист книгиworkSheet;

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

  • создаем объект- диаграмму ChartObjects на рабочем листе worksheet, устанавливаем ее размер, и делаем ее активной;
  • с помощью свойства SerriesCollection, создаем ряд диаграммы, определяем значения ряда по оси X и значения, представляющие коллекцию ряда (ось Y);

  • устанавливаем автоподбор ширины и высоты столбцов, а также вид гистограммы XlChartType.xlColumnClustered (в виде столбцов), и с помощью свойства AxisTitle. Text, задаем название осей гистограммы;
  • устанавливаем ActiveChart.HasLegend в false, тем самым отменяя наличие легенды у графика гистограммы, и с помощью свойства xlWorkBook.SaveAs, сохраняем полученную книгу и передаем управлению пользователю, отображая файл Excel в соседнем окне;

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

В следующем уроке мы будем разбираться, как обеспечить взаимодействие нашей программы с внешней СУБД.

Смотреть: Дополнительные материалы к уроку 9