Нахожу в тесте вопросы, которые в принципе не освещаются в лекции. Нужно гуглить на других ресурсах, чтобы решить тест, или же он всё же должен испытывать знания, полученные в ходе лекции? |
Самостоятельная работа 1: Сборка и установка библиотеки OpenCV. Использование библиотеки в среде Microsoft Visual Studio
4. Разработка приложения для демонстрации базовых операций работы с изображениями
4.1. Задача определения контуров объектов
К настоящему моменту решены все технические вопросы, поэтому в данном разделе сконцентрируемся на модельной задаче определения контуров объекта, а также на рассмотрении базовых функций библиотеки OpenCV для решения данной задачи.
Резкое изменение яркости изображения представляет интерес по нескольким причинам [20]:
- Такие изменения, как правило, возникают на границах объектов, например, при изображении светлого объекта на темном фоне или наоборот.
- Резкие изменения яркости могут быть следствием изменения отражательной способности на достаточно характерных структурах, таких, как разметка пешеходного перехода или пятна на шкуре леопарда.
- Резкие изменения ориентации поверхности – это еще одна возможная причина изменения яркости.
Пользуясь терминологией, принятой в компьютерном зрении, точки, в которых происходит резкий перепад яркости изображения, называются краями или краевыми точками. Возникает проблема, связанная с тем, как связать краевые точки с границами или контурами объектов на изображении. Далее попробуем решить данную задачу средствами библиотеки OpenCV. Предварительно рассмотрим ряд базовых функций работы с изображениями.
4.2. Базовые операции
4.2.1. Создание изображения
В OpenCV любое изображение представляет собой матрицу интенсивностей, а именно объект класса Mat. Существует много способов создания объекта данного типа, рассмотрим два наиболее часто используемых в контексте изображений:
- Конструктор класса Mat.
// _rows – количество строк // _cols – количество столбцов // _type – тип матрицы (CV_8UC1, CV_64FC3 и другие) Mat(int _rows, int _cols, int _type); Mat(Size _size, int _type); // _s - заполнитель Mat(int _rows, int _cols, int _type, const Scalar& _s); Mat(Size _size, int _type, const Scalar& _s);
- Метод create.
void create(int _rows, int _cols, int _type); void create(Size _size, int _type);
По сути это два эквивалентных способа создания, выбор, что использовать, безусловно, принадлежит разработчику.
После выполнения всех операций с объектом типа Mat необходимо освободить память, вызвав метод release.
void release();
4.2.2. Загрузка изображения
Загрузка изображения – это одна из основных операций. Ниже приведен прототип функции OpenCV, которая отвечает за загрузку изображений.
Mat imread(const string& filename, int flags=1)
Как отмечалось в предыдущем разделе, изображение представляет собой двумерную матрицу интенсивностей, поэтому функция imread возвращает объект типа Mat. В качестве входных параметров функция принимает название файла filename и целочисленный флаг flags, определяющий правило загрузки:
- flags>0 означает, что изображение загружается как цветное трехканальное. Отметим, что в OpenCV каналы хранятся в порядке BGR;
- flags<0 – изображение загружается так, как есть, т.е. автоматически определяется количество каналов;
- flags=0 используется для загрузки изображения в оттенках серого, что позволяет сразу получить из цветного изображение в оттенках серого без дополнительной конвертации.
Класс Mat имеет набор полей и методов, часть из которых представляет интерес с точки зрения работы с изображением:
- uchar* data – поле, содержащее значение интенсивностей для каждого пикселя изображения. Если данное поле после загрузки изображения имеет значение NULL, значит, произошла ошибка в процессе загрузки изображения. Типичными ошибками является неправильный путь или название изображения, неподдерживаемый или неправильный формат, некорректные права доступа к файлу;
- int rows, cols – количество строк и столбцов в матрице;
- int channels() const – метод, который возвращает количество каналов в изображении;
- Size size() const – метод для получения размера изображения (width, height – поля класса Size). Обратим внимание читателя, что rows и cols совпадают с width, height соответственно.
Описание назначения других полей и методов можно найти в документации [14].
4.2.3. Сохранение изображения
Естественным образом раз есть операция чтения изображения, необходима и противоположная операция сохранения. Сохранение изображения в файл осуществляется посредством вызова функции imwrite, прототип которой приведен далее.
bool imwrite(const string& filename, const Mat& img, const vector<int>& params=vector<int>())
Функция в качестве параметров принимает название файла filename, в который необходимо сохранить изображение, само изображение img, а также вектор целочисленных параметров params. Указанный вектор определяет параметры сохранения в файл, специфичные для выбранного формата сохранения. Формат определяется расширением файла filename. Вектор параметров представляет собой единую последовательность пар <идентификатор_параметра> и <значение_параметра>. На данный момент доступны следующие идентификаторы:
- CV_IMWRITE_JPEG_QUALITY – качество сохранения изображения в формате JPEG, принимает значения от 0 до 100%, по умолчанию значение равно 95%.
- CV_IMWRITE_PNG_COMPRESSION – уровень сжатия изображения при сохранении в формате PNG, принимает значения от 0 до 9 (чем больше уровень, тем мельче результирующее изображение), по умолчанию используется уровень сжатия, равный 3.
- CV_IMWRITE_PXM_BINARY – флаг, который определяет тип хранения (бинарный или нет) изображения в форматах PPM, PGM, PBM, принимает значение 0 или 1, по умолчанию используется 1.
4.2.4. Отображение изображения
Безусловно, после обработки изображения необходимо посмотреть результат. Для корректного отображения изображения необходимо последовательно выполнить три действия:
1. Создать окно для отображения с помощью функции namedWindow. Функция принимает на вход название окна, которое служит идентификатором окна, и флаги. Отметим, что если окно с аналогичным идентификатором уже существует, то функция не выполняет никаких действий.
void namedWindow(const string& winname, int flags)
Параметр flags может принимать следующие значения или их комбинации, полученные в результате применения оператора ‘OR’:
- CV_WINDOW_NORMAL или CV_WINDOW_AUTOSIZE, первое значение позволяет пользователю вручную изменять размеры окна в процессе работы приложения, в то время, как второе автоматически подгоняет размеры окна под размеры изображения, запрещая пользователю изменять размер вручную;
- CV_WINDOW_FREERATIO или CV_WINDOW_KEEPRATIO, CV_WINDOW_FREERATIO подгоняет изображение под окно без сохранения пропорций, CV_WINDOW_KEEPRATIO позволяет сохранять пропорции;
- CV_GUI_NORMAL или CV_GUI_EXPANDED, первое значение обеспечивает отрисовку окна без дополнительных компонент таких, например, как строка состояний и панель инструментов, второе же, напротив, предоставляет более новые возможности по созданию графических интерфейсов пользователя наряду с отображением изображений. По умолчанию для окна устанавливаются свойства CV_WINDOW_AUTOSIZE, CV_WINDOW_KEEPRATIO, и CV_GUI_EXPANDED.
2. Отобразить изображение посредством вызова функции imshow. Для отображения необходим идентификатор окна winname, в которое будет помещено изображение, а также само изображение image.
void imshow(const string& winname, const Mat& image)
3. Дождаться нажатия какой-либо клавиши, чтобы закрыть окно. Ожидание реализуется посредством вызова функции waitKey , которая принимает на вход время ожидания delay в миллисекундах. По умолчанию delay=0 , что означает ожидание в течение бесконечного промежутка времени, т.е. исполнение приложения будет продолжено после нажатия какой-либо клавиши. Отметим, что отсутствие вызова указанной функции приведет к тому, что по завершении программы окно будет автоматически закрыто.
int waitKey(int delay=0)
4.2.5. Копирование изображения
В некоторых случаях при разработке приложений необходимо работать не с самим изображением, а с его полной копией, чтобы повторно использовать исходное изображение. Напомним, что изображение представляется объектом класса Mat . В состав методов данного класса входит метод clone , который решает указанную задачу.
Mat clone() const;
Есть еще пара полезных методов копирования copyTo : первый (см. прототип ниже) выделяет память для хранения полностью аналогичной матрицы m и копирует в нее содержимое текущей матрицы, второй метод выполняет копирование в соответствии с передаваемой маской mask (копируются только элементы, которым соответствуют ненулевые элементы маски).
void copyTo(Mat& m) const; void copyTo(Mat& m, const Mat& mask) const;