Цель данной работы - изучить базовые примитивы модуля opencv_core и простейшие операции обработки изображений, входящие в состав модуля opencv_imgproc, научиться разрабатывать приложения с графическим интерфейсом средствами модуля opencv_highgui.
Основные задачи
-
Реализовать метод конвертации заданной прямоугольной области цветного изображения в оттенки серого.
-
Реализовать метод размытия заданной прямоугольной области цветного изображения с помощью медианного фильтра.
-
Реализовать метод определения ребер в заданной области изображения с использованием метода Канни.
-
Реализовать метод пикселизации заданной области изображения.
-
Разработать приложение, которое на вход принимает изображение и метод преобразования заданной области изображения (см. предыдущие пункты). Приложение должно обеспечивать следующий функционал:
- Отрисовка исходного изображения.
- Выделение области для преобразования на исходном изображении с использованием курсора мыши.
- Отрисовка результата выполнения преобразования.
Дополнительные задачи
-
Разработать приложение, обеспечивающее аналогичный функционал преобразования области изображения для случая, когда на входе имеется видео.
-
Разработать приложение, обеспечивающее аналогичный функционал для случая, когда на входе имеется видео, поступающее с видеокамеры.
-
Разработать приложение, которое на вход принимает изображение и обеспечивает следующий функционал:
- Отрисовка исходного изображения.
- Установка точки на исходном изображении с использованием курсора мыши.
- Построение и отображение выпуклой оболочки набора точек, поставленных на изображении. Замечание: при добавлении очередной точки выпуклая оболочка может пересчитываться и перерисовываться в режиме online.
Пример работы приложения, которое решает данную задачу, можно посмотреть на YouTube.
В лабораторной работе основные задачи решаются на базе программного
модуля image_processing
библиотеки summer_school_2016_lib
. Модуль
включает заголовочный файл include\image_processing.hpp
и исходный файлsrc\image_processing.cpp
. Модуль содержит объявление
абстрактного класса ImageProcessor
.
class ImageProcessor {
public:
virtual cv::Mat CvtColor(const cv::Mat &src, const cv::Rect &roi) = 0;
virtual cv::Mat Filter(const cv::Mat &src, const cv::Rect &roi,
const int size) = 0;
virtual cv::Mat DetectEdges(const cv::Mat &src, const cv::Rect &roi,
const int filter_size, const int low_threshold,
const int ratio, const int kernel_size) = 0;
virtual cv::Mat Pixelize(const cv::Mat &src, const cv::Rect &roi,
const int divs) = 0;
};
Класс имеет следующие чисто виртуальные методы:
CvtColor
- метод конвертации прямоугольной областиroi
исходного изображенияsrc
в оттенки серого.Filter
- метод медианной фильтрации прямоугольной областиroi
исходного изображенияsrc
с помощью фильтра с ядром размераsize x size
.DetectEdges
- метод для выделения ребер в прямоугольной областиroi
исходного изображенияsrc
с использованием детектора ребер Канни. Входные параметры:filter_size
- размер ядра линейного фильтра,low_threshold
иlow_threshold * ratio
пороги метода Канни,kernel_size
- размер ядра фильтра Собеля.Pixelize
- метод пикселизации прямоугольной областиroi
исходного изображенияsrc
(телевизионный эффект, используемый для того, чтобы скрыть лица людей) с количеством деленийdivs
по каждой оси.
- Разработать объявление наследника
ImageProcessorImpl
классаImageProcessor
. - Последовательно реализовать методы класса
ImageProcessorImpl
. - Скопировать
samples\template_demo.cpp
в директориюsamples
. - Переименовать копию примера в
samples\imgproc_demo.cpp
. - Разработать приложение
samples\imgproc_demo.cpp
в соответствии с перечнем требований, представленным в описании основных задач. - Разработать приложения, решающие дополнительные задачи.
- Разработать объявление наследника
ImageProcessorImpl
классаImageProcessor
и поместить его в файлinclude\image_processing.hpp
.
class ImageProcessorImpl : public ImageProcessor {
public:
virtual cv::Mat CvtColor(const cv::Mat &src, const cv::Rect &roi);
virtual cv::Mat Filter(const cv::Mat &src, const cv::Rect &roi,
const int size);
virtual cv::Mat DetectEdges(const cv::Mat &src, const cv::Rect &roi,
const int filter_size, const int low_threshold,
const int ratio, const int kernel_size);
virtual cv::Mat Pixelize(const cv::Mat &src, const cv::Rect &roi,
const int divs);
};
-
Реализовать метод
ImageProcessorImpl::CvtColor
. Метод предполагает выполнение следующей последовательности действий:- Создать копию
src_copy
исходного изображенияsrc
. - Выделить подматрицу
src_copy_roi
из копииsrc_copy
, соответствующую областиroi
. - Сконвертировать подматрицу
src_copy_roi
в оттенки серого, результат записать в матрицуdst_gray_roi
. Примечание: необходимо использовать функциюcvtColor
. - Создать вектор матриц
vector<Mat> channels
, соответствующих каналам результирующей области преобразованного изображенияdst_roi
. - Сформировать
dst_roi
посредством склеивания трех каналов, каждый канал соответствуетdst_gray_roi
. Примечание: необходимо использовать функциюmerge
. - Скопировать
dst_roi
в подматрицуsrc_copy_roi
. - Вернуть
src_copy
.
- Создать копию
-
Реализовать метод
ImageProcessorImpl::Filter
. Метод предполагает выполнение следующей последовательности действий:- Создать копию
src_copy
исходного изображенияsrc
. - Выделить подматрицу
src_copy_roi
из копииsrc_copy
, соответствующую областиroi
. - Вызвать функцию медианной фильтрации
medianBlur
для выделенной областиsrc_copy_roi
. - Вернуть
src_copy
.
- Создать копию
-
Реализовать метод
ImageProcessorImpl::DetectEdges
.- Выделить подматрицу
src_roi
из копииsrc
. - Сконвертировать матрицу
src_roi
в оттенки серого, результат записать в матрицуsrc_gray_roi
. - Отфильтровать
src_gray_roi
с использованием линейного фильтра, результат записать в матрицуgray_blurred
. Примечание: для фильтрации можно использовать функциюblur
. - Построить ребра
detected_edges
на изображенииgray_blurred
с помощью функцииCanny
. - Создать матрицу
dst
. - Скопировать изображение
src
вdst
. - Выделить подматрицу
dst_roi
изdst
в соответствии с областьюroi
. - Обнулить все значения в подматрице
dst_roi
. Примечание: необходимо использовать статический методall
классаScalar
. - Скопировать
src_roi
вdst_roi
в соответствии с маскойdetected_edges
. - Вернуть
dst
.
- Выделить подматрицу
-
Реализовать метод
ImageProcessorImpl::Pixelize
.-
Создать копию
src_copy
исходного изображенияsrc
. -
Выделить подматрицу
src_сopy_roi
из копииsrc_copy
. -
Определить размеры блока пикселизации
block_size_x = roi.width / divs
,block_size_y = roi.height / divs
. -
Реализовать обход пикселей выделенной области
roi
по всемx
иy
с шагамиblock_size_x
иblock_size_y
по осям Ox и Oy соответственно.- Для каждого положения с координатами (
x
,y
) в выделенной области взять вложенную областьsrc_roi_block
размера (block_size_x
,block_size_y
). - Выполнить размытие области
src_roi_block
с помощью линейного фильтра с ядром размера (block_size_x
,block_size_y
).
- Для каждого положения с координатами (
-
Вернуть
src_copy
.
-
-
Скопировать
samples\template_demo.cpp
в директориюsamples
. -
Переименовать копию примера в
samples\imgproc_demo.cpp
. -
Разработать приложение
samples\imgproc_demo.cpp
в соответствии с требованиями, перечисленными в основных задачах.- Создать массив опций приложения:
image
- название исходного изображения;gray
- флаг, показывающий, что необходимо выполнить преобразование области в оттенки серого;median
- флаг, показывающий, что необходимо выполнить медианную фильтрацию области;edges
- флаг, показывающий, что необходимо построить ребра для выделенной области;pix
- флаг, показывающий, что необходимо выполнить пикселизацию.
const char* kOptions = "{ @image | <none> | image to process }" "{ gray | | convert ROI to gray scale }" "{ median | | apply median filter for ROI }" "{ edges | | detect edges in ROI }" "{ pix | | pixelize ROI }" "{ h ? help usage | | print help message }";
- Создать структуру для хранения состояния мыши
MouseCallbackState
:point_first
- левый верхний угол выделенной прямоугольной области;point_second
- правый нижний угол выделенной прямоугольной области;is_selection_started
- флаг, определяющий, что пользователь зажал левую кнопку мыши;is_selection_finished
- флаг, определяющий, что пользователь отпустил левую кнопку мыши.
struct MouseCallbackState { bool is_selection_started; bool is_selection_finished; Point point_first; Point point_second; };
-
Реализовать обработчик
OnMouse
события нажатия на кнопку мыши.- Если зажата левая кнопка мыши (событие
cv::EVENT_LBUTTONDOWN
), то необходимо выставить правильные значения флаговis_selection_started = true
,is_selection_finished = false
и сохранить координаты курсора вpoint_first
. - Если левая кнопка мыши освобождена (событие
cv::EVENT_LBUTTONUP
), то необходимо выставить правильные значения флаговis_selection_started = false
,is_selection_finished = true
и сохранить координаты курсора вpoint_second
. - Если курсор мыши изменил положения (событие
cv::EVENT_MOUSEMOVE
) и при этомis_selection_finished = false
, то необходимо изменить положение точкиpoint_second
.
- Если зажата левая кнопка мыши (событие
-
Реализовать основную функцию. Логика выполнения основной функции следующая:
- Разобрать аргументы командной строки. Примечание: необходимо
использовать класс
CommandLineParser
библиотеки OpenCV. - Создать окно для отображения исходного изображения и назначить
на это окно событие
OnMouse
. Для визуализации выделения области можно отрисовать построенный прямоугольник. Примечание: использовать функцииnamedWindow
,resizeWindow
,setMouseCallback
,imshow
иwaitKey
,rectangle
. - Реализовать цикл ожидания выбора области интереса для обработки.
- В зависимости от того, какая опция передана на вход программе, вызвать фильтр, соответствующей указанной области.
- Создать окно для отображения преобразованного изображения.
- Показать результат выполнения преобразования.
- Разобрать аргументы командной строки. Примечание: необходимо
использовать класс
- Создать массив опций приложения:
-
Разработать приложения, решающие дополнительные задачи.