Версия:
Аннотация
Растровое изображение. Пиксели. Сглаживание. Обработка видео.
В данной заметке будет показано как обрабатывать растровые изображения. В первом подразделе как по-пиксельно обрабатывать изображение.
Как было указано в прошлой заметке растровое изображение представляется в виде матрицы. Матрица хранится в памяти построчно, т.е. строчка за строчкой. Последние означает, что данные одной строчки идут вслед за данными предыдущей. Данные каждой строчки соответствуют пикселям её составляющие, при этом каналы хранятся последовательно для каждого из пикселей.
В согласии с вышеописанным представим простейшую программу, которая создает негатив по изображению, т.е. значение каждого из каналов заменяется на "противоположный а именно – вычитается из значения . Сначала покажем как это можно осуществить на чистом Си, далее будем видоизменять программу, в том числе, совершенствовать.
Си-шный способ Обход всех пикселов в общем случае технически сложен так как необходимо учитывать тип элементов матрицы. Рассмотрим случай, когда компоненты вектора элемента матрицы является беззнаковыми 8-битными целыми числами (CV_8U).
Обычно функции расчитаны не на все типы данных, иначе бы пришлось писать много проверок, да и кода было бы много. Поэтому, стандартно, когда функция прежде чем выполнять какие-либо действия сначала проверяет соответствие входных данных требуемым. В данном случае, функция умеет обрабатывать только матрицы элементы которой являются векторами из 8-битных беззнаковых чисел.
С точки зрения эффективности память лучше обходить последовательно (связано с устройством кэша), поэтому строчки матрицы как это и показано в программе лучше обходить построчно.
Ввиду того, что каналы в памяти идут подряд, как и сами пикселы, в случае идентичной операции для всех каналов можно избавится от внутреннего цикла, заменив цикл по колонкам на:
Подчеркну, что это возможно только в том случае, если все каналы обрабатываются единообразно. В противном случае, пришлось бы как ранее и было показано все-таки каждый из пикселов обрабатывать по отдельности.
Эффективность можно поднять ещё больше, если учитывать расположение строк. Так, существует метод Mat::isContinuous(), который позволяет определить идут ли строчку в притык одна к другой. Если да, то матрицу можно обрабатывать как одномерный массив. Для этого, до внешнего цикла следует вызвать код:
Для использования в предыдущем коде, следует убрать const.
Объекты C++ Объектная модель C++ позволяет сократить немного код. Так, вместо того, чтобы обрабатывать матрицу по компонентно, её можно обрабатывать по пиксельно.
В случае цветных изображений, пиксели будут являться векторами длины 3 компоненты которого являются 8-битным беззнаковым числом. Для такого объекта в C++ есть обозначение: Vec3b. Тогда код можно свести к следующему:
Естественно для других типов изображений придется написать свой код.
Итератор из C++ Циклы с явной индексацией элементов в C++ были обобщены на итераторы. В OpenCV соответствующий механизм поддерживается, так для обхода всех пикселов можно ими воспользоваться:
Напрямую У класса Mat есть метод Mat::at, который позволяет получить доступ к произвольному элементу матрицы.
или в случае 3х компонентной матрицы
Через ламба функцию:
Упражнения Упражнение. В прошлой заметке было показано как изменить контраст (умножению на константу) и яркость (добавление серого) фактически благодаря операциям над матрицами. Все тоже самое можно сделать написав цикл. Напишите его в качестве тренировки. Подсказка: значения нужно "насыщать"(saturate_cast<uchar>).
Компоненты Матрицу можно расслоить на разные компоненты. Для этого используется функция split:
Компоненты можно обратно собрать в матрицу, в частности? в изображение:
Больше одного измерения Scalar::all?? .create метод.
Печать Можно использовать для инициализации объекта «, или печать » и для point.
Например, для отладки или дотошного вывода данных.
format Formater::FMT_??
Одно из важны способов обработки изображений является сглаживанием. Суть сглаживания сводится к тому, что окно определенного фиксированного размера бежит по изображению. В выходное изображение заносится значения для данного окна являющиеся некой функцией от пикселов в окне.
Самым простым способом сглаживания является усреднение. Это достигается посредством функции blur. А англоязычной литературе этот фильтр называется обычно box filter.
Обычное усреднение имеет свои недостатки (более подробно в курсе по цифровой обработке изображений). В частности, все пикселы используются с одинаковыми весами. Это устраняет как может Гауссовский фильтр, который задается соответствующим распределением. В опессв от реализован функцией GaussianBlur.
Для определенного типа шума в изображении требуется свой тип фильтра. Так, шум типа соль/перец хорошо убирается медианным фильтром. Суть его заключается в том, что он заменяет центральный пиксель фильтра на медиану пикселей в окне, если между ними большая разница.
Сглаживающий фильтр сглаживает все подряд. В частности, границы между объектами. Для борьбы с этим был разработан адаптивный фильтр – билатерал фильтр. Конкретно он называется bilateralFilter.
Все данные фильтры объедены в ниже следующей программе:
Упражнение. Написать собственную реализацию фильтров.
При использовании обычных фильтров сглаживания (Гауссовский) можно построить (имеет смысл) пирамиду. Так после сглаживания, изображения можно уменьшить в два раза в размерах. И так далее. Получиться пирамида масштабов для изображения. В некоторых методах обработки изображения она применяется.
Для построения следующего слоя пирамиды:
Для выполнения обратной операции можно сделать так:
Фурье преобразование является важным инструментом при цифровой обработке изображений. Само по себе оно задается функцией dft. Но чтобы её корректно вызвать необходимо проделать ряд действий.
Как ранее было показано изображения считываются функцией imread. Для считывания видео нужно использовать класс VideoCapture.
В конструкторе указывается путь к картинке.
Помимо ввода и вывода изображений библиотека opencv позволяет вводить и выводить видео данные хоть и с некоторыми ограничениями видь в первую очередь данная библиотека предназначена для анализа визуальной информации.
Ввод кадров Класс cv::VideoCapture предназначен для считывания видео потоков, в частности, из файлов:
Упражнение. Измени программу так, чтобы каждый -ый кадр был записан на диск (по отдельности) как изображение.
Упражнение. Измени программу так, чтобы в окошке показывались кадры из видео потока.
Считывание дополнительной информации Видео поток помимо самих кадров – растровые изображения – характеризуется и другой информацией, например, общим количеством кадров в видео файле и частотой проигрывания. Для этого вставим следующий фрагмент кода в предыдущую программу:
В переменную total_frames будет записано реальное общее количество кадров в видео потоке. Соответственно вывод можно поменять на:
Приведу краткий список полезных параметров:
Общие параметры:
CV_CAP_PROP_FRAME_WIDTH | Ширина видео кадра. |
CV_CAP_PROP_FRAME_HEIGHT | Высота видео кадра. |
CV_CAP_PROP_FPS | Количество кадров в секунду. |
CV_CAP_PROP_FOURCC | Название видео кодека потока в формате fourcc. |
Для обработки видеофайлов:
CV_CAP_PROP_FRAME_COUNT | Общее количество кадров в видео файле. |
CV_CAP_PROP_POS_FRAMES | Номер текущего считываемого кадра. |
CV_CAP_PROP_POS_MSEC | Текущая позиция в миллисекундах. |
CV_CAP_PROP_POS_AVI_RATIO | Процент обработанных кадров. |
При взаимодействии с видеокамерой:
Параметры камеры:
CV_CAP_PROP_BRIGHTNESS | Яркость картинки. |
CV_CAP_PROP_CONTRAST | Контраст картинки. |
CV_CAP_PROP_SATURATION | Насыщенность цвета. |
CV_CAP_PROP_SHARPNESS | Резкость картинки. |
CV_CAP_PROP_EXPOSURE | Величина выдержки. |
CV_CAP_PROP_AUTO_EXPOSURE | Автоматическая подстройка выдержки. |
CV_CAP_PROP_IRIS | Размер диафрагмы. |
CV_CAP_PROP_ZOOM | Степень увеличения. |
CV_CAP_PROP_FOCUS | Положение фокуса. |
CV_CAP_PROP_ISO_SPEED | Значение чувствительности ISO. |
Подчеркну, что не все параметры обязаны быть поддержаны. Так, если он не поддерживается, то возвращается отрицательное значение. Также следует отметить, что не все параметры кросс-платформенны, т.е. результат может отличаться в зависимости от используемой операционной системы.