Czytaj książkę: «Мультимедийное Программирование OpenCV»

Czcionka:

Мультимедийное программирование


07.15.2019


Профессор: Orazdurdyyev Serdar Begnarlyevich


Внедрение цифровой обработки изображений / Introduction of Digital Image Processing


Выборка и квантование / Sampling and Quantization




Continuous Tone Image – Непрерывное тональное изображение

Sampled Image – Пример изображения

Sampled and Quandtized Image – Выборочное и квантованное изображение

Sampler – образец

Quantizer – Квантизатор


Аналого-цифровое преобразование / Analog to Digital Conversion





(a) Analog Signal – Аналоговый сигнал

(b) Sampling – Выборка

(c) Quantization – Квантование

(d) Coding – Кодирование


TS: Sampling Period – Период выборки


Происхождение изображения / Image Origin


Upper-left corner of image – Левый верхний угол изображения

Pixels – Пиксели

Lines – Линии




Изменение яркости изображения / Image Brightness Variation







Brightness – Яркость

Distance – Расстояние


Шаги яркости изображения / Image Brightness Steps





(a) 8 Steps : 3 bits (b) 16 Steps : 4 bits

(а) 8 шагов: 3 бита (б) 16 шагов: 4 бита






(c) 32 Steps : 5 bits (d) 64 Steps : 6 bits

(c) 32 шагов: 5 бит (d) 64 шагов: 6 бит






(e) 128 Steps : 7 bits (f) 256 Steps : 8 bits

(e) 128 шагов: 7 бит (f) 256 шагов: 8 бит


Яркость изображения Разрешение / Image Brightness Resolution





















Световой спектр / Light Spectrum





WHITE LIGHT / БЕЛЫЙ СВЕТ

INFRARED / ИНФРАКРАСНЫЙ

ULTRAVIOLET / УЛЬТРАФИОЛЕТ

OPTICAL PRISM / ОПТИЧЕСКАЯ ПРИЗМА


Табличка I. Цветовой спектр, видимый при прохождении белого света через призму. (С разрешения General Electric Co., подразделения по производству ламп.) / Plate I. Color spectrum seen by passing white light a prism. (Courtesy of General Electric Co., Lamp Business Division.)


COSMIC RAYS / КОСМИЧЕСКИЕ ЛУЧИ

GAMMA RAYS / ГАММА ИЗЛУЧЕНИЕ

X-RAYS / X-ЛУЧИ


INFRARED / ИНФРАКРАСНЫЙ


MICRO-WAVES / МИКРОВОЛНЫ

RADIO / РАДИО

ELECTRIC POWER / ЭЛЕКТРОЭНЕРГИЯ

ULTRAVIOLET / УЛЬТРАФИОЛЕТ

VISIBLE SPECTRUM / ВИДИМЫЙ СПЕКТР

INFRARED / ИНФРАКРАСНЫЙ


Смеси света и пигментов / Mixtures of Light and Pigments




RGB Color – Цвет RGB

MIXTURES OF LIGHT (Additive primaries)

СМЕСИ СВЕТА (Аддитивные праймериз)


RED – КРАСНЫЙ

YELLOW – ЖЕЛТЫЙ

GREEN – ЗЕЛЕНЫЙ

CYAN – ГОЛУБОЙ

WHITE – БЕЛЫЙ

BLUE – СИНИЙ

MAGENTA – ПУРПУРНЫЙ


MIXTURES OF PIGMENTS СМЕСИ ПИГМЕНТОВ

(Subtractive primaries) (Субтрактивные праймериз)





CMY(K) Color / (CMYK) Цвет


RED – КРАСНЫЙ

YELLOW – ЖЕЛТЫЙ

GREEN – ЗЕЛЕНЫЙ

CYAN – ГОЛУБОЙ

BLACK – ЧЕРНЫЙ

BLUE – СИНИЙ

MAGENTA – ПУРПУРНЫЙ


Изображение R, G, B / R, G, B Image






Исходное изображение (Original Image) Красный компонент (Red Component)






Зеленый компонент (Green Component) Синий компонент (Blue Component)



Тип цифрового изображения / A Type of Digital Image




(а) Цветное изображение (Color Image)

(b) Изображение с уровнем серого (Gray Level Image)

(c) Двоичное изображение (Binary Image)


Тип цифрового изображения / A Type of Digital Image





(a) Двоичное изображение / Binary Image





(b) Изображение с уровнем серого / Gray Level Image


Тип цифрового изображения / A Type of Digital Image





Цветное изображение (Color Image)


2. Введение OpenCV (Introduction of OpenCV)


OpenCV?

● 

OpenCV – библиотека компьютерного зрения с открытым исходным кодом

– Библиотека с открытым исходным кодом для обработки изображений

и компьютерного зрения

– Состоит из более чем 2500 алгоритмов

– Поддержка интерфейсов C, C++, Python, Matlab.

– Поддержка операционных систем для Windows, Linux, Android, Mac

OS и т. д.

– Быстрая реализация алгоритма с использованием инструкций MX

(MultiMedia eXtension) и SSE (потоковые расширения SIMD).

– Разработка интерфейса CUDA и OpenCL


Установка OpenCV / OpenCV Install

• 

Условия для программирования OpenCV с использованием C ++ (для ОС Windows)


– 

На вашем компьютере должна быть установлена 64-битная ОС Windows. (OpenCV поддерживает только 64-битные ОС)

– 

Visual Studio 2017 должен быть установлен как инструмент редактора программ для программирования на C ++. (Последняя версия Visual Studio – 2019, но в настоящее время поддерживает только OpenCV для Visual Studio 2017.)


① Установка сообщества Visual Studio 2017.

(① Visual Studio Community 2017 Install)

● 

https://visualstudio.microsoft.com/ru/free-developer-offers/





• 

На официальном сайте выше можно загрузить только последнюю версию 2019 года, поэтому вы можете найти версию 2017 года с помощью веб-поиска и загрузки.

• 

30-дневная ознакомительная версия, затем зарегистрируйтесь в Microsoft, войдите в Visual Studio и продолжайте использовать ее бесплатно


② Загрузка OpenCV (OpenCV Download)

• 

http://opencv.org

> Releases

• 

После загрузки установочного файла, дважды щелкните файл exe для установки




③ Add to “System Environment Path” of Windows

• 

Зарегистрируйте место установки OpenCV в «Путь к системной среде» Windows

• 

Если вы установили диск C следующим образом, добавьте следующее в Path

• 

C:\OpenCV\build\x64\vc15\bin





Настройка OpenCV для Visual Studio 2017

(OpenCV Setup of Visual Studio 2017)
















Проверьте, что Debug mode(режим отладки) в настоящее время включен !!!







































Режим отладки → opencv_worldxxxd.lib

(Режим выпуска → opencv_worldxxx.lib)

Debug mode → opencv_worldxxxd.lib

(Release mode → opencv_worldxxx.lib)










● 

Имя → OpenCV410_x64_v15_

отлаживать

Name → OpenCV410_x64_v15_debug

● 

Местоположение → Папка сохранения программы OpenCV (помните!!!)

Location → OpenCV program saving folder (remember!!!)





• 

При использовании Visual Studio в Release mode(режиме выпуска)


– 

Запустите проект> Свойства в Main Menu





– 

Выполните то же самое содержание на страницах с 24 по 30

Release mode → opencv_worldxxx.lib

(Режим выпуска → opencv_worldxxx.lib)









• 

Имя → OpenCV410_x64_v15_release

Name → OpenCV410_x64_v15_release

• 

Местоположение → Папка сохранения программы OpenCV (помните!!!)

Location → OpenCV program saving folder (remember!!!)




Пример программы OpenCV / OpenCV Sample Program


• 

запись OpenCV Sample Program





• 

Ввод имени программы C++… → ???.cpp

C++ program name typing… → ???.cpp












#include <opencv2/highgui.hpp>

пустая функция()

{

cv::Mat image(300, 400, CV_8UC1, cv::Scalar(200));

cv::imshow("Просмотр изображений", image);

резюме::waitKey (0);

}


#include <opencv2/highgui.hpp>

void main()

{

cv::Mat image(300, 400, CV_8UC1, cv::Scalar(200));

cv::imshow("Image Viewer", image);

cv::waitKey(0);

}





• 

Ошибка → установка x64!! / Error → x64 setting!!







• 

Ctrl+F5: запустить без отладки. / Ctrl+F5 : Start without Debugging





Выход (Результат) / Output (Result)





3. OpenCV Classes


Точка_Класс / Point_ Class

• 

Шаблонный класс (template class) для представления позиций width (ширины) и height (высоты) в двухмерных координатах (2 Dimension coordinate).



• 

(Объявление класса Point_( Declaration of Point_ Class)

Point_<int> <==> Point2i <==> Point;

Point_<float> <==> Point2f;

Point_<double> <==> Point2d;


• 

Бывший)

Ex)

Point_<int> pt1(100, 200);

Point_<float> pt2(92.3f, 125.23f);

Point_<double> pt3(100.2, 300.9);


Point pt4(120, 69);

Point2f pt5(0.3f, 0.f), pt6(0.f, 0.4f);

Point2d pt7(0.25, 0.6);


Размер_Класс / Size_ Class

• 

Шаблонный класс(template class), который определяет размер изображения(image) или прямоугольника(rectangle).





• 

Объявление класса Size_ (Declaration of Size_ Class)

Size_<int> <==> Size2i <==> Size;

Size_<float> <==> Size2f;

Size_<double> <==> Size2d;


• 

Бывший)

• 

Ex)

Size_<int> sz1(100, 200);

Size_<float> sz2(192.3f, 25.3f);

Size_<double> sz3(100.2, 30.9);


Size sz4(120, 69);

Size2f sz5(0.3f, 0.f);

Size2d sz6(0.25, 0.6);


Прямой_класс / Rect_ Class

• 

класс шаблона для представления rectangle(прямоугольников)

• 

((Начальная точка_x, Начальная точка_y), (Конечная точка_x, Конечная точка_y))

• 

((Начальная точка_x, Начальная точка_y), Ширина, Высота)





• 

Объявление класса Rect_ (Declaration of Rect_ Class)

Rect_<int> <==> Rect2i <==> Rect;

Rect_<float> <==> Rect2f;

Rect_<double> <==> Rect2d;

• 

Бывший)


• 

Ex)

Size2d sz(100.5, 60.6);

Point2f pt1(20.f, 30.f), pt2(100.f, 200.f);


Rect_<int> rect1(10, 10, 30, 50);

// column, row, width, height

Rect_<float> rect2(pt1, pt2);

Rect_<double> rect3(Point2d(20.5, 10), sz);


Век-класс / Vec Class

• 

Шаблонный класс(template class) для вектора(Vector) чисел с небольшим количеством элементов.

• 

Укажите data type(тип данных) и количество element(элементов) между < и >.

Vec<uchar, 2> <==> Vec2b

Vec<int, 3> <==> Vec3i

Vec<float, 4> <==> Vec4f

Vec<double, 5> <==> Vec5d

• 

Ex)

Vec<int, 2> v1(5, 12);

Vec<double, 3> v2(40, 130.7, 125.6);

Vec2b v3(10, 10);

Vec6f v4(40.f, 230.25f, 525.6f);

Vec3i v5(200, 230, 250);


Скаляр_класс / Scalar_ Class

• 

Укажите четыре значения в качеств data type(типа данных), чтобы указать значение яркости pixel(пикселя)

• 

Сохраните четыре значения Blue, Green, Red, Alpha(transparency).

• 

Установите в 0, если при инициализации (Initialization) не указано значение

• 

Scalar_<double> <==> Scalar

• 

Ex)

Scalar_<uchar> red(0, 0, 255);

Scalar_<int> blue(255, 0, 0);

Scalar_<double> color1(500);

Scalar_<float> color2(100.f, 200.f, 125.9f);


Мат Класс / Mat Class

• 

Класс(class), используемый для представления image(изображения).

• 

Mat (строки, столбцы, тип, скаляр (rows, cols, type, Scalar))

строки: размер строки (rows: row size)

столбцы: размер столбца (cols : column size)

тип: тип данных (type : data type)

Скаляр: матричное значение (Scalar : matrix value)





#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

float data[] = {

      1.2f, 2.3f, 3.2f,

      4.5f, 5.f, 6.5f,

};

Mat m1(2, 3, CV_8U);

Mat m2(2, 3, CV_8U, Scalar(300));

Mat m3(2, 3, CV_32F, data);

Size sz(2, 3);

Mat m4(Size(2, 3), CV_64F);

Mat m5(sz, CV_32F, data);

cout << "[m1] =" << endl << m1 << endl;

cout << "[m2] =" << endl << m2 << endl;

cout << "[m3] =" << endl << m3 << endl << endl;

cout << "[m4] =" << endl << m4 << endl;

cout << "[m5] =" << endl << m5 << endl;

return 0;

}








#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

Mat m1(4, 3, CV_32FC3);

cout << “Dimension = " << m1.dims << endl;

cout << “Rows = " << m1.rows << endl;

cout << “Columns = " << m1.cols << endl << endl;

cout << “Channels = " << m1.channels() << endl;

cout << “Data Type = " << m1.depth() << endl;

cout << “Matrix Size = " << m1.size() << endl << endl;

cout << “Total Data Number = " << m1.total() << endl;

return 0;

}





#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

Mat m1(2, 3, CV_8U, 2);

Mat m2(2, 3, CV_8U, Scalar(10));

Mat m3 = m1 + m2;

Mat m4 = m2 – 6;

Mat m5 = m1;

cout << "[m2] =" << endl << m2 << endl;

cout << "[m3] =" << endl << m3 << endl;

cout << "[m4] =" << endl << m4 << endl << endl;

cout << "[m1] =" << endl << m1 << endl;

cout << "[m5] =" << endl << m5 << endl << endl;

m5 = 100;

cout << "[m1] =" << endl << m1 << endl;

cout << "[m5] =" << endl << m5 << endl;

return 0;

}


• Копирование исходной матрицы в другую матрицу / Copy original matrix to another matrix

• Матовый клон () / Mat clone ()

• void copy To (матрица целей, матрица маски) / void copy To

(objective matrix, mask matrix)

– 

mask matrix : Копирование только ненулевых элементов (elemen)


• 

void convertTo (objective matrix, data type)


– 

data type : data type, которые вы хотите изменить


#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

double data[] = {

      1.1, 2.2, 3.3, 4.4,

      5.5, 6.6, 7.7, 8.9,

      9.9, 10, 11, 12

};

Mat m1(3, 4, CV_64F, data);

Mat m2 = m1.clone(); // copy m1 to m2

Mat m3, m4;

m1.copyTo(m3); // copy m1 to m3

m1.convertTo(m4, CV_8U); // copy m1 to m4 converting to uchar

cout << "[m1] =\n" << m1 << endl;

cout << "[m2] =\n" << m2 << endl;

cout << "[m3] =\n" << m3 << endl;

cout << "[m4] =\n" << m4 << endl;

return 0;

}


векторный класс / vector Class

• 

Контейнер последовательностей(Sequence Container) C++ STL(Standard Template Library)

• 

доступ к элементу(element access) вектора(vector) : используйте оператор индекса(subscript operator), [], как массив(array)

• 

vector() : конструктор(constructor)

• 

void push_back() : добавляет элемент в конец vector

• 

void pop_back() : удалить последний элемент


#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

vector<Point> v1;

v1.push_back(Point(10, 20));

v1.push_back(Point(20, 30));

v1.push_back(Point(50, 60));

vector<float> v2(3, 9.25);

Size arr_size[] = { Size(2, 2), Size(3, 3), Size(4, 4) };

int arr_int[] = { 10, 20, 30, 40, 50 };

vector<Size> v3(arr_size, arr_size + sizeof(arr_size) / sizeof(Size));

vector<int> v4(arr_int + 2, arr_int + sizeof(arr_int) / sizeof(int));

cout << "[v1] " << ((Mat)v1) << endl << endl;

cout << "[v2] " << ((Mat)v2) << endl << endl;

cout << "[v2] " << ((Mat)v2).reshape(1, 1) << endl;

cout << "[v3] " << ((Mat)v3).reshape(1, 1) << endl;

cout << "[v4] " << ((Mat)v4).reshape(1, 1) << endl;

return 0;

}

Класс диапазона / Range class

• 

Используется в основном для указания диапазона row(строк) и column(столбцов) в классе Mat.

• 

Range(int start, int end)

• 

start(начало) в диапазоне, end(конец) не в диапазоне

Функция операции с матрицей / Matrix Operation Function

• 

Matexp inv(метод): расчет обратной матрицы

– метод

• 

Matexp inv(method) : inverse matrix calculation

– method



• 

Matexp mul (input matrix): Выполнить поэлементное (element-wise) умножение двух матриц

• 

Matexp t () : вычислить транспонированную матрицу(transposed matrix)


• 

Одновременные уравнения (simultaneous equation)





#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

float data[] = {

      1, 0, 2,

      -3, 2, 6,

      -1, -2, 3

};

float ans[] = {6, 30, 8};

Mat m1(3, 3, CV_32F, data);

Mat m2(1, 3, CV_32F, ans);

Mat m2_t = m2.t();

Mat m1_inv = m1.inv(DECOMP_LU);

Mat x = m1_inv * m2_t;

cout << "[m1] = " << endl << m1 << endl;

cout << "[m1_inv] = " << endl << m1_inv << endl << endl;

cout << "[m2(transposed)] = " << endl << m2_t << endl << endl;

cout << “solution x1, x2, x3 = " << x.t() << endl;

}


насыщенный_ бросок < > / saturate_cast < >

• 

image data는 основном представляют собой кодированные(encoding) данные с 8 битами на канал.

• 

Поскольку он использует только 8bit, он имеет ограниченный диапазон значений пикселей (0 ~ 255).

• 

saturate_cast() template method : Когда значение сохраняется в 8-битном, если оно превышает 8-битный диапазон, оно сохраняется как 0 или 255

• 

Ex)

Mat m1(2, 2, CV_8U);

m1(0, 0) = -50; // -> 206

m1(0, 1) = 300; // -> 44

m1(1, 0) = saturate_cast<uchar>(-50);

m1(1, 1) = saturate_cast<uchar>(300);


4. Пользовательские интерфейсы OpenCV

(OpenCV User Interfaces)


Контрольние виндов / Window Control

• 

Named Window (winname, flags) : Устанавливает имя window и создает window с этим именем


– 

flags : Изменение размера window





• 

imshow (): отображает матрицу "mat" как окно в окне winname

• 

destroyWindow (): удаляет указанное окно с экрана

• 

destroyAllWindows (): удалить все видимые окна

• 

moveWindow (x, y): переместить окно winname в указанную позицию (x (столбец, y (строка))

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

Mat image1(300, 400, CV_8U, Scalar(255));

Mat image2(300, 400, CV_8U, Scalar(100));

string title1 = "white window control";

string title2 = "gray window control";

namedWindow(title1, WINDOW_AUTOSIZE);

namedWindow(title2, WINDOW_NORMAL);

moveWindow(title1, 100, 200);

moveWindow(title2, 300, 200);

imshow(title1, image1);

imshow(title2, image2);

waitKey();

destroyAllWindows();

return 0;

}


Контрольние событиями клавиатуры / Keyboard Event Control

• 

waitKey (delay, задержка): ожидает ввода ключа в течение времени задержки(delay), возвращает(return) значение клавиши, когда происходит событие клавиши,


– 

delay : время задержки. ms.

– 

delay <= 0 : Бесконечное ожидание, пока не произойдет ключевое событие

– 

delay > 0 : дождитесь ввода ключа в течение времени задержки. return (Возвращает) -1, если в течение времени задержки нет клавишного ввода


• 

Используйте waitKeyEx () для ввода клавиши со стрелкой (arrow key)

• 

Event (Событие) происходит только когда window active (активно).


Контрольние событиями мыши / Mouse Event Control

• 

Создать callback function (функцию обратного вызова) (event handler) (обработчик событий) для обработки событий мыши и зарегистрировать эту функцию в системе через setMouseCallback ()

• 

Если во время выполнения программы обнаружено событие мыши, оно call(вызовет) созданную пользователем callback function (функцию обратного вызова).





#include <opencv2/opencv.hpp>

using name space cv;

using name space std;

void on Mouse (int, int, int, int, void *);

int main ()

{

Mat image (200, 300, CV_8U);

image.setTo (255);

imshow (“mouse event 1", image);

imshow (“mouse event 2", image);

set Mouse Callback (“mouse event 1", on Mouse, 0);

waitKey(0);

return 0;

}

// next page continued....


void on Mouse (int event, int x, int y, int flags, void *params)

{

switch (event)

{

      case EVENT_LBUTTONDOWN:

            cout << “Left mouse button press" << endl;

            break;

      case EVENT_RBUTTONDOWN:

            cout << "Right mouse button press" << endl;                         break;

      case EVENT_RBUTTONUP:

            cout << "Right mouse button release" << endl;

            break;

      case EVENT_LBUTTONDBLCLK:

            cout << "Left mouse button double click" << endl;                   break;

}

}


Контрольние событиями трекбара / Trackbar Event Control

• 

Полоса прокрутки (scroll bar) или ползунок (slider bar), используемые при выборе определенного значения в определенном диапазоне

• 

Create Trackbar (tn, pw, sv, max, обратный вызов, данные)

– tn: имя трекбара

– pw: имя родительского window

– sv: значение ползунка

– max: максимальное значение ползунка (минимальное значение = 0)

– callback: функция обратного вызова (onChange)

– data: userdata transferred to callback function


#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

string title = “Trackbar Event";

Mat image;

void onChange(int value, void* userdata)

{

int add_value = value – 128;

cout << “added pixel value " << add_value << endl;

Mat tmp = image + add_value;

imshow(title, tmp);

}

// next page continued....


int main()

{

int value = 128;

image = Mat(300, 400, CV_8UC1, Scalar(128));

namedWindow(title, WINDOW_AUTOSIZE);

createTrackbar(“Brightness", title, &value, 255, onChange);

imshow(title, image);

waitKey(0);

return 0;

}


Линия, Прямоугольный рисунок / Line, Rectangle Drawing

• 

Line (img, pt1, pt2, цвет, толщина, тип линий, сдвиг)


• 

rectangle (img, pt1, pt2, цвет, толщина, тип линий, сдвиг)


– 

img: Тема должна быть нарисована matrix (image)

– 

pt1, pt2: звездная точка, конечная точка (star point, end point)

– 

color: цвет линии или прямоугольника (line or rectangle color)

– 

thickness : line thickness (-1: Заполните внутри)

– 

linetype




– 

сдвиг: вправо, битовый сдвиг // сдвиг вправо и влево

– 

сдвиг: бит вправо // сдвиг вправо и влево


#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main ()

{

Scalar blue (255, 0, 0), red (0, 0, 255), green = Scalar (0, 255, 0);

Scalar white (255, 255, 255);

Scalar yellow (0, 255, 255);

Mat image (400, 600, CV_8UC3, white);

Point pt1(50, 130), pt2(200, 300), pt3(300, 150), pt4(400, 50);

Rect rect (pt3, Size (200, 150));

Line (image, pt1, pt2, red);

line (image, pt3, pt4, green, 2, LINE_AA);

line (image, pt3, pt4, green, 3, LINE_8, 1);

rectangle (image, rect, blue, 2);

rectangle (image, rect, blue, FILLED, LINE_4, 1);

rectangle (image, pt1, pt2, red, 3);

imshow (“Line & Rectangle", image);

waitKey (0);

return 0;

}

• 

Выход (Output) 80-niň suratyna täzeden seret





Текстовый рисунок / Text Drawing

• 

putText (img, текст, организация, FontFace, FontScale, цвет, толщина, тип линии (img, text, org, fontFace, fontScale, color, thickness, linetype))


– 

img: матрица написать Текст (изображение)

– 

text: написать характер

– 

org: начальные координаты текста

– 

font Face: текстовый шрифт

– 

font Scale: Коэффициент увеличения размера шрифта

– 

color: цвет текста

– 

thickness: толщина текста

– 

linetype: тип текстовой строки (по умолчанию = 8)


• 

Начальные координаты строки дисплея – lower left (левый нижний)


font Face: текстовый шрифт //ширина (text font //shirift)



#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

Scalar olive(128, 128, 0), violet(221, 160, 221), brown(42, 42, 165);

Point pt1(20, 100), pt2(20, 200), pt3(20, 250);

Mat image(300, 500, CV_8UC3, Scalar(255, 255, 255));

putText(image, "SIMPLEX", Point(20, 30), FONT_HERSHEY_SIMPLEX, 1, brown);

putText(image, "DUPLEX", pt1, FONT_HERSHEY_DUPLEX, 2, olive);

putText(image, "TRIPLEX", pt2, FONT_HERSHEY_TRIPLEX, 3, violet);

putText(image, "ITALIC", pt3, FONT_HERSHEY_PLAIN | FONT_ITALIC, 2, violet);

imshow(“Text Drawing", image);

waitKey(0);

return 0;

}


• 

Выход (Output) 84-nji sahypa hem täzeden seretmeli





Рисунок круга / Circle Drawing

• 

circle (изображение, центр, радиус, цвет, толщина, тип линии)


– 

img: matrix Чтобы нарисовать круг (image)

– 

center: координаты центра круга

– 

radius: радиус круга

– 

color: цвет круга

– 

thickness: толщина круга

– 

linetype: тип окружной линии (по умолчанию = 8)


#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

Scalar orange(0, 165, 255), blue(255, 0, 0), magenta(255, 0, 255);

Mat image(300, 500, CV_8UC3, Scalar(255, 255, 255));

Point center = image.size() / 2;

Point pt1(70, 50), pt2(350, 220);

circle(image, center, 100, blue);

circle(image, pt1, 80, orange, 2);

circle(image, pt2, 60, magenta, -1);

int font = FONT_HERSHEY_COMPLEX;

putText(image, "center_blue", center, font, 1.2, blue);

putText(image, "pt1_orange", pt1, font, 0.8, orange);

putText(image, "pt2_magenta", pt2 + Point(2, 2), font, 0.5, Scalar(0, 0, 0), 2);

putText(image, "pt2_magenta", pt2, font, 0.5, magenta, 1);

imshow(“Circle Drawing", image);

waitKey(0);

return 0;

}


● 

Выход

/ Output



Обработка файлов изображений / Image File Processing

• 

imread (имя файла, флаги)


– 

имя файла: имя файла изображения для чтения

– 

флаги: тип цвета на следующей странице…





#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

void print_matInfo(string name, Mat img)

{

string str;

int depth = img.depth();

if (depth == CV_8U) str = "CV_8U";

else if (depth == CV_8S) str = "CV_8S";

else if (depth == CV_16U) str = "CV_16U";

else if (depth == CV_16S) str = "CV_16S";

else if (depth == CV_32S) str = "CV_32S";

else if (depth == CV_32F) str = "CV_32F";

else if (depth == CV_64F) str = "CV_64F";

cout << name;

cout << format(": depth(%d) channels(%d) -> data type: ", depth, img.channels());

cout << str << "C" << img.channels() << endl;

}

// next page continued....


int main()

{

string filename = "../image/read_color.jpg";

Mat color2gray = imread(filename, IMREAD_GRAYSCALE);

Mat color2color = imread(filename, IMREAD_COLOR);

CV_Assert(color2gray.data && color2color.data);

Rect roi(100, 100, 1, 1);

cout << “Matrix (100,100) pixel value " << endl;

cout << "color2gray " << color2gray(roi) << endl;

cout << "color2color " << color2color(roi) << endl;

print_matInfo("color2gray", color2gray);

print_matInfo("color2color", color2color);

imshow("color2gray", color2gray);

imshow("color2color", color2color);

waitKey(0);

return 0;

}







• 

imwrite (имя файла, изображение, вектор параметров)


– 

имя файла: сохранение имени файла

– 

изображение: матрица (изображение) для сохранения

– 

вектор параметров: пара векторов параметров в зависимости от метода сжатия





• 

Легко save (сохранить) image file (файл изображения) с расширением имени (extension name)

• 

Форматы файлов изображений JPG, BMP, PNG, TIF, PPM и т. д.


#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

Mat img8 = imread("../image/read_color.jpg", IMREAD_COLOR);

CV_Assert(img8.data);

vector<int> params_jpg, params_png;

params_jpg.push_back(IMWRITE_JPEG_QUALITY);

params_jpg.push_back(50);

params_png.push_back(IMWRITE_PNG_COMPRESSION);

params_png.push_back(9);

imwrite("../image/write_test1.jpg", img8);

imwrite("../image/write_test2.jpg", img8, params_jpg);

imwrite("../image/write_test.png", img8, params_png);

imwrite("../image/write_test.bmp", img8);

return 0;

}


Обработка видео / Video Processing

• 

Video file (Видеофайл) сжимается (compression) кодеком (codec) в соответствии с форматом (format), а сохраненный видеофайл распаковывается (decompression).

• 

Video Capture Class / Класс видеозахвата: Читать frame (кафраме) с камеры или видео файла

– 

Video Capture /

Захват видео (имя файла, устройство)

• 

device / устройство: идентификатор устройства захвата (Если есть одна камера, 0)

– 

open (): открытие видеофайла или камеры

– 

isOpened(): подключено ли возврат устройства захвата

– 

get(): возвращаемое значение идентификатора свойства

– 

set(): установка свойств видео с использованием идентификатора свойств

– 

read(): чтение видеокадра, затем передача в матрицу изображения

● 

идентификатор свойства

/ properties identifier


• 

Video Writer Class: save (сохранить) image (изображение) matrix (матрицы) в видео файл(video file)


– 

VideoWriter (file name, fourcc, fps, framesize, isColor / имя файла, fourcc, частота кадров, размер кадра, isColor)


• 

fourcc: 4-character code of codec (4-значный код кодека)

• 

fps: frame per second (кадр в секунду)

• 

framesize: video frame size (column x row) /размер видеокадра (столбец x строка)

• 

isColor: true – color ecoding, false – gray frame encoding /

true – кодирование цвета, false – кодирование серого кадра


– 

open () : opening of video file (открытие видеофайла)

– 

isOpened () : будь открытым возврат файла записи видео

– 

write() : writing video frame from image matrix (запись видеокадра из матрицы изображений)


● 

4-значный код кодека (

www.fourcc.org

)


(4-character code of codec (www.fourcc.org)





// Video Frame Reading Program

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

VideoCapture capture(0);

if (!capture.isOpened())

{

cout << “camera not connected!!" << endl;

exit(1);

}

cout << “Width " << capture.get(CAP_PROP_FRAME_WIDTH) << endl;

cout << “Height" << capture.get(CAP_PROP_FRAME_HEIGHT) << endl;

cout << “Exposure " << capture.get(CAP_PROP_EXPOSURE) << endl;

cout << “Brightness " << capture.get(CAP_PROP_BRIGHTNESS) << endl;

// next page continued....


Point shade = Point(10, 40) + Point(2, 2);

int font = FONT_HERSHEY_SIMPLEX;

string text = "EXPOS: " + to_string((int)capture.get(CAP_PROP_EXPOSURE));

Mat frame;

for (;;) {

capture.read(frame);

putText(frame, text, shade, font, 0.7, Scalar(0, 0, 0), 2);                  putText(frame, text, Point(10, 40), font, 0.7, Scalar(120, 200, 90), 2);

imshow(“Camera Viewer", frame);

if (waitKey(30) >= 0)

break;

}

return 0;

}


// Video Frame Writing Program

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

VideoCapture capture(0);

CV_Assert(capture.isOpened());

double fps = 29.97;

int delay = cvRound(1000.0 / fps);

Size size(640, 480);

int fourcc = VideoWriter::fourcc('D', 'X', '5', '0');

capture.set(CAP_PROP_FRAME_WIDTH, size.width);

capture.set(CAP_PROP_FRAME_HEIGHT, size.height);

// next page continued....


cout << "width x height : " << size << endl;

cout << "VideoWriterfourcc : " << fourcc << endl;

cout << "delay : " << delay << endl;

cout << "fps : " << fps << endl;

VideoWriter writer;

writer.open("../image/video_file.avi", fourcc, fps, size);

CV_Assert(writer.isOpened());

Mat frame;

for (;;) {

      capture >> frame;

      writer << frame;

      imshow(“Camera Viewer", frame);

      if (waitKey(delay) >= 0)

            break;

}

return 0;

}


// Video File Reading Program

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

VideoCapture capture;

capture.open("../image/video_file.avi");

CV_Assert(capture.isOpened());

Mat frame;

double frame_rate = capture.get(CAP_PROP_FPS);

int delay = 1000 / frame_rate;

int frame_cnt = 0, font = FONT_HERSHEY_PLAIN;

Point pt(25, 55);

Point shade = pt + Point(2, 2);

// next page continued....


while (capture.read(frame))

{

      if (waitKey(delay) >= 0) break;

      string text = "Frame Count : ";

      text += to_string(frame_cnt++);

      putText(frame, text, shade, font, 1.8, Scalar(0, 0, 0), 2);

      putText(frame, text, pt, font, 1.8, Scalar(120, 200, 90), 2);

      imshow(“Video File Reading", frame);

}

return 0;

}


5. Работа OpenCV с массивами / OpenCV Operation on Arrays


Основные функции обработки массивов / Fundamental Array Processing Functions


• 

flip (src, dst, flipCode): вертикальное, горизонтальное, переворот в обоих направлениях


– 

src: входной массив

– 

dst: внешний массив

– 

flipCode : 0 – горизонтальное перевор

1 – вертикальное переворот

–1 – горизонтальное и вертикальное переворачивание

• 

transpose (): вернуть транспонированную матрицу входной матрицы


// Image Flipping Program

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

Mat image = imread("../image/flip_test.jpg", IMREAD_COLOR);

CV_Assert(image.data);

Mat x_axis, y_axis, xy_axis, trans_img;

flip(image, x_axis, 0);

flip(image, y_axis, 1);

flip(image, xy_axis, -1);

transpose(image, trans_img);

imshow("image", image);

imshow("x_axis", x_axis);

imshow("y_axis", y_axis);

imshow("xy_axis", xy_axis);

imshow("trans_img", trans_img);

waitKey();

return 0;

}


Функции обработки каналов / Channel Processing Functions

Метод сохранения элемента трехканальной матрицы (цвет)




// Image Channel Dividing Program

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

Mat image = imread("../image/color.jpg", IMREAD_COLOR);

CV_Assert(image.data);

Mat bgr[3];

split(image, bgr);

imshow("image", image);

imshow(“Blue Channel", bgr[0]);

imshow(“Green Channel", bgr[1]);

imshow(“Red Channel", bgr[2]);

waitKey(0);

return 0;

}


Четыре фундаментальные операции над массивами / The Four Fundamental Operations of Arrays


• 

Выполняет поэлементную (element-wise) операцию (operation)

• 

add (), subtract (), multiply (), divide ()

• 


element-wise

element-wise


// The Four Fundamental Operations of Arrays

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

Mat m1(3, 6, CV_8UC1, Scalar(10));

Mat m2(3, 6, CV_8UC1, Scalar(50));

Mat m_add1, m_add2, m_sub, m_div1, m_div2;

Mat mask(m1.size(), CV_8UC1, Scalar(0));

Rect rect(Point(3, 0), Size(3, 3));

mask(rect).setTo(1);

add(m1, m2, m_add1);

add(m1, m2, m_add2, mask);

// next page continued....


divide(m1, m2, m_div1);

m1.convertTo(m1, CV_32F);

m2.convertTo(m2, CV_32F);

divide(m1, m2, m_div2);

cout << "[m1] = " << endl << m1 << endl;

cout << "[m2] = " << endl << m2 << endl;

cout << "[mask] = " << endl << mask << endl << endl;

cout << "[m_add1] = " << endl << m_add1 << endl;

cout << "[m_add2] = " << endl << m_add2 << endl;

cout << "[m_div1] = " << endl << m_div1 << endl;

cout << "[m_div2] = " << endl << m_div2 << endl;

return 0;

}


Операции с корнем, степенью и величиной массивов / Root, Power, Magnitude Operations of Arrays

• 

sqrt (input, ouput): вычисление квадратного корня из всех элементов массива

• 

pow (input, power, ouput):

расчет мощности всех элементов массива

• 

magnitude (x, y, output): расчет величин векторов x и y


• 

exp (input, ouput): вычисление экспоненты всех элементов массива

• 

log (input, ouput): вычисление натуральных логарифмов всех элементов массива


Логические битовые операции с массивами / Logical Bit Operations of Arrays

• 

Выполнять logical operation (логические операции) в битовых единицах (bit-wise) элементов массива (array elements)

• 

bitwise_and (вход 1, вход 2, выход, маска)


– 

mask: Выполнять расчеты только для позиций с ненулевым значением


• 

bitwise_or (вход 1, вход 2, выход, маска)

• 

bitwise_xor (вход 1, вход 2, выход, маска)

• 

bitwise_not (вход, вывод, маска)


// Logical Bit Operations of Arrays

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

Mat image1(250, 250, CV_8U, Scalar(0));

Mat image2(250, 250, CV_8U, Scalar(0));

Mat image3, image4, image5, image6;

Point center = image1.size() / 2;

circle(image1, center, 80, Scalar(255), -1);

rectangle(image2, Point(0, 0), Point(125, 250), Scalar(255), -1);

bitwise_or(image1, image2, image3);

bitwise_and(image1, image2, image4);

bitwise_xor(image1, image2, image5);

bitwise_not(image1, image6);

imshow("image1", image1);

imshow("image2", image2);

imshow("bitwise_or", image3);

imshow("bitwise_and", image4);

imshow("bitwise_xor", image5);

imshow("bitwise_not", image6);

waitKey();

return 0;

}


● 

Выход (Output)
















Абсолютное значение, Макс., Мин. Операции с массивами / Absolute value, Max, Min Operations of Arrays

• 

abs (): Расчет абсолютного значения всех элементов массива

• 

absdiff (): После поэлементного (element-wise) вычитания двух массивов рассчитайте absolute value (абсолютное значение).

• 

max (src1, src2, dst): сравнить src1 и src2 поэлементно (element-wise) и return большое значение в dst matrix

• 

min (src1, src2, dst): сравнить src1 и src2 поэлементно (element-wise) и return Меньшие значение в dst matrix


// Absolute value, Max, Min Operations of Arrays

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

Mat image1 = imread("../image/Semiconduct.tif", 0);

Mat image2 = imread("../image/Semiconduct2.tif", 0);

CV_Assert(image1.data && image2.data);

Mat dif_img, abs_dif1, abs_dif2;

image1.convertTo(image1, CV_16S);

image2.convertTo(image2, CV_16S);

subtract(image1, image2, dif_img);

abs_dif1 = abs(dif_img);

image1.convertTo(image1, CV_8U);

image2.convertTo(image2, CV_8U);

dif_img.convertTo(dif_img, CV_8U);

abs_dif1.convertTo(abs_dif1, CV_8U);

// next page continued....


absdiff(image1, image2, abs_dif2);

imshow("image1", image1), imshow("image2", image2);

imshow("dif_img", dif_img);

imshow("abs_dif1", abs_dif1), imshow("abs_dif2", abs_dif2);

Mat image_max, image_min;

image1 = imread("../image/abs_test1.jpg", 0);

image2 = imread("../image/abs_test2.jpg", 0);

CV_Assert(image1.data && image2.data);


max(image1, 120, image_max);

min(image1, image2, image_min);

image_max.convertTo(image_max, CV_8U);

image_min.convertTo(image_min, CV_8U);

imshow("image_max", image_max);

imshow("image_min", image_min);

waitKey();

return 0;

}


Статистические операции с массивами / Statistics Operations of Arrays

• 

sum (input): вычисляет сумму элементов (element) для каждого канала (channel) в array (массиве)

• 

mean (input, mask): вычисляет среднее значение элементов (element) для каждого канала (channel) в array


– 

mask: Выполнять расчеты только для позиций с ненулевым значением


• 

mean Std Dev (input, mean, stddev, mask): Рассчитать среднее (mean) и стандартное отклонение (standard deviation) элементов массива (array elements).

• 

count Non Zero (): return (Вернуть) количество ненулевых элементов массива


// Statistics Operations of Arrays

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

Mat image = imread("../image/sum_test.jpg", 1);

CV_Assert(image.data);

Mat mask(image.size(), CV_8U, Scalar(0));

mask(Rect(20, 40, 70, 70)).setTo(255);

Scalar sum_value = sum(image);

Scalar mean_value1 = mean(image);

Scalar mean_value2 = mean(image, mask);

cout << "[sum_value] = " << sum_value << endl;

cout << "[mean_value1] = " << mean_value1 << endl;

cout << "[mean_value2] = " << mean_value2 << endl << endl;

// next page continued....


Mat mean, stddev;

meanStdDev(image, mean, stddev);

cout << "[mean] = " << mean << endl;

cout << "[stddev] = " << stddev << endl << endl;

meanStdDev(image, mean, stddev, mask);

cout << "[mean] = " << mean << endl;

cout << "[stddev] = " << stddev << endl;

imshow("image", image), imshow("mask", mask);

waitKey();

return 0;

}


6. Обработка изображений с использованием OpenCV / Image

Processing using OpenCV

Доступ к пикселям изображения / Image Pixel Access

• 

Mat::at (): Функция шаблона (template function), которая access (обращается) к указанному элементу (пикселю) (element (pixel)) матрицы (matrix).

• 

Тип возвращаемых данных (return data type) функции Mat :: at () должен соответствовать типу данных (data type) элемента массива (array element).

• 

mat1.at<uchar>(10, 20);

• 

mat2.at<int>(i, j);

• 

mat3.at<double>(y, x);

• 

mat4.at<Vec3d>(y, x)[0];


Пиксельное отображение изображения / Image Pixel Display

// Image Pixel Display

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

Mat image = imread("../image/pixel_test.jpg", IMREAD_GRAYSCALE);

if (image.empty()){

      cout << “can’t open Image!!!" << endl;

      exit(1);

}

Rect roi(135, 95, 20, 15);

Mat roi_img = image(roi);

Mat image_roi(Size(roi_img.cols * 10, roi_img.rows * 10), CV_8U, Scalar(0));

// next page continued....

for (int i = 0; i < roi_img.rows; i++) {

for (int j = 0; j < roi_img.cols; j++) {

      for (int k = 0; k < 10; k++) {

       for (int m = 0; m < 10; m++)

            image_roi.at<uchar>(i*10+k, j*10+m) = roi_img.at<uchar>(i, j);

      }

}

}

imshow("image_roi", image_roi);

cout << "[roi_img] =" << endl;

      cout << roi_img << endl;

rectangle(image, roi, Scalar(255), 1);

imshow("image", image);

waitKey();

return 0;

}

● 

Выход /

Output



Сложение/вычитание значения яркости изображения / Addition/Subtraction of Image Brightness Value


// Addition/Subtraction of Image Brightness Value

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

int main()

{

Mat image = imread("../image/bright.jpg", IMREAD_GRAYSCALE);

CV_Assert(!image.empty());

Mat dst1 = image + 100;      // Automatic saturate_cast

Mat dst2 = image – 100;      // Automatic saturate_cast

Mat dst3 = 255 – image;      // Image negative transform

Mat dst4(image.size(), image.type());

Mat dst5(image.size(), image.type());

// next page continued....


for (int i = 0; i < image.rows; i++) {

      for (int j = 0; j < image.cols; j++) {

            dst4.at<uchar>(i, j) = image.at<uchar>(i, j) + 100;

            dst5.at<uchar>(i, j) = 255 – image.at<uchar>(i, j);

      }

}

imshow(“Original Image", image);

imshow("dst1 – Brighter", dst1);

imshow("dst2 – Darker", dst2);

imshow("dst3 – Inversion", dst3);

imshow("dst4 – Brighter", dst4);

imshow("dst5 – Darker", dst5);

waitKey();

return 0;

}

//dst4.at<uchar>(i, j) = saturate_cast<uchar>(image.at<uchar>(i, j) + 100);


Гистограмма / Histogram

• 

График, показывающий количество значений яркости каждого пикселя (pixel) в image (изображении)

• 

Горизонтальная ось – значение яркости пикселя

• 

Вертикальная ось – частота (frequency) яркости (brightness) каждого пикселя (pixel)

• 

Image вы можете узнать распределение значений яркости пикселей для


• 

Предоставленная Open CV Histogram Calculation Function (функция вычисления гистограммы)

calcHist (img, nimg, chn, mask, hist, dims, histsize, range)

– 

img: исходный массив изображений (тип данных CV_8U или CV_32F)

– 

nimg: номера оригинальных изображений

– 

chn: список каналов

– 

mask: mask array (Выполнять расчеты только для позиций с ненулевым значением)

– 

hist: гистограмма, сохраняющая массив результатов вычислений

– 

dims: номер измерения гистограммы

– 

histsize: размер массива гистограммы каждого измерения

– 

range: диапазон значений пикселей гистограммы


Расчет гистограммы / Histogram Calculation


// Histogram Calculation

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

void calc_Histo(const Mat& image, Mat& hist, int bins, int range_max = 256)

{

int histSize[] = { bins };

float range[] = { 0, (float)range_max };

      int channels[] = { 0 };

const float* ranges[] = { range };

calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges); // OpenCV

}

int main()

{

Mat image = imread("../image/pixel_test.jpg", IMREAD_GRAYSCALE);

CV_Assert(!image.empty());

Mat hist, hist_img;

calc_Histo(image, hist, 256);

cout << hist.t() << endl;

imshow("image", image);

waitKey();

return 0;

}


● 

Выход

/ Output



Рисование гистограммы / Histogram Drawing


// Histogram Drawing Program

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

void calc_Histo(const Mat& image, Mat& hist, int bins, int range_max = 256)

{

int histSize[] = { bins };

float range[] = { 0, (float)range_max };

int channels[] = { 0 };

const float* ranges[] = { range };

calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges);

}

void draw_histo(Mat hist, Mat &hist_img, Size size = Size(256, 200))

{

hist_img = Mat(size, CV_8U, Scalar(255));

normalize(hist, hist, 0, hist_img.rows, NORM_MINMAX);

// next page continued....


for (int i = 0; i < hist.rows; i++){

Point2f pt1 = Point2f(i, 0);

Point2f pt2 = Point2f((i + 1), hist.at <float>(i));

if (pt2.y > 0)

      rectangle(hist_img, pt1, pt2, Scalar(0), -1);

}

flip(hist_img, hist_img, 0);

}

int main()

{

Mat image = imread("../image/lena_std.tif", IMREAD_GRAYSCALE);

CV_Assert(!image.empty());

Mat hist, hist_img;

calc_Histo(image, hist, 256);

draw_histo(hist, hist_img);

imshow(“Histogram Image”, hist_img);

imshow(“Image", image);

waitKey();

return 0;

}



Растяжение гистограммы / Histogram Stretching











①




②


③


// Histogram Stretching Program

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

void calc_Histo(const Mat& image, Mat& hist, int bins, int range_max = 256)

{

int histSize[] = { bins };

float range[] = { 0, (float)range_max };

int channels[] = { 0 };

const float* ranges[] = { range };

calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges);

}

void draw_histo(Mat hist, Mat &hist_img, Size size = Size(256, 200))

{

hist_img = Mat(size, CV_8U, Scalar(255));

normalize(hist, hist, 0, hist_img.rows, NORM_MINMAX);

for (int i = 0; i < hist.rows; i++) {

Point2f pt1 = Point2f(i, 0);

Point2f pt2 = Point2f((i+1), hist.at <float>(i));

if (pt2.y > 0)

rectangle(hist_img, pt1, pt2, Scalar(0), -1);

}

flip(hist_img, hist_img, 0);

}

void search_valueIdx(Mat hist, int &low_value, int &high_value)

{

int i;

for (i = 0; i < hist.rows; i++) {

if (hist.at<float>(i) > 0)

break;

}

low_value = i;

// next page continued....


for (i = hist.rows-1; i > 0; i–){

      if (hist.at<float>(i) > 0)

break;

}

high_value = i;

}

int main()

{

Mat image = imread("../image/Lenna-histo_str.tif", 0);

CV_Assert(!image.empty());

Mat hist, hist_dst, hist_img, hist_dst_img;

int histsize = 256, ranges = 256;

calc_Histo(image, hist, histsize, ranges);

draw_histo(hist, hist_img);

int low_value, high_value;

search_valueIdx(hist, low_value, high_value);

cout << "high_value = " << high_value << endl;

cout << "low_value = " << low_value << endl;

int d_value = high_value – low_value;

Mat dst = (image – low_value) * (255.0 / d_value);

calc_Histo(dst, hist_dst, histsize, ranges);

draw_histo(hist_dst, hist_dst_img);

imshow("Original Image", image);

imshow("Hist. Stretch. Image", dst);

imshow("Hist. of Origin", hist_img);

imshow("Hist. of Stretch. Image", hist_dst_img);

waitKey();

return 0;

}


Выравнивание гистограммы / Histogram Equalization

• 

Применяется к изображениям с широким распределением гистограммы (Histogram), но с распределением контраста, смещенным в одном направлении


• 

[Шаг 1] Расчет гистограммы

• 

[Шаг 2] Расчет накопленной суммы гистограммы



• 

[Шаг 3] Нормализация накопленной суммы

: Общее количество пикселей

: Максимальное значение яркости пикселей


● 

Шаг 1

– Расчет гистограммы


ㅔㅑㅔㅑㅑ

a) яркость пикселей


изображение

изображение


image

(b) histogram

яркость пикселей


● 

Шаг 2

– Расчет накопленной суммы гистограммы


(a)Гистограмма


яркость пикселей


(b) Накопленная сумма


● 

Шаг 3

– Нормализация накопленной суммы

– 

n[i]=sum[i]*(1/16)*7


j Нормализованная гистограмма




(b) гистограмма


(a) входное изображение







// Histogram Equalization Program

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

void calc_Histo(const Mat& image, Mat& hist, int bins, int range_max = 256)

{

int histSize[] = { bins };

float range[] = { 0, (float)range_max };

int channels[] = { 0 };

const float* ranges[] = { range };

calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges);

}

void draw_histo(Mat hist, Mat &hist_img, Size size = Size(256, 200))

{

hist_img = Mat(size, CV_8U, Scalar(255));

Mat hist2;

normalize(hist, hist2, 0, hist_img.rows, NORM_MINMAX);

for (int i = 0; i < hist2.rows; i++) {

Point2f pt1 = Point2f(i, 0);

Point2f pt2 = Point2f((i+1), hist2.at <float>(i));

if (pt2.y > 0)

rectangle(hist_img, pt1, pt2, Scalar(0), -1);

}

flip(hist_img, hist_img, 0);

}

void create_hist(Mat img, Mat &hist, Mat &hist_img)

{

int histsize = 256, range = 256;

calc_Histo(img, hist, histsize, range);

draw_histo(hist, hist_img);

}

// next page continued....


int main()

{

Mat image = imread("../image/Ave.tif", 0);

CV_Assert(!image.empty());

Mat hist, dst1, dst2, hist_img, hist_img1, hist_img2;

create_hist(image, hist, hist_img);

Mat accum_hist = Mat(hist.size(), hist.type(), Scalar(0));

accum_hist.at<float>(0) = hist.at<float>(0);

for (int i = 1; i < hist.rows; i++)

accum_hist.at<float>(i) = accum_hist.at<float>(i – 1) + hist.at<float>(i);

accum_hist /=(image.rows*image.cols);;

accum_hist *= 255;

dst1 = Mat(image.size(), CV_8U);

for (int i = 0; i < image.rows; i++) {

for (int j = 0; j < image.cols; j++) {

int idx = image.at<uchar>(i, j);

      dst1.at<uchar>(i, j) = (uchar)accum_hist.at<float>(idx);

}

}

create_hist(dst1, hist, hist_img1);

// Using Histogram Equalization of OpenCV Function

equalizeHist(image, dst2);

create_hist(dst2, hist, hist_img2);

imshow(“image", image), imshow("img_hist", hist_img);

imshow("dst1-User", dst1), imshow("User_hist", hist_img1);

imshow("dst2-OpenCV", dst2), imshow("OpenCV_hist", hist_img2);

waitKey();

return 0;

}


7. Обработка свертки с использованием OpenCV / Convolution

Processing using OpenCV

Обработка свертки / Convolution Processing

• 

Изображение обрабатывается с использованием метода свертки (convolution technique), включая ассоциацию с соседним пикселем (neighbor pixel) пикселя

• 

использование Mask (= Kernel, Window, Filter)


Маска(М)


Соседние пиксели


Входное изображение(f)


Текущий пиксели


Pixel

Выходной пиксель


Выходное изображение (г)


Сумма всех умножений


Умножение маски и соседних пикселей


Размытие / Blurring

• 

Как внести постепенные изменения в резкость изменения значения пикселя (pixel value)

• 

Обработка свертки с использованием маски размытия.

• 

Маска размытия


Входное изображение


(a) Входное изображение


(b) Размытое изображение


// Blurring Program

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

void filter(Mat img, Mat& dst, Mat mask)

{

dst = Mat(img.size(), CV_32F, Scalar(0));

// Image Extension (using 3 x 3 Mask)

Mat ExtImg(img.rows+2, img.cols+2, CV_32F);

for (int i = 0; i < img.rows; i++) {

for (int j = 0; j < img.cols; j++)

ExtImg.at<float>(i + 1, j + 1) = img.at<uchar>(i, j); // center

}

for (int i = 1; i < img.rows+1; i++) {

ExtImg.at<float>(i, 0) = ExtImg.at<float>(i, 1);      // Left line

ExtImg.at<float>(i, img.cols + 1) = ExtImg.at<float>(i, img.cols); // Right line

}

for (int j = 1; j < img.cols+1; j++){

ExtImg.at<float>(0, j) = ExtImg.at<float>(1, j);      // Upper line

ExtImg.at<float>(img.rows + 1, j) = ExtImg.at<float>(img.rows, j); // Bottom line

}

ExtImg.at<float>(0, 0) = ExtImg.at<float>(1, 1); // Upper left corner

ExtImg.at<float>(0, img.cols+1) = ExtImg.at<float>(1, img.cols); // Upper right corner

ExtImg.at<float>(img.rows+1, 0) = ExtImg.at<float>(img.rows, 1); // Bottom left corner

ExtImg.at<float>(img.rows+1, img.cols+1) = ExtImg.at<float>(img.rows, img.cols); // Bottom right

                                     // corner

// next page continued....


for (int i = 0; i < img.rows; i++) {

for (int j = 0; j < img.cols; j++) {

float sum = 0;

for (int u = 0; u < mask.rows; u++) {

      for (int v = 0; v < mask.cols; v++)

       sum += ExtImg.at<float>(i + u, j + v) * mask.at<float>(u, v);

}

dst.at<float>(i, j) = sum;

}

}

}

int main()

{

Mat image = imread("../image/filter_blur.jpg", IMREAD_GRAYSCALE);

CV_Assert(image.data);

float data[] = {

1 / 9.f, 1 / 9.f, 1 / 9.f,

1 / 9.f, 1 / 9.f, 1 / 9.f,

1 / 9.f, 1 / 9.f, 1 / 9.f };

Mat mask(3, 3, CV_32F, data), blur;

filter(image, blur, mask);

blur.convertTo(blur, CV_8U);

namedWindow(“Original Image", WINDOW_AUTOSIZE);

namedWindow(“Blurring", WINDOW_AUTOSIZE);

moveWindow(“Original Image", 200, 200), moveWindow(“Blurring", 600, 200);

imshow(“Original image", image), imshow(“Blurring", blur);

waitKey();

return 0;

}


Заточка / Sharpening

• 

Разница между соседними пикселями (neighbor pixel) заставляет их чувствовать себя резкими

• 

Детали изображения могут быть подчеркнуты, а контраст яркости (brightness contrast) увеличен на краевой (edge) части

• 

Заточка маски


(a) Входное изображение


(b) Резкое изображение


// Sharpening Program

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

void filter(Mat img, Mat& dst, Mat mask)

{

dst = Mat(img.size(), CV_32F, Scalar(0));

// Image Extension (using 3 x 3 Mask)

Mat ExtImg(img.rows+2, img.cols+2, CV_32F);

for (int i = 0; i < img.rows; i++) {

for (int j = 0; j < img.cols; j++)

ExtImg.at<float>(i + 1, j + 1) = img.at<uchar>(i, j); // center

}

for (int i = 1; i < img.rows+1; i++) {

ExtImg.at<float>(i, 0) = ExtImg.at<float>(i, 1);      // Left line

ExtImg.at<float>(i, img.cols + 1) = ExtImg.at<float>(i, img.cols); // Right line

}

for (int j = 1; j < img.cols+1; j++){

ExtImg.at<float>(0, j) = ExtImg.at<float>(1, j);      // Upper line

ExtImg.at<float>(img.rows + 1, j) = ExtImg.at<float>(img.rows, j); // Bottom line

}

ExtImg.at<float>(0, 0) = ExtImg.at<float>(1, 1); // Upper left corner

ExtImg.at<float>(0, img.cols+1) = ExtImg.at<float>(1, img.cols); // Upper right corner

ExtImg.at<float>(img.rows+1, 0) = ExtImg.at<float>(img.rows, 1); // Bottom left corner

ExtImg.at<float>(img.rows+1, img.cols+1) = ExtImg.at<float>(img.rows, img.cols); // Bottom right

                                     // corner

// next page continued....

for (int i = 0; i < img.rows; i++) {

for (int j = 0; j < img.cols; j++) {

float sum = 0;

for (int u = 0; u < mask.rows; u++) {

      for (int v = 0; v < mask.cols; v++)

       sum += ExtImg.at<float>(i + u, j + v) * mask.at<float>(u, v);

}

dst.at<float>(i, j) = sum;

}

}

}

int main()

{

Mat image = imread("../image/filter_sharpen.jpg", IMREAD_GRAYSCALE);

CV_Assert(image.data);

float data[] = {

–1, -1, -1,

–1, 9, -1,

–1, -1, -1};

Mat mask(3, 3, CV_32F, data), sharpen;

filter(image, sharpen, mask);

sharpen.convertTo(sharpen, CV_8U);

namedWindow(“Original Image", WINDOW_AUTOSIZE);

namedWindow(“Sharpening Image", WINDOW_AUTOSIZE);

moveWindow("Original Image", 200, 200), moveWindow("Sharpening Image", 600, 200);

imshow("Original Image", image), imshow("Sharpening Image", sharpen);

waitKey();

return 0;

}

Обнаружение края / Edge Detection

• 

В изображении край (edge) – это часть, где значение пикселя (pixel value) резко меняется

Hhh

• 

Однородный оператор

– центральный пиксель 8 – дифференциальный расчет

● 

Дифференциальный оператор

– центральный пиксель и пиксель на противоположной стороне и 4 дифференциальных вычисления (differential calculation)

Выход дифференциального оператора =

Однородный вывод оператора

Обнаружение края (однородный оператор) / Edge Detection (Homogeneous Operator)

// Edge Detection (Homogeneous Operator) Program

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

void homogenOp(Mat img, Mat& dst, int mask_size)

{

dst = Mat(img.size(), CV_8U, Scalar(0));

// Image Extension (using 3 x 3 Mask)

Mat ExtImg(img.rows + 2, img.cols + 2, CV_32F);

for (int i = 0; i < img.rows; i++) {

for (int j = 0; j < img.cols; j++)

ExtImg.at<float>(i + 1, j + 1) = img.at<uchar>(i, j);

}

for (int i = 1; i < img.rows + 1; i++) {

ExtImg.at<float>(i, 0) = ExtImg.at<float>(i, 1);

ExtImg.at<float>(i, img.cols + 1) = ExtImg.at<float>(i, img.cols);

}

for (int j = 1; j < img.cols + 1; j++) {

ExtImg.at<float>(0, j) = ExtImg.at<float>(1, j);

ExtImg.at<float>(img.rows + 1, j) = ExtImg.at<float>(img.rows, j);

}

ExtImg.at<float>(0, 0) = ExtImg.at<float>(1, 1);

ExtImg.at<float>(0, img.cols + 1) = ExtImg.at<float>(1, img.cols);

ExtImg.at<float>(img.rows + 1, 0) = ExtImg.at<float>(img.rows, 1);

ExtImg.at<float>(img.rows + 1, img.cols + 1) = ExtImg.at<float>(img.rows, img.cols);

// next page continued....

Обнаружение края (однородный оператор) / Edge Detection (Homogeneous Operator)

for (int i = 0; i < img.rows; i++) {

for (int j = 0; j < img.cols; j++) {

float max = 0;

for (int u = 0; u < mask_size; u++) {

      for (int v = 0; v < mask_size; v++) {

       float difference = abs(ExtImg.at<float>(i+1, j+1) – ExtImg.at<float>(i+u, j+v));

       if (difference > max)

            max = difference;

      }

}

dst.at<uchar>(i, j) = max;

}

}

}

int main()

{

Mat image = imread("../image/edge_test.jpg", IMREAD_GRAYSCALE);

CV_Assert(image.data);

Mat edge;

homogenOp(image, edge, 3);

namedWindow(“Original Image", WINDOW_AUTOSIZE);

namedWindow(“Homogen. Edge", WINDOW_AUTOSIZE);

moveWindow(“Original Image", 200, 200);

moveWindow("Homogen. Edge", 600, 200);

imshow(“Original Image", image);

imshow("Homogen. Edge", edge);

waitKey();

return 0;

}

Обнаружение края (Дифференциальный оператор) / Edge Detection (Differential Operator)

// Edge Detection (Differential Operator) Program

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

void differOp(Mat img, Mat& dst, int mask_size)

{

dst = Mat(img.size(), CV_8U, Scalar(0));

// Image Extension (using 3 x 3 Mask)

Mat ExtImg(img.rows + 2, img.cols + 2, CV_32F);

for (int i = 0; i < img.rows; i++) {

for (int j = 0; j < img.cols; j++)

ExtImg.at<float>(i + 1, j + 1) = img.at<uchar>(i, j);

}

for (int i = 1; i < img.rows + 1; i++) {

ExtImg.at<float>(i, 0) = ExtImg.at<float>(i, 1);

ExtImg.at<float>(i, img.cols + 1) = ExtImg.at<float>(i, img.cols);

}

for (int j = 1; j < img.cols + 1; j++) {

ExtImg.at<float>(0, j) = ExtImg.at<float>(1, j);

ExtImg.at<float>(img.rows + 1, j) = ExtImg.at<float>(img.rows, j);

}

ExtImg.at<float>(0, 0) = ExtImg.at<float>(1, 1);

ExtImg.at<float>(0, img.cols + 1) = ExtImg.at<float>(1, img.cols);

ExtImg.at<float>(img.rows + 1, 0) = ExtImg.at<float>(img.rows, 1);

ExtImg.at<float>(img.rows + 1, img.cols + 1) = ExtImg.at<float>(img.rows, img.cols);

// next page continued....

// Edge Detection (Differential Operator) Program

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

void differOp(Mat img, Mat& dst, int mask_size)

{

dst = Mat(img.size(), CV_8U, Scalar(0));

// Image Extension (using 3 x 3 Mask)

Mat ExtImg(img.rows + 2, img.cols + 2, CV_32F);

for (int i = 0; i < img.rows; i++) {

for (int j = 0; j < img.cols; j++)

ExtImg.at<float>(i + 1, j + 1) = img.at<uchar>(i, j);

}

for (int i = 1; i < img.rows + 1; i++) {

ExtImg.at<float>(i, 0) = ExtImg.at<float>(i, 1);

ExtImg.at<float>(i, img.cols + 1) = ExtImg.at<float>(i, img.cols);

}

for (int j = 1; j < img.cols + 1; j++) {

ExtImg.at<float>(0, j) = ExtImg.at<float>(1, j);

ExtImg.at<float>(img.rows + 1, j) = ExtImg.at<float>(img.rows, j);

}

ExtImg.at<float>(0, 0) = ExtImg.at<float>(1, 1);

ExtImg.at<float>(0, img.cols + 1) = ExtImg.at<float>(1, img.cols);

ExtImg.at<float>(img.rows + 1, 0) = ExtImg.at<float>(img.rows, 1);

ExtImg.at<float>(img.rows + 1, img.cols + 1) = ExtImg.at<float>(img.rows, img.cols);

// next page continued....

for (int i = 0; i < img.rows; i++) {

for (int j = 0; j < img.cols; j++) {

vector<float> mask;

for (int u = 0; u < mask_size; u++) {

      for (int v = 0; v < mask_size; v++)

       mask.push_back(ExtImg.at<float>(i + u, j + v));

}

float max = 0;

for (int k = 0; k <= mask_size; k++) {

      float difference = abs(mask[k]-mask[8-k]);

      if (difference > max) max = difference;

}

dst.at<uchar>(i, j) = max;

}

}

}

int main()

{

Mat image = imread("../image/edge_test.jpg", IMREAD_GRAYSCALE);

CV_Assert(image.data);

Mat edge;

differOp(image, edge, 3);

namedWindow(“Original Image", WINDOW_AUTOSIZE);

namedWindow(“Diff. Edge", WINDOW_AUTOSIZE);

moveWindow("Original Image", 200, 200), moveWindow("Diff. Edge", 600, 200);

imshow("Original Image", image), imshow("Diff. Edge", edge);

waitKey();

return 0;

}

Обнаружение краев (оператор маски Робертса/Собела) / Edge Detection (Roberts/Sobel Mask Operator)

● 

Оператор маски Робертса

/ Roberts Mask Operator

163-iň suratyny alyp bilmedim.

● 

Оператор Маски Собел (Оператор Маски Собел)

/

Sobel Mask Operator (Sobel Mask Operator)

Обнаружение края (оператор маски Робертса) / Edge Detection (Roberts Mask Operator)

// Edge Detection (Roberts Mask Operator)

// Using filter2D function of OpenCV

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

void differential(Mat image, Mat& dst, float data1[], float data2[])

{

Mat dst1, mask1(3, 3, CV_32F, data1);

Mat dst2, mask2(3, 3, CV_32F, data2);

filter2D(image, dst1, CV_32F, mask1, Point(-1, -1), 0, BORDER_REPLICATE);

filter2D(image, dst2, CV_32F, mask2, Point(-1, -1), 0, BORDER_REPLICATE);

       // Point : filtering start point of kernel, 0 : value added to result

       // BORDER_REPLICATE : image extension using border replication

magnitude(dst1, dst2, dst);

dst.convertTo(dst, CV_8U);

dst1 = abs(dst1);

      dst2 = abs(dst2);

dst1.convertTo(dst1, CV_8U);

dst2.convertTo(dst2, CV_8U);

namedWindow(“Mask 1 Result", WINDOW_AUTOSIZE);

namedWindow("Mask 2 Result", WINDOW_AUTOSIZE);

moveWindow("Mask 1 Result", 200, 500);

moveWindow("Mask 2 Result", 700, 500);

imshow("Mask 1 Result", dst1);

imshow("Mask 2 Result", dst2);

}

// next page continued....

int main()

{

Mat image = imread("../image/edge_test1.jpg", IMREAD_GRAYSCALE);

CV_Assert(image.data);

float data1[] = {

      -1, 0, 0,

      0, 1, 0,

      0, 0, 0

};

float data2[] = {

      0, 0, -1,

      0, 1, 0,

      0, 0, 0

};

Mat dst;

differential(image, dst, data1, data2);

namedWindow(“Original Image", WINDOW_AUTOSIZE);

namedWindow(“Roberts Edge", WINDOW_AUTOSIZE);

moveWindow("Original Image", 200, 100);

moveWindow("Roberts Edge", 700, 100);

imshow("Original Image”, image);

imshow("Roberts Edge", dst);

waitKey();

return 0;

}

Обнаружение края (оператор маски Собеля) / Edge Detection (Sobel Mask Operator)

// Edge Detection (Sobel Mask Operator)

// Using filter2D and Sobel function of OpenCV

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

void differential(Mat image, Mat& dst, float data1[], float data2[])

{

Mat dst1, mask1(3, 3, CV_32F, data1);

Mat dst2, mask2(3, 3, CV_32F, data2);

filter2D(image, dst1, CV_32F, mask1, Point(-1, -1), 0, BORDER_REPLICATE);

      filter2D(image, dst2, CV_32F, mask2, Point(-1, -1), 0, BORDER_REPLICATE);

magnitude(dst1, dst2, dst);

dst.convertTo(dst, CV_8U);

convertScaleAbs(dst1, dst1);

convertScaleAbs(dst2, dst2);

namedWindow("dst1 – Vertical Mask", WINDOW_AUTOSIZE);

namedWindow("dst2 – Horiz. Mask", WINDOW_AUTOSIZE);

moveWindow("dst1 – Vertical Mask", 700, 100);

moveWindow("dst2 – Horiz. Mask", 700, 500);

imshow("dst1 – Vertical Mask", dst1);

imshow("dst2 – Horiz. Mask", dst2);

}

int main()

{

Mat image = imread("../image/edge_test1.jpg", IMREAD_GRAYSCALE);

CV_Assert(image.data);

// next page continued....

float data1[] = {

      -1, 0, 1,

      -2, 0, 2,

      -1, 0, 1 };

float data2[] = {

      -1, -2, -1,

      0, 0, 0,

      1, 2, 1 };

Mat dst, dst3, dst4;

differential(image, dst, data1, data2);

namedWindow(“Original Image", WINDOW_AUTOSIZE);

namedWindow(“Sobel Edge", WINDOW_AUTOSIZE);

moveWindow("Original Image", 200, 100);

moveWindow("Sobel Edge", 200, 500);

imshow("Original Image", image);

imshow("Sobel Edge", dst);

// Sobel Edge Detection using OpenCV Function

Sobel(image, dst3, CV_32F, 1, 0, 3); // 4th = 1 -> vertical mask (vertical edge)

Sobel(image, dst4, CV_32F, 0, 1, 3); // 5th = 1 -> horizontal mask (horizontal edge)

convertScaleAbs(dst3, dst3); // 3 -> kernal size

      convertScaleAbs(dst4, dst4);

namedWindow("dst3 – vert._OpenCV", WINDOW_AUTOSIZE);

namedWindow("dst4 – horiz._OpenCV", WINDOW_AUTOSIZE);

moveWindow("dst3 – vert._OpenCV", 1200, 100);

moveWindow("dst4 – horiz._OpenCV", 1200, 500);

imshow("dst3 – vert.OpenCV", dst3), imshow("dst4 – horiz._OpenCV", dst4);

waitKey();

return 0;

}

Медианный фильтр / Median Filter



Медианный фильтр / Median Filter

– 

После выравнивания значений соседних пикселей (neighbor pixel) в порядке возрастания выберите значение центра в качестве выходного значения

– 

Используется для удаления импульсного шума (impulse noise), который имеет резкое изменение цвета, как искра(spark) на изображении (image)

// Median Filtering Program

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

void medianFilter(Mat img, Mat& dst, int size)

{

dst = Mat(img.size(), CV_8U, Scalar(0));

// Image Extension (using 3 x 3 Mask)

Mat ExtImg(img.rows + 2, img.cols + 2, CV_32F);

for (int i = 0; i < img.rows; i++) {

for (int j = 0; j < img.cols; j++)

ExtImg.at<float>(i + 1, j + 1) = img.at<uchar>(i, j);

}

for (int i = 1; i < img.rows + 1; i++) {

ExtImg.at<float>(i, 0) = ExtImg.at<float>(i, 1);

ExtImg.at<float>(i, img.cols + 1) = ExtImg.at<float>(i, img.cols);

}

for (int j = 1; j < img.cols + 1; j++) {

ExtImg.at<float>(0, j) = ExtImg.at<float>(1, j);

ExtImg.at<float>(img.rows + 1, j) = ExtImg.at<float>(img.rows, j);

}

ExtImg.at<float>(0, 0) = ExtImg.at<float>(1, 1);

ExtImg.at<float>(0, img.cols + 1) = ExtImg.at<float>(1, img.cols);

ExtImg.at<float>(img.rows + 1, 0) = ExtImg.at<float>(img.rows, 1);

ExtImg.at<float>(img.rows + 1, img.cols + 1) = ExtImg.at<float>(img.rows, img.cols);

// next page continued....

for (int i = 0; i < img.rows; i++) {

for (int j = 0; j < img.cols; j++) {

vector<float> mask;

for (int u = 0; u < size; u++) {

      for (int v = 0; v < size; v++)

       mask.push_back(ExtImg.at<float>(i + u, j + v));

}

cv::sort(mask, mask, SORT_EVERY_ROW); // cv:: writing to distinguish from std::sort()

dst.at<uchar>(i, j) = (uchar)mask[4];

}

}

}

int main()

{

Mat gray = imread("../image/Boat-noise.tif", IMREAD_GRAYSCALE);

CV_Assert(gray.data);

Mat med_img1, med_img2;

namedWindow("Original Image", WINDOW_AUTOSIZE);

moveWindow("Original Image", 200, 200);

imshow("Original Image", gray);

medianFilter(gray, med_img1, 3); // Median Filtering using User Function

namedWindow("median-User", WINDOW_AUTOSIZE);

moveWindow("median-User", 600, 200);

imshow("median-User", med_img1);

medianBlur(gray, med_img2, 3); // Median Filtering using OpenCV Function

namedWindow("median-OpenCV", WINDOW_AUTOSIZE);

moveWindow("median-OpenCV", 1000, 200);

imshow("median-OpenCV", med_img2);

waitKey();

return 0;

}

8. Преобразование обработки домена / Transform Domain Processing

Пространственная частота (Мекансал фреканс)/ Spatial Frequency (Mekansal frekans)

• 

Hertz (Hz)

– 

единица частоты

– 

Количество раз, чтобы вибрировать в 1 секунду

• 

При обработке изображений (image processing) используется понятие пространственной частоты (spatial frequency)

• 

Определение степени яркости пикселя

sec

sec

sec

• 

Пространственная частота (spatial frequency)

– 

Низкочастотная пространственная область

• 

В области, где яркость пикселей(pixel brightness) практически не изменяется или постепенно изменяется

• 

Фоновая часть изображений.

– 

Высокочастотная пространственная область

• 

Яркость пикселей (pixel brightness) быстро меняется

Краевая часть изображений

Низкая частота


Высокая частота


• 

Что делать, если вы разделяете изображения (image) по частотной области(frequency domain)?


– 

Изображение с удаленными высокочастотными компонентами (high frequency components)

☞

Изображение (image) с размытым краем (edge)

– 

Изображение снято только с высокочастотными компонентами (high frequency components)

☞

Изображение, включающее только край (edge), то есть edge image


• 

Преобразование частоты (Frequency Transform)


Входное изображение


Частота

Трансформировать


Частота

Обратное преобразование


Частота

Коэффициенты


Преобразование Фурье / Fourier Transform

● 

Пространственная область → Ширина частотной области, высота, размер изображения: N

(Spatial Domain → Frequency Domain width, height size of image: N)




● 

Частотная область → Ширина пространственной области, высота, размер изображения:

N

(Frequency Domain → Spatial Domain width, height size of image: N)




(a) Входное изображение


(b) Изображение частоты


(c) Изображение перетасованной частоты


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


Фурье

Трансформировать


Фурье

Обратный

Трансформировать


Дискретное косинусное преобразование / (DCT) Discrete Cosine Transform(DCT)


● 

Пространственная область → Ширина частотной области, высота, размер изображения:

N

(Spatial Domain → Frequency Domain width, height size of image: N)




● 

Частотная область → Ширина пространственной области, высота, размер изображения:

N

(Frequency Domain → Spatial Domain width, height size of image: N)





Ленна 16x16 Блок пикселей / Lenna 16x16 Block Pixels




suratyny oňarmaly, doly goup bilmedim.


Ленна 16x16 Блок коэффициентов DCT / Lenna 16x16 Block DCT Coefficients

● 

Ленна 16x16 Блок коэффициентов DCT

● 

Смещение=128


179-daky Suraty goýup bilmedim







Высокий (High)


180-däki Suraty goýup bilmedim


Дискретное косинусное преобразование (DCT) / Discrete Cosine Transform(DCT)


// Discrete Cosine Transform(DCT) Program

#include <opencv2/opencv.hpp>

using namespace cv;

using namespace std;

Mat DCT_block(Mat g) // Forward DCT

{

Mat dst(g.size(), g.type());

int N = g.rows, M = g.cols;

for (int k = 0; k < N; k++) {

for (int l = 0; l < M; l++) {

float sum = 0;

for (int n = 0; n < N; n++) {

      for (int m = 0; m < M; m++) {

       float theta1 = (float)((2 * n + 1) * k * CV_PI / (2 * N));

       float theta2 = (float)((2 * m + 1) * l * CV_PI / (2 * M));

       sum += g.at<float>(n, m) * cos(theta1) * cos(theta2);

      }

}

float ck = (k) ? sqrt(2.0f / N) : sqrt(1.0f / N);

float cl = (l) ? sqrt(2.0f / M) : sqrt(1.0f / M);

dst.at<float>(k, l) = ck * cl * sum;

}

}

return dst;

}

// next page continued....


Mat IDCT_block(Mat f) // Inverse DCT

{

Mat dst(f.size(), f.type());

int N = f.rows, M = f.cols;

for (int n = 0; n < N; n++) {

for (int m = 0; m < M; m++) {

float sum = 0;

for (int k = 0; k < N; k++) {

      for (int l = 0; l < M; l++) {

       float theta1 = (float)((2 * n + 1) * k * CV_PI / (2 * N));

       float theta2 = (float)((2 * m + 1) * l * CV_PI / (2 * M));

       float ck = (k) ? sqrt(2.0f / N) : sqrt(1.0f / N);

       float cl = (l) ? sqrt(2.0f / M) : sqrt(1.0f / M);

       sum += ck * cl * f.at<float>(k, l) * cos(theta1) * cos(theta2);

      }

}

dst.at<float>(n, m) = sum;

}

}

return dst;

}

void DCT_2D(Mat img, Mat& dst, int N, int M, int dir)

{

dst = Mat(img.size(), CV_32F);

img.convertTo(img, CV_32F);

// next page continued....


for (int bi = 0; bi < img.rows; bi += N) {

for (int bj = 0; bj < img.cols; bj += M) {

Rect rect(Point(bj, bi), Size(M, N));

Mat block = img(rect);

Mat new_block = (dir == 0) ? DCT_block(block) : IDCT_block(block);

new_block.copyTo(dst(rect));

}

}

}

int main()

{

Mat image = imread("../image/lena_std.tif", IMREAD_GRAYSCALE);

CV_Assert(image.data);

Mat m_dct, m_idct;

DCT_2D(image, m_dct, 8, 8, 0);

DCT_2D(m_dct, m_idct, 8, 8, 1);

m_idct.convertTo(m_idct, CV_8U);

namedWindow("Original Image", WINDOW_AUTOSIZE);

namedWindow("Inverse DCT", WINDOW_AUTOSIZE);

moveWindow("Original Image", 200, 200), moveWindow("Inverse DCT", 800, 200);

imshow("Original Image", image), imshow("Inverse DCT", m_idct);

Rect rect(0, 0, 8, 8);

cout << “First 8x8 Block Original Image Elements" << endl;

cout << image(rect) << endl << endl;

cout << “First 8x8 Block DCT Coefficients" << endl;

cout << m_dct(rect) << endl;

waitKey();

}

Ograniczenie wiekowe:
12+
Data wydania na Litres:
26 lipca 2024
Data napisania:
2024
Objętość:
125 str. 126 ilustracji
Właściciel praw:
Автор
Format pobierania:

Podobne książki