Опубликован: 02.09.2013 | Доступ: свободный | Студентов: 429 / 54 | Длительность: 19:27:00
Самостоятельная работа 2:

Базовые операции обработки изображений

3. Программная реализация

3.1. Разработка консольного редактора изображений

3.1.1. Требования к приложению

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

  1. Организация диалога с пользователем. Предполагается вывод перечня пунктов меню (загрузка изображения и набор операций) и возможность выбора определенной операции. Отметим, что программа должна обеспечивать многократное выполнение различных операций.
  2. Отображение исходного изображения.
  3. Отображение результата применения операции.
  4. Контроль корректности вводимых пользователем данных.
3.1.2. Структура консольного приложения

Сначала необходимо создать и настроить проект в среде Mcrosoft Visual Studio. Процедура подробно была описана ранее в работе "Сборка и установка библиотеки OpenCV. Использование библиотеки в среде Microsoft Visual Studio", поэтому в данном разделе остановимся на разработке структуры приложения. Консольное приложение будет состоять из модуля, содержащего вызов функций OpenCV для обработки изображений, и файла исходного кода основной функции.

Для упрощения разработки введем несколько констант:

  • kMenuTabs – количество пунктов меню (фактически число допустимых операций);
    const int kMenuTabs = 12; 
  • menu – массив строк, содержащий описание пунктов меню;
    const char* menu[] =  
    { 
        "0 - Read image",  
        "1 - Apply linear filter",  
        "2 - Apply blur(...)", 
        "3 - Apply medianBlur(...)", 
        "4 - Apply GaussianBlur(...)", 
        "5 - Apply erode(...)", 
        "6 - Apply dilate(...)", 
        "7 - Apply Sobel(...)", 
        "8 - Apply Laplacian(...)", 
        "9 - Apply Canny(...)", 
        "10 - Apply calcHist(...)", 
        "11 - Apply equalizeHist(...)" 
    }; 
  • winNames – массив строк, содержащий названия окон, которые будут использованы при отображении результата выполнения той или иной операции;
    const char* winNames[] =  
    { 
        "Initial image",  
        "filter2d",  
        "blur", 
        "medianBlur", 
        "GaussianBlur", 
        "erode", 
        "dilate", 
        "Sobel", 
        "Laplacian", 
        "Canny", 
        "calcHist", 
        "equalizeHist" 
    }; 
  • maxFileNameLen – максимальная длина строки, содержащей название файла с изображением;
    const int maxFileNameLen = 1000; 
  • escCode – код символа ESC для организации выхода из приложения.
    const int escCode = 27; 

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

  1. Выбор пункта меню. Отметим, что выбор операции обработки изображения не должен быть доступен до тех пор, пока оно не будет загружено. Реализуется посредством функции chooseMenuTab, которая обеспечивает печать пунктов меню с использованием функции printMenu, контроль ввода данных и загрузку изображения с помощью функции библиотеки OpenCV loadImage.
  2. Применение операции обработки изображения, отображение исходного и результирующего изображений. Выполняется при вызове функции applyOperation.
  3. Ожидание нажатия произвольной клавиши для продолжения работы приложения, либо нажатия ESC для выхода из приложения. Для реализации ожидания используется встроенная функция OpenCV waitKey.
void printMenu(); 
void chooseMenuTab(int &activeMenuTab, Mat &srcImg); 
void loadImage(Mat &srcImg); 
 
int main(int argc, char** argv) 
{ 
    Mat srcImg; // исходное изображение 
    char ans; 
    int activeMenuTab = -1; 
    do 
    { 
        // вызов функции выбора пункта меню 
        chooseMenuTab(activeMenuTab, srcImg); 
        // применение операций 
        applyOperation(srcImg, activeMenuTab); 
        // вопрос о необходимости продолжения 
        printf("Do you want to continue? ESC - exit\n"); 
        // ожидание нажатия клавиши 
        ans = waitKey(); 
    } 
    while (ans != escCode); 
    destroyAllWindows(); // закрытие всех окон 
    srcImg.release(); // освобожение памяти 
    return 0; } 
    

Перейдем к реализации необходимых функций.

  1. printMenu – функция вывода пунктов меню на консоль. Реализуется в виде прохода по элементам константного массива, содержащего описания пунктов меню.
    void printMenu() 
    { 
        int i = 0; 
        printf("Menu items:\n"); 
        for (i; i < kMenuTabs; i++) 
        { 
            printf("\t%s\n", menu[i]); 
        } 
        printf("\n"); 
    } 
    
  2. chooseMenuTab – функция выбора пункта меню. Функция выполняет запрос ввода идентификатора пункта меню до тех пор, пока не будет введено корректное значение. Заметим, что операции обработки изображения не могут быть выбраны, пока не загружено изображение. Функция возвращает индекс выбранного меню activeMenuTab и загруженное изображение srcImg.
    void chooseMenuTab(int &activeMenuTab, Mat &srcImg) 
    { 
        int tabIdx; 
        while (true) 
        { 
            // print menu items 
            printMenu(); 
            // get menu item identifier to apply operation 
            printf("Input item identifier to apply \ 
                    operation: "); 
            scanf("%d", &tabIdx); 
            if (tabIdx == 0) 
            { 
                // read image 
                loadImage(srcImg);             
            } 
            else if (tabIdx >=1 && tabIdx < kMenuTabs &&
                     srcImg.data == 0) 
            { 
                // read image 
                printf("The image should be read to apply\ 
                        operation!\n"); 
                loadImage(srcImg); 
            } 
            else if (tabIdx >=1 && tabIdx < kMenuTabs)         { 
                activeMenuTab = tabIdx; 
                break; 
            } 
        } 
    } 
    
  3. loadImage – функция загрузки изображения. Функция реализована в виде цикла, в котором выполняется запрос на ввод полного имени изображения и контроль корректности операции чтения изображения. Возвращает загруженное изображение srcImg.
    void loadImage(Mat &srcImg) 
    { 
        char fileName[maxFileNameLen]; 
        do  
        { 
            printf("Input full file name: "); 
            scanf("%s", &fileName); 
            srcImg = imread(fileName, 1); 
        } 
        while (srcImg.data == 0);     
        printf("The image was succesfully read\n\n"); 
    } 
    
  4. applyOperation – функция применения операции обработки изображения. Принимает на вход исходное изображение src и индекс операции operationIdx . Функция содержит оператор множественного выбора, предполагается, что в зависимости от выбранной операции выполняется вызов той или иной функции обработки с предварительным вводом входных параметров этих функций. Далее осуществляется отображение исходного и результирующего изображений. Объявление и реализацию данной функции поместим в отдельный модуль.
    int applyOperation(const Mat &src, const int operationIdx) 
    { 
        char key = -1; 
        Mat dst; 
        switch (operationIdx) 
        { 
        case 1: 
            { 
                // TODO: "1 - Apply linear filter" 
                break; 
            } 
        // TODO: Apply another operations (from 2 to 11) 
        } 
        // show initial image 
        namedWindow(winNames[0], 1);     imshow(winNames[0], src); 
     
        // show processed image 
        namedWindow(winNames[operationIdx]); 
        imshow(winNames[operationIdx], dst); 
     
        return 0; 
    } 
    

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

Диалог с пользователем

Рис. 9.12. Диалог с пользователем
3.2. *Разработка редактора изображений с графическим интерфейсом с использованием функций OpenCV, реализованных на базе Qt

Разработка редактора изображений с графическим интерфейсом на базе Qt требует выполнения ряда предварительных действий:

  1. Установка библиотек Qt. Для установки необходимо загрузить Qt libraries 4.x for Windows (VS 2010) с официальной страницы проекта [11] и далее следовать подсказкам инсталлятора.
  2. Сборка исходных кодов библиотеки OpenCV с опцией ( -D WITH_QT=YES ), предусматривающей возможность последующего использования интерфейсных компонент на базе Qt. Подробнее процедура сборки OpenCV описана в лабораторной работе "Сборка и установка библиотеки OpenCV. Использование библиотеки в среде Microsoft Visual Studio". Отметим, что установочный файл содержит сборку исходных кодов, не предусматривающую возможность использования Qt-компонент.
  3. Создание консольного приложения в среде Microsoft Visual Studio и установка свойств проекта, обеспечивающих использование функционала библиотеки OpenCV.

После предварительной подготовки инфраструктуры необходимо выполнить создание и настройку проекта в Visual Studio по схеме, описанной ранее. Далее можно использовать все доступные функции библиотеки OpenCV, реализованные на базе Qt [12]. Количество доступных функций ограничено, тем не менее, для создания минимального графического интерфейса предоставляемого набора вполне достаточно: создание окон с базовым набором операций просмотра (сохранение, масштабирование изображения и т.п., рис.9.13), создание кнопочных элементов, полос прокрутки и др.

Создание окна просмотра изображения с использованием  функции namedWindow, реализованной на базе Qt

Рис. 9.13. Создание окна просмотра изображения с использованием функции namedWindow, реализованной на базе Qt

Читателю предлагается самостоятельно продумать структуру приложения и разработать его программную реализацию.

Андрей Терёхин
Андрей Терёхин

Нахожу в тесте вопросы, которые в принципе не освещаются в лекции. Нужно гуглить на других ресурсах, чтобы решить тест, или же он всё же должен испытывать знания, полученные в ходе лекции?

Демянчик Иван
Демянчик Иван

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

" Искомый объект можно описать с помощью фильтра F= \lbrace f_{x',y'},x' \in \lbrace0, ...,w_f \rbrace , y' \in \lbrace 0,...,h_f \rbrace \rbrace "