Kitabı oku: «Мультимедийное Программирование OpenCV», sayfa 4
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;