OpenCV之C++入门

1、Visual Studio安装及环境配置与搭建

  1. 下载地址:https://my.visualstudio.com/Downloads?q=Visual,下载后按照说明安装即可

    登录账号下载即可,建议下载Visual Studio 2017 专业版,本教程使用该版本完成

    该教程笔记是本人整理的OpenCV学堂视频教程内容,感谢贾志刚老师的视频教程,下面是OpenCV 4.5.4及源码下载链接

    链接:https://pan.baidu.com/s/1HmWrX35P774rr6tlfUXB2A 提取码:urtd

  2. 配置系统环境变量,鼠标右键我的电脑,选择属性,之后按下图操作,复制opencv目录下的bin目录,vs2017选择vc15

  3. 安装完毕后,新建第一个项目如下图

  4. 右键源文件选择新建项新建一个main.cpp

  5. 添加包含目录、库目录及附加依赖项

  6. 在D盘下新建一个images文件夹,放入一张图片,图片名与下面代码段中的图片名字一致

  7. 在main.cpp中输入以下代码

    #include<opencv2/opencv.hpp>
    #include<iostream> using namespace cv;
    using namespace std; int main(int argc, char**argv) {
    Mat src = imread("D:/images/lena.jpg");
    imshow("input", src);
    waitKey(0);
    destroyAllWindows();
    return 0;
    }
  8. 点击 调试开始调试 ,如果出现下图则表示运行成功,配置成功

至此,Visual Studio的准备工作完成!

2、图像基本操作

多行注释快捷键:Ctrl + K + Ctrl + C

2.1、图像读取与显示

#include<opencv2/opencv.hpp>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
//imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
Mat src = imread("D:/images/lena.jpg",IMREAD_GRAYSCALE); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()){
printf("could not load image...\n");
return -1;
}
namedWindow("输入窗口",WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名,imshow()只支持显示8位图像及浮点图像
waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

2.2、图像色彩空间转换

新建一个头文件quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
};

添加该项目包含目录为当前文件夹,操作如下

新建一个源文件quickdemo.cpp

#include<quickopencv.h>

void QuickDemo::colorSpace_Demo(Mat &image) {
Mat gray, hsv;
cvtColor(image, hsv, COLOR_BGR2HSV);
// H 0~180 S 0~255 V 0~255
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("HSV", hsv);
imshow("灰度", gray);
imwrite("D:/images/hsv.png", hsv);
imwrite("D:/images/gray.png", gray);
}

修改源文件test440,进行调试

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
//imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/lena.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 //引入类QuickDemo,调用方法
QuickDemo qd;
qd.colorSpace_Demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.3、图像对象的创建与赋值

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
};

quickdemo.cpp

#include<quickopencv.h>

void QuickDemo::colorSpace_Demo(Mat &image) {
Mat gray, hsv;
cvtColor(image, hsv, COLOR_BGR2HSV);
// H 0~180 S 0~255 V 0~255
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("HSV", hsv);
imshow("灰度", gray);
imwrite("D:/images/hsv.png", hsv);
imwrite("D:/images/gray.png", gray);
} void QuickDemo::mat_creation_demo() {
//克隆和复制才会创建新的对象,赋值不会创建新的对象
//Mat m1, m2;
//m1 = image.clone();
//image.copyTo(m2); // 创建空白图像
Mat m3 = Mat::ones(Size(512, 512), CV_8UC3);
m3 = Scalar(127, 127, 127); // 为像素赋予指定的值 B,G,R顺序 std::cout << "width: " << m3.cols << " height: " << m3.rows << " channels: " << m3.channels() << std::endl;
//std::cout << m3 << std::endl; Mat m4 = m3; //赋值后m4改变,会引起m3改变,clone或copyTo则会创建新对象,不影响原对象
m4 = Scalar(0, 255, 255); imshow("创建图像", m3); Mat kernel = (Mat_<char>(3, 3) << 0,-1,0, // 3*3卷积核
-1,5,-1,
0,-1,0);
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/lena.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.mat_creation_demo(); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.4、图像像素的读写操作

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
};

quickdemo.cpp

#include<quickopencv.h>

void QuickDemo::pixel_visit_demo(Mat &image) {
int w = image.cols;
int h = image.rows;
int dims = image.channels();
//for (int row = 0; row < h; row++) {
// for (int col = 0; col < w; col++) {
// if (dims == 1) { //灰度图像
// int pv = image.at<uchar>(row, col); //row,col → y,x
// image.at<uchar>(row, col) = 255 - pv; //对像素值反转,image.at<uchar>为获取某点格式为uchar的像素值
// }
// if (dims == 3) { //彩色图像
// Vec3b bgr = image.at<Vec3b>(row, col); //Vec3b为bgr图像像素点存储格式,对像素值进行反转
// image.at<Vec3b>(row, col)[0] = 255 - bgr[0];
// image.at<Vec3b>(row, col)[1] = 255 - bgr[1];
// image.at<Vec3b>(row, col)[2] = 255 - bgr[2];
// }
// }
//} for (int row = 0; row < h; row++) {
uchar* current_row = image.ptr<uchar>(row); //获取当前行最初位置的指针
for (int col = 0; col < w; col++) {
if (dims == 1) { //灰度图像
int pv = *current_row;
*current_row++ = 255 - pv; //每次运算完,指针右移一位
}
if (dims == 3) { //彩色图像
*current_row++ = 255 - *current_row; //由于bgr图像矩阵是连续的,所以指针直接指向下一位
*current_row++ = 255 - *current_row;
*current_row++ = 255 - *current_row;
}
}
} imshow("像素读写演示", image);
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/lena.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.pixel_visit_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.5、图像像素的算数操作

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
};

quickdemo.cpp

#include<quickopencv.h>

void QuickDemo::operators_demo(Mat &image) {
Mat dst;
Mat m = Mat::zeros(image.size(), image.type());
m = Scalar(2, 2, 2); //Scalar标量 //dst = image + Scalar(50, 50, 50);
//dst = image - Scalar(50, 50, 50);
//dst = image / Scalar(2, 2, 2); //加法手写实现,主要使用saturate_cast函数,运算可使用对应函数快速实现
/*
int w = image.cols;
int h = image.rows;
int dims = image.channels();
for (int row = 0; row < h; row++) {
for (int col = 0; col < w; col++) {
Vec3b p1 = image.at<Vec3b>(row, col);
Vec3b p2 = m.at<Vec3b>(row, col);
//saturate_cast函数,将大于255的数转换为255,小于0的数转换为0
dst.at<Vec3b>(row, col)[0] = saturate_cast<uchar>(p1[0] + p2[0]);
dst.at<Vec3b>(row, col)[1] = saturate_cast<uchar>(p1[1] + p2[1]);
dst.at<Vec3b>(row, col)[2] = saturate_cast<uchar>(p1[2] + p2[2]);
}
}
imshow("加法操作", dst);
*/
//add(image, m, dst); //add(操作的图,对图片操作的参数,输出的结果)
//subtract(image, m, dst); //减法
//divide(image, m, dst); //除法
multiply(image, m, dst); //乘法 //imshow("加法操作", dst);
//imshow("减法操作", dst);
//imshow("除法操作", dst);
imshow("乘法操作", dst); }

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/dark_face.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.operators_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.6、使用滚动条调整图像亮度(TrackBar)

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
};

quickdemo.cpp

Mat src, dst, m;
int lightness = 50; //回调函数两个形参,第一个int为createTrackbar中当前滑块所在位置,初始为lightness,第二个为userdata,为createTrackbar最后一个参数,默认为0
static void on_track(int, void*) {
m = Scalar(lightness, lightness, lightness);
add(src, m, dst);
imshow("亮度调整", dst);
}
void QuickDemo::tracking_bar_demo(Mat &image) {
namedWindow("亮度调整", WINDOW_AUTOSIZE);
dst = Mat::zeros(image.size(), image.type());
m = Mat::zeros(image.size(), image.type());
src = image;
int max_value = 100; //createTrackbar(滑动条名,滑动条所在的窗口,滑动块初始位置,滑动条最大值,回调函数(滑块滑动时的处理))
createTrackbar("Value Bar:", "亮度调整", &lightness, max_value, on_track);
on_track(50, 0);
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/dark_face.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.tracking_bar_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.7、滚动条操作-通过参数传递度

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
};

quickdemo.cpp 对上一节函数优化

//回调函数两个形参,第一个int为createTrackbar中的当前滑块所在位置,第二个为userdata,为createTrackbar最后一个参数,默认为0
static void on_lightness(int b, void* userdata) {
Mat image = *((Mat*)userdata); //指针转换成Mat类型数据
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
addWeighted(image, 1.0, m, 0, b, dst); //dst = image*1.0 + m*0 + b
imshow("亮度与对比度调整", dst);
}
static void on_contrast(int b, void* userdata) {
Mat image = *((Mat*)userdata); //指针转换成Mat类型数据
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
double contrast = b / 100.0;
//addWeighted()函数可以实现两张图片混合
addWeighted(image, contrast, m, 0, 0, dst); //dst = image*contrast + m*0 + 0
imshow("亮度与对比度调整", dst);
}
void QuickDemo::tracking_bar_demo(Mat &image) {
namedWindow("亮度与对比度调整", WINDOW_AUTOSIZE);
int lightness = 50;
int light_max_value = 100;
int contrast_value = 100;
int contrast_max = 200;
//createTrackbar(滑动条名,滑动条所在的窗口,滑动块初始位置,滑动条最大值,回调函数(滑块滑动时的处理),userdata(传递给回调函数的数据))
createTrackbar("Value Bar:", "亮度与对比度调整", &lightness, light_max_value, on_lightness, (void*)(&image));
createTrackbar("Contrast Bar:", "亮度与对比度调整", &contrast_value, contrast_max, on_contrast, (void*)(&image));
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/dark_face.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.tracking_bar_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.8、滚动条操作-键盘响应操作

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
};

quickdemo.cpp

void QuickDemo::key_demo(Mat &image) {
Mat dst = Mat::zeros(image.size(), image.type());
while (true) {
int c = waitKey(1); //waitKey(图像刷新时间间隔)不断刷新图像,刷新间隔时间为1ms,视频处理时尽量设置1ms
if (c == 27) { // 退出
break;
}
if (c == 49) { // Key #1
cvtColor(image, dst, COLOR_BGR2GRAY);
imshow("键盘响应01", dst);
}
if (c == 50) { // Key #2
cvtColor(image, dst, COLOR_BGR2HSV);
imshow("键盘响应02", dst);
}
if (c == 51) { // Key #3
dst = Scalar(50, 50, 50);
add(image, dst, dst);
imshow("键盘响应03", dst);
}
//imshow("键盘响应", dst);
}
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/lena.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.key_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.9、OpenCV自带颜色表操作

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
};

quickdemo.cpp

void QuickDemo::color_style_demo(Mat &image) {
int colormap[] = {
COLORMAP_AUTUMN,
COLORMAP_BONE,
COLORMAP_JET,
COLORMAP_WINTER,
COLORMAP_RAINBOW,
COLORMAP_OCEAN,
COLORMAP_SUMMER,
COLORMAP_SPRING,
COLORMAP_COOL,
COLORMAP_PINK,
COLORMAP_HOT,
COLORMAP_PARULA,
COLORMAP_MAGMA,
COLORMAP_INFERNO,
COLORMAP_PLASMA,
COLORMAP_VIRIDIS,
COLORMAP_CIVIDIS,
COLORMAP_TWILIGHT,
COLORMAP_TWILIGHT_SHIFTED
}; Mat dst;
int index = 0;
while (true) {
int c = waitKey(2000);
if (c == 27) {
break;
}
applyColorMap(image, dst, colormap[index%19]);
index++;
imshow("颜色风格", dst);
}
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/lena.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.color_style_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.10、图像像素的逻辑操作

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
};

quickdemo.cpp

void QuickDemo::bitwise_demo(Mat &image) {
Mat m1 = Mat::zeros(Size(256, 256), CV_8UC3);
Mat m2 = Mat::zeros(Size(256, 256), CV_8UC3); //rectangle()函数第四个参数小于0表示填充,大于0表示绘制
//rectangle(m1, Rect(100, 100, 80, 80), Scalar(255, 255, 0), 2, LINE_8, 0);
//rectangle(m2, Rect(150, 150, 80, 80), Scalar(0, 255, 255), 2, LINE_8, 0);
rectangle(m1, Rect(100, 100, 80, 80), Scalar(255, 255, 0), -1, LINE_8, 0);
rectangle(m2, Rect(150, 150, 80, 80), Scalar(0, 255, 255), -1, LINE_8, 0);
imshow("m1", m1);
imshow("m2", m2);
Mat dst;
//bitwise_and(m1, m2, dst);
//bitwise_or(m1, m2, dst);
//dst = ~image; //也可以实现图像取反操作
//bitwise_not(image, dst); //当前图像取反操作
bitwise_xor(m1, m2, dst); //异或((非m1 与 m2) 或 (m1 与 非m2)),相当于 m1或m2,相交的部分(非(m1 与 m2))
imshow("像素位操作", dst);
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/lena.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.bitwise_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.11、通道分离与合并

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
};

quickdemo.cpp

void QuickDemo::channels_demo(Mat &image) {
std::vector<Mat> mv; //Mat数组
split(image, mv);
imshow("蓝色", mv[0]);
imshow("绿色", mv[1]);
imshow("红色", mv[2]); Mat dst;
//mv[1] = 0;
//mv[2] = 0;
//merge(mv, dst);
//imshow("蓝色", dst);
//mv[0] = 0;
//mv[2] = 0;
//merge(mv, dst);
//imshow("绿色", dst);
mv[0] = 0;
mv[1] = 0;
merge(mv, dst);
imshow("红色", dst); //from_to[]复制列表
int from_to[] = { 0,2,1,1,2,0 }; //通道0复制到通道2,通道1复制到通道1,通道2复制到通道0
//mixChannels(输入矩阵,输入矩阵数量,输出矩阵,输出矩阵数量,复制列表,复制列表中复制几次)
mixChannels(&image, 1, &dst, 1, from_to, 3);
imshow("通道混合", dst);
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/flower.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.channels_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.12、图像色彩空间转换

HSV颜色空间表

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
};

quickdemo.cpp

void QuickDemo::inrange_demo(Mat &image) {
Mat hsv;
cvtColor(image, hsv, COLOR_BGR2HSV);
Mat mask;
inRange(hsv, Scalar(35, 43, 46), Scalar(77, 255, 255), mask);
imshow("mask01", mask); Mat redback = Mat::zeros(image.size(), image.type());
redback = Scalar(40, 40, 200);
bitwise_not(mask, mask); //像素逻辑运算,mask取反
imshow("mask02", mask);
//image.copyTo(拷贝到的图像,mask为1的部分拷贝为0的部分不拷贝)
image.copyTo(redback, mask); //将image拷贝到其他图像中
imshow("roi区域提取", redback);
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/greenback.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.inrange_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.13、图像像素值统计

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_statistic_demo(Mat &image);
};

quickdemo.cpp

void QuickDemo::pixel_statistic_demo(Mat &image) {
double minv, maxv;
Point minLoc, maxLoc;
Mat mean, stddev;
std::vector<Mat> mv;
split(image, mv);
for (int i = 0; i < mv.size(); i++) {
//第一个参数需要是单通道的图像,可以先把多通道分离;最后一个参数为mask
minMaxLoc(mv[i], &minv, &maxv, &minLoc, &maxLoc, Mat());
std::cout << "No.channels: " << i << " min value: " << minv << " max value: " << maxv << std::endl;
//第一个参数是单通道图像则计算一组均值、方差,如果是多通道图像,则同时计算多组均值、方差
meanStdDev(mv[i], mean, stddev);
std::cout << "means: " << mean << std::endl;
std::cout << "stddev: " << stddev << std::endl;
}
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/greenback.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.pixel_statistic_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.14、图像几何形状绘制,随机数与随机颜色

基本绘图

 1 Point:
2 Point pt;
3 pt.x = 10;
4 pt.y = 8;
5 或者
6 Point pt = Point(10, 8);
7
8 Scalar:
9 Scalar( B, G, R ) //定义的RGB颜色值为:Blue,Green, Red
10
11 line 绘直线:
12 line( img, //输出图像
13 start, //起始点
14 end, //结束点
15 Scalar( 0, 0, 0 ), //颜色
16 thickness=2, //线条粗细
17 lineType=8 ); //线条类型
18
19 ellipse 绘椭圆:
20 ellipse( img, //输出图像
21 Point( w/2.0, w/2.0 ), //中心为点 (w/2.0, w/2.0)
22 Size( w/4.0, w/16.0 ), //大小位于矩形 (w/4.0, w/16.0) 内
23 angle, //旋转角度为 angle
24 0,
25 360, //扩展的弧度从 0 度到 360 度
26 Scalar( 255, 0, 0 ), //颜色
27 thickness, //线条粗细
28 lineType ); //线条类型
29
30 circle 绘圆:
31 circle( img, //输出图像
32 center, //圆心由点 center 定义
33 w/32.0, /圆的半径为: w/32.0
34 Scalar( 0, 0, 255 ), //颜色
35 thickness, //线条粗细
36 lineType ); //线条类型
37
38 rectangle 绘矩形:
39 rectangle( rook_image,
40 Point( 0, 7*w/8.0 ),
41 Point( w, w), //矩形两个对角顶点为 Point( 0, 7*w/8.0 ) 和 Point( w, w)
42 Scalar( 0, 255, 255 ),
43 thickness = -1,
44 lineType = 8 );
45
46 fillPoly 绘填充的多边形:
47 fillPoly( img,
48 ppt, //多边形的顶点集为 ppt
49 npt, //要绘制的多边形顶点数目为 npt
50 1, //要绘制的多边形数量仅为 1
51 Scalar( 255, 255, 255 ),
52 lineType );

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_statistic_demo(Mat &image);
void form_paint_random();
};

quickdemo.cpp

void QuickDemo::form_paint_random() {
Mat image_line = Mat::zeros(512, 512, CV_8UC3); //新建两个512*512的三通道矩阵
Mat image_rect = Mat::zeros(512, 512, CV_8UC3);
Rect rect; //新建一个矩形对象
RNG rng(0xFFFFFF); //生成随机数的类RNG,随机数产生器,用数值0xFFFFFF来实例化一个RNG对象
image_line.setTo(Scalar(0, 0, 0)); //将图像使用另一种颜色覆盖
image_rect.setTo(Scalar(0, 0, 0)); //将图像使用另一种颜色覆盖 for (int i = 0; i < 100000; i++) {
int x1 = rng.uniform(0, 512); //获取[0,512)的均匀分布的随机数
int y1 = rng.uniform(0, 512);
int x2 = rng.uniform(0, 512);
int y2 = rng.uniform(0, 512); int b = rng.uniform(0, 256);
int g = rng.uniform(0, 256);
int r = rng.uniform(0, 256);
//void line(绘制线段的图像,起点坐标,终点坐标,线段的颜色通过Scalar()定义,线段的宽度(线宽为负数时表示填充),线段的类型,坐标点小数点位数)
line(image_line, Point(x1, y1), Point(x2, y2), Scalar(b, g, r), 1, LINE_AA, 0); //线段的类型。可以取值LINE_8,LINE_4和LINE_AA,分别代表8邻接连接线,4邻接连接线和反锯齿连接线。默认值为8邻接。为了获得更好地效果可以选用LINE_AA(采用了高斯滤波)。
imshow("image_line", image_line);
rect.x = x1; //定义矩形的左上顶点坐标及宽高
rect.y = y1;
rect.width = x2 - x1;
rect.height = y2 - y1;
rectangle(image_rect, rect, Scalar(b, g, r), 1, LINE_AA, 0);
imshow("image_rect", image_rect);
char c = waitKey(20);
if (c == 27)
break;
}
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/greenback.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
//imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.form_paint_random(); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.15、多边形填充与绘制

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_statistic_demo(Mat &image);
void form_paint_random();
void polyline_drawing_demo();
};

quickdemo.cpp

void QuickDemo::polyline_drawing_demo() {
Mat canvas01 = Mat::zeros(Size(512, 512), CV_8UC3);
Mat canvas02 = Mat::zeros(Size(512, 512), CV_8UC3);
Point p1(100, 100);
Point p2(350, 100);
Point p3(450, 280);
Point p4(320, 450);
Point p5(80, 400);
std::vector<Point> pts;
pts.push_back(p1);
pts.push_back(p2);
pts.push_back(p3);
pts.push_back(p4);
pts.push_back(p5);
fillPoly(canvas01, pts, Scalar(255, 255, 0), 8, 0);
//polylines(绘制所在图像,要绘制的顶点集合,图形是否闭合,线的颜色,线宽,线的类型)
//polylines(canvas, pts, true, Scalar(0, 0, 255), 3, LINE_8, 0); //不能设置线宽为负数进行填充
polylines(canvas01, pts, true, Scalar(0, 0, 255), 3, LINE_AA, 0); //使用LINE_AA抗锯齿
std::vector<std::vector<Point>> contours;
contours.push_back(pts);
//drawContours(绘制所在的图像,绘制的点集的集合,绘制第几个点集-1表示全部绘制,线段颜色,线宽-1表示填充)
drawContours(canvas02, contours, -1, Scalar(255, 0, 0), -1);
imshow("多边形绘制01", canvas01);
imshow("多边形绘制02", canvas02);
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/greenback.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
//imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.polyline_drawing_demo(); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.16、鼠标操作与响应

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_statistic_demo(Mat &image);
void form_paint_random();
void polyline_drawing_demo();
void mouse_drawing_demo(Mat &image);
};

quickdemo.cpp

Point sp(-1, -1);  //起点
Point ep(-1, -1); //终点
//新建一个temp矩阵保存原图像,没有绘制的
Mat temp;
static void on_draw(int event, int x, int y, int flags, void *userdata) {
Mat image = *((Mat*)userdata);
if (event == EVENT_LBUTTONDOWN) {
sp.x = x;
sp.y = y;
std::cout << "start point: " << sp << std::endl;
}
else if (event == EVENT_LBUTTONUP) {
ep.x = x;
ep.y = y;
int dx = ep.x - sp.x;
int dy = ep.y - sp.y;
if (dx > 0 && dy > 0) {
Rect box(sp.x, sp.y, dx, dy);
temp.copyTo(image); //去除绘制目标区域的边框
imshow("ROI区域", image(box)); //将绘制区域中的图像单独显示出来
rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);
imshow("鼠标绘制", image);
//ready for next drawing
sp.x = -1;
sp.y = -1;
}
}
else if (event == EVENT_MOUSEMOVE) {
if (sp.x > 0 && sp.y > 0) {
ep.x = x;
ep.y = y;
int dx = ep.x - sp.x;
int dy = ep.y - sp.y;
if (dx > 0 && dy > 0) {
Rect box(sp.x, sp.y, dx, dy);
temp.copyTo(image); //每次都重新加载没有绘制的原图,实现擦除过程中绘制的图形
rectangle(image, box, Scalar(0, 0, 255), 2, 8, 0);
imshow("鼠标绘制", image);
}
}
}
} void QuickDemo::mouse_drawing_demo(Mat &image) {
namedWindow("鼠标绘制", WINDOW_AUTOSIZE);
setMouseCallback("鼠标绘制", on_draw, (void*)(&image));
imshow("鼠标绘制", image);
temp = image.clone(); //将加载的原图克隆到临时矩阵temp中
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/greenback.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
//imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.mouse_drawing_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.17、图像像素类型转换与归一化

图像为什么要进行归一化:

归一化就是要把需要处理的数据经过处理后(通过某种算法)限制在你需要的一定范围内。首先归一化是为了后面数据处理的方便,其次是保证程序运行时收敛加快。归一化的具体作用是归纳统一样本的统计分布性。归一化在0-1之间是统计的概率分布,归一化在某个区间上是统计的坐标分布。归一化有同一、统一和合一的意思。

归一化的目的简而言之,是使得没有可比性的数据变得具有可比性,同时又保持相比较的两个数据之间的相对关系,如大小关系;或是为了作图,原来很难在一张图上作出来,归一化后就可以很方便的给出图上的相对位置等。

四种归一化方式:

其中的NORM_L2计算方式实例如下公式,其他归一化方式根据图片中的内容即可理解

\[2.0\div \sqrt {{{2}^{2}+{8}^{2}+10}^{2}}\approx 0.15
\]

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_statistic_demo(Mat &image);
void form_paint_random();
void polyline_drawing_demo();
void mouse_drawing_demo(Mat &image);
void norm_demo(Mat &image);
};

quickdemo.cpp

//image.type()返回的数值与类型对应关系,第一行为通道数,第一列为数据类型
+--------+----+----+----+----+------+------+------+------+
| | C1 | C2 | C3 | C4 | C(5) | C(6) | C(7) | C(8) |
+--------+----+----+----+----+------+------+------+------+
| CV_8U | 0 | 8 | 16 | 24 | 32 | 40 | 48 | 56 |
| CV_8S | 1 | 9 | 17 | 25 | 33 | 41 | 49 | 57 |
| CV_16U | 2 | 10 | 18 | 26 | 34 | 42 | 50 | 58 |
| CV_16S | 3 | 11 | 19 | 27 | 35 | 43 | 51 | 59 |
| CV_32S | 4 | 12 | 20 | 28 | 36 | 44 | 52 | 60 |
| CV_32F | 5 | 13 | 21 | 29 | 37 | 45 | 53 | 61 |
| CV_64F | 6 | 14 | 22 | 30 | 38 | 46 | 54 | 62 |
+--------+----+----+----+----+------+------+------+------+ void QuickDemo::norm_demo(Mat &image) {
Mat dst;
std::cout << image.type() << std::endl;
image.convertTo(image, CV_32F); //将8UC3 Integer数据转换成32F float数据,以便用于后续归一化操作
std::cout << image.type() << std::endl; //值归一化与范围归一化:值归一化L1,L2,MINMAX;范围归一化可以自己设置归一化范围如[0,255]
//normalize(输入数组,输出数组,1用来规范值2规范范围下限,0值归一化其他范围归一化上限,归一化选择的数学公式类型)
normalize(image, dst, 1.0, 0, NORM_MINMAX); //转换为浮点数类型后必须进行归一化操作
std::cout << dst.type() << std::endl;
imshow("图像数据归一化前", image);
imshow("图像数据归一化后", dst);
//CV_8UC3, CV_32FC3
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/greenback.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.norm_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.18、图像放缩与插值

OpenCV图像放缩的五种插值算法:最近邻、双线性、双三次、基于像素区域关系、兰索斯插值。

1、最近邻:选取离目标点最近的点作为新的插入点;

2、双线性:由相邻的四像素(2 * 2)计算得出;

  • 原理公式及矩阵

  • 计算过程示意图

3、双三次:由相邻的4 * 4像素计算得出,公式类似于双线性插值;

4、基于像素区域关系:共分三种情况,图像放大时类似于双线性插值,图像缩小(x轴、y轴同时缩小)又分两种情况,此情况下可以避免波纹出现;

5、兰索斯插值:由相邻的8 * 8像素计算得出,公式类似于双线性

总结:

  • 速度比较:INTER_NEAREST(最近邻插值)>INTER_LINEAR(双线性插值)>INTER_CUBIC(三次样条插值)>INTER_AREA(区域插值)
  • OpenCV推荐:如果要缩小图像,通常推荐使用 INTER_AREA插值效果最好;而要放大图像,通常使用 INTER_CUBIC(速度较慢,但效果最好),或者使用 INTER_LINEAR(速度较快,效果还可以)。至于最近邻插值 INTER_NEAREST,一般不推荐使用

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_statistic_demo(Mat &image);
void form_paint_random();
void polyline_drawing_demo();
void mouse_drawing_demo(Mat &image);
void norm_demo(Mat &image);
void resize_demo(Mat &image);
};

quickdemo.cpp

void QuickDemo::resize_demo(Mat &image) {
Mat zoomin, zoomout;
int h = image.rows;
int w = image.cols; //resize(输入图像,输出图像,大小变换方法Size(),x方向缩放系数,y方向缩放系数,插值算法)
//如果size有值,使用size做放缩插值,否则根据fx与fy卷积
resize(image, zoomin, Size(w / 2, h / 2), 0, 0, INTER_LINEAR);
imshow("zoomin", zoomin);
resize(image, zoomout, Size(w * 1.5, h * 1.5), 0, 0, INTER_LINEAR);
imshow("zoomout", zoomout);
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/greenback.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.resize_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.19、图像翻转

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_statistic_demo(Mat &image);
void form_paint_random();
void polyline_drawing_demo();
void mouse_drawing_demo(Mat &image);
void norm_demo(Mat &image);
void resize_demo(Mat &image);
void flip_demo(Mat &image);
};

quickdemo.cpp

void QuickDemo::flip_demo(Mat &image) {
Mat dst;
flip(image, dst, 0); //上下翻转
imshow("图像上下翻转", dst);
flip(image, dst, 1); //左右翻转
imshow("图像左右翻转", dst);
flip(image, dst, -1); //180°旋转
imshow("图像180°翻转", dst);
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/greenback.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.flip_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.20、图像旋转

公式:

\[i'\, =\, icosθ\, -\, j\sin {\theta }
\]
\[i'\, =\, i\sin {\theta }\, +\, jcosθ
\]

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_statistic_demo(Mat &image);
void form_paint_random();
void polyline_drawing_demo();
void mouse_drawing_demo(Mat &image);
void norm_demo(Mat &image);
void resize_demo(Mat &image);
void flip_demo(Mat &image);
void rotate_demo(Mat &image);
};

quickdemo.cpp

void QuickDemo::rotate_demo(Mat &image) {
Mat dst, M;
int w = image.cols;
int h = image.rows;
M = getRotationMatrix2D(Point2f(w / 2, h / 2), 45, 1.0);
double cos = abs(M.at<double>(0, 0));
double sin = abs(M.at<double>(0, 1));
int nw = cos * w + sin * h;
int nh = sin * w + cos * h;
M.at<double>(0, 2) += (nw / 2 - w / 2);
M.at<double>(1, 2) += (nh / 2 - h / 2);
warpAffine(image, dst, M, Size(nw, nh), INTER_LINEAR, 0, Scalar(255, 255, 0));
imshow("旋转展示", dst);
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/lena.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.rotate_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.21、视频文件摄像头使用

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_statistic_demo(Mat &image);
void form_paint_random();
void polyline_drawing_demo();
void mouse_drawing_demo(Mat &image);
void norm_demo(Mat &image);
void resize_demo(Mat &image);
void flip_demo(Mat &image);
void rotate_demo(Mat &image);
void video_demo(Mat &image);
};

quickdemo.cpp

void QuickDemo::video_demo(Mat &image) {
//VideoCapture capture(0); //获取当前设备摄像头视频
VideoCapture capture("D:/images/video/example.mp4"); //获取该地址下的视频
Mat frame; while (true) {
capture.read(frame); int h = frame.rows; //获取视频每一帧的宽高
int w = frame.cols; //flip(frame, frame, 1); //摄像头需要翻转,视频不需要翻转
if (frame.empty()) {
break;
} resize(frame, frame, Size(w / 4, h / 4), 0, 0, INTER_LINEAR); //缩放视频 imshow("frame", frame); //显示缩放后的视频 colorSpace_Demo(frame); //调用色彩空间转换函数,将视频转换为灰度图像及HSV图像并显示 // TODO: do something....
int c = waitKey(10);
if (c == 27) { //退出
break;
}
} //release
capture.release();
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/lena.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
//imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.video_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.22、视频处理与保存

分辨率清晰度对照:

视频显示格式 分辨率尺寸名 汉语简称
480p、576p SD(Standard Definition) 标清
720p HD(High Definition) 高清
1080p FHD(Full High Definition) 全高清
2k QHD(Quad High Definition) 四倍HD
4k UHD(Ultra High Definition) 超高清 或 4k UHD
8k FUHD(Full Ultra High Definition) 8k超高清 或 8k UHD

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_statistic_demo(Mat &image);
void form_paint_random();
void polyline_drawing_demo();
void mouse_drawing_demo(Mat &image);
void norm_demo(Mat &image);
void resize_demo(Mat &image);
void flip_demo(Mat &image);
void rotate_demo(Mat &image);
void video_demo(Mat &image);
};

quickdemo.cpp

void QuickDemo::video_demo(Mat &image) {
//VideoCapture capture(0); //获取当前设备摄像头视频
VideoCapture capture("D:/images/video/example.mp4"); //获取该地址下的视频 int frame_width = capture.get(CAP_PROP_FRAME_WIDTH); //获取视频帧的宽高
int frame_height = capture.get(CAP_PROP_FRAME_HEIGHT);
int count = capture.get(CAP_PROP_FRAME_COUNT); //获取视频的全部帧数
double fps = capture.get(CAP_PROP_FPS); //获取视频每秒帧数fps
std::cout << "frame width: " << frame_width << std::endl;
std::cout << "frame height: " << frame_height << std::endl;
std::cout << "FPS: " << fps << std::endl;
std::cout << "Number of Frames: " << count << std::endl;
int fourcc = VideoWriter::fourcc('a','v','c','1'); //H264编码格式的fourcc code //VideoWriter writer(保存地址,fourcc编码格式code,帧率,保存视频的画面宽高,是否是彩色);
VideoWriter writer("D:/test.mp4", fourcc, fps, Size(frame_width, frame_height), true); Mat frame;
Mat frame1; while (true) {
capture.read(frame); int h = frame.rows; //获取视频每一帧的宽高
int w = frame.cols; //flip(frame, frame, 1); //摄像头需要翻转,视频不需要翻转
if (frame.empty()) {
break;
} resize(frame, frame1, Size(w / 4, h / 4), 0, 0, INTER_LINEAR); //缩放视频 imshow("frame", frame1); //显示缩放后的视频 //colorSpace_Demo(frame); //调用色彩空间转换函数,将视频转换为灰度图像及HSV图像并显示
writer.write(frame); //将每一帧保存到新的文件中 // TODO: do something....
int c = waitKey(10);
if (c == 27) { //退出
break;
}
} //release
capture.release();
writer.release();
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/lena.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
//imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.video_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

运行过程中缺少H264编码器:

1、出现错误

2、到给出的网站中下载对应的dll文件

3、将该文件下载解压后放到opencv的bin目录下

4、再次运行正常

注意:H264对应的fourcc codeavc1! 具体原因可以自行百度,与OpenCV遵守的开源协议有关

2.23、图像直方图

图像直方图解释:

图像直方图使图像像素值的统计学特征,计算代价较小,具有图像平移、旋转、缩放不变性等众多优点,广泛地应用域图像处理的各个领域,特别是灰度图像的阈值分割、基于颜色的图像检索以及图像分类、反向投影跟踪。常见的分为灰度直方图颜色直方图

Bins是指直方图的大小范围,对于像素值取在0~255之间的,最少有256个bin,此外还可以有16、32、48、128等,256除以bin的大小应该是整数倍。

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_statistic_demo(Mat &image);
void form_paint_random();
void polyline_drawing_demo();
void mouse_drawing_demo(Mat &image);
void norm_demo(Mat &image);
void resize_demo(Mat &image);
void flip_demo(Mat &image);
void rotate_demo(Mat &image);
void video_demo(Mat &image);
void histogram_demo(Mat &image);
};

quickdemo.cpp

void QuickDemo::histogram_demo(Mat &image) {
//三通道分离
std::vector<Mat> bgr_plane; //定义Mat类型的集合,用来保存三通道数据
split(image, bgr_plane); //将图像三通道分离,保存到定义的集合中
//定义参数变量
const int channels[1] = { 0 };
const int bins[1] = { 256 };
float hranges[2] = { 0,255 };
const float* ranges[1] = { hranges };
Mat b_hist;
Mat g_hist;
Mat r_hist;
//计算Blue,Green,Red通道的直方图
calcHist(&bgr_plane[0], 1, 0, Mat(), b_hist, 1, bins, ranges);
calcHist(&bgr_plane[1], 1, 0, Mat(), g_hist, 1, bins, ranges);
calcHist(&bgr_plane[2], 1, 0, Mat(), r_hist, 1, bins, ranges);
//显示直方图
int hist_w = 512;
int hist_h = 400;
int bin_w = cvRound((double)hist_w / bins[0]);
Mat histImage = Mat::zeros(hist_h, hist_w,CV_8UC3);
//归一化直方图数据
normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat());
//绘制直方图曲线
for (int i = 1; i < bins[0]; i++) {
line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(b_hist.at<float>(i - 1))),
Point(bin_w*(i), hist_h - cvRound(b_hist.at<float>(i))), Scalar(255, 0, 0), 2, LINE_AA, 0);
line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),
Point(bin_w*(i), hist_h - cvRound(b_hist.at<float>(i))), Scalar(0, 255, 0), 2, LINE_AA, 0);
line(histImage, Point(bin_w*(i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),
Point(bin_w*(i), hist_h - cvRound(b_hist.at<float>(i))), Scalar(0, 0, 255), 2, LINE_AA, 0);
}
//显示直方图
namedWindow("Histogram Demo", WINDOW_AUTOSIZE);
imshow("Histogram Demo", histImage);
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/flower.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.histogram_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.24、二维直方图

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_statistic_demo(Mat &image);
void form_paint_random();
void polyline_drawing_demo();
void mouse_drawing_demo(Mat &image);
void norm_demo(Mat &image);
void resize_demo(Mat &image);
void flip_demo(Mat &image);
void rotate_demo(Mat &image);
void video_demo(Mat &image);
void histogram_demo(Mat &image);
void histogram_2d_demo(Mat &image);
};

quickdemo.cpp

void QuickDemo::histogram_2d_demo(Mat &image) {
//2D直方图
Mat hsv, hs_hist;
cvtColor(image, hsv, COLOR_BGR2HSV);
int hbins = 30, sbins = 32;
int hist_bins[] = { hbins,sbins };
float h_range[] = { 0,180 };
float s_range[] = { 0,256 };
const float* hs_ranges[] = { h_range,s_range };
int hs_channels[] = { 0,1 };
calcHist(&hsv, 1, hs_channels, Mat(), hs_hist, 2, hist_bins, hs_ranges, true, false);
double maxVal = 0;
minMaxLoc(hs_hist, 0, &maxVal, 0, 0);
int scale = 10;
Mat hist2d_image = Mat::zeros(sbins*scale, hbins*scale, CV_8UC3);
Mat hist2d_image_back = Mat::zeros(sbins*scale, hbins*scale, CV_8UC3);
for (int h = 0; h < hbins; h++) {
for (int s = 0; s < sbins; s++) {
float binVal = hs_hist.at<float>(h, s);
int intensity = cvRound(binVal * 255 / maxVal);
rectangle(hist2d_image, Point(h*scale, s*scale),
Point((h + 1)*scale - 1, (s + 1)*scale - 1),
Scalar::all(intensity),
-1);
}
} applyColorMap(hist2d_image, hist2d_image_back, COLORMAP_JET); imshow("H-S Histogram", hist2d_image);
imshow("H-S Histogram_back", hist2d_image_back);
imwrite("D:/hist_2d.png", hist2d_image);
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/flower.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.histogram_2d_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.25、直方图均衡化

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_statistic_demo(Mat &image);
void form_paint_random();
void polyline_drawing_demo();
void mouse_drawing_demo(Mat &image);
void norm_demo(Mat &image);
void resize_demo(Mat &image);
void flip_demo(Mat &image);
void rotate_demo(Mat &image);
void video_demo(Mat &image);
void histogram_demo(Mat &image);
void histogram_2d_demo(Mat &image);
void histogram_eq_demo(Mat &image);
};

quickdemo.cpp

void QuickDemo::histogram_eq_demo(Mat &image) {
Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("灰度图像", gray);
Mat dst;
equalizeHist(gray, dst);
imshow("直方图均衡化演示", dst);
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/flower.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.histogram_eq_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.26、图像卷积操作

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_statistic_demo(Mat &image);
void form_paint_random();
void polyline_drawing_demo();
void mouse_drawing_demo(Mat &image);
void norm_demo(Mat &image);
void resize_demo(Mat &image);
void flip_demo(Mat &image);
void rotate_demo(Mat &image);
void video_demo(Mat &image);
void histogram_demo(Mat &image);
void histogram_2d_demo(Mat &image);
void histogram_eq_demo(Mat &image);
void blur_demo(Mat &image);
};

quickdemo.cpp

void QuickDemo::blur_demo(Mat &image) {
Mat dst01, dst02, dst03, dst04, dst05;
blur(image, dst01, Size(3, 3), Point(-1, -1));
blur(image, dst02, Size(13, 13), Point(-1, -1));
blur(image, dst03, Size(23, 23), Point(-1, -1));
blur(image, dst04, Size(13, 1), Point(-1, -1));
blur(image, dst05, Size(1, 13), Point(-1, -1)); imshow("图像模糊01", dst01);
imshow("图像模糊02", dst02);
imshow("图像模糊03", dst03);
imshow("图像模糊04", dst04);
imshow("图像模糊05", dst05);
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/flower.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.blur_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.27、高斯模糊

高斯模糊计算公式:

\[G(x,y)=\frac {1} {2π{σ}^{2}}{e}^{-({x}^{2}+{y}^{2})/(2{σ}^{2})}
\]

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_statistic_demo(Mat &image);
void form_paint_random();
void polyline_drawing_demo();
void mouse_drawing_demo(Mat &image);
void norm_demo(Mat &image);
void resize_demo(Mat &image);
void flip_demo(Mat &image);
void rotate_demo(Mat &image);
void video_demo(Mat &image);
void histogram_demo(Mat &image);
void histogram_2d_demo(Mat &image);
void histogram_eq_demo(Mat &image);
void blur_demo(Mat &image);
void gaussian_blue_demo(Mat &image);
};

quickdemo.cpp

void QuickDemo::gaussian_blue_demo(Mat &image) {

	Mat dst01, dst02, dst03;
GaussianBlur(image, dst01, Size(5, 5), 15);
GaussianBlur(image, dst02, Size(3, 3), 15);
GaussianBlur(image, dst03, Size(0, 0), 15); imshow("高斯模糊01",dst01);
imshow("高斯模糊02",dst02);
imshow("高斯模糊03",dst03);
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/flower.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.gaussian_blue_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

2.28、高斯双边模糊

双边滤波原理:

  • 空间距离:当前点距离滤波模板中心点的欧式距离。

  • 灰度距离:当前点距离滤波模板中心点的灰度的差值的绝对值。

双边滤波的核函数是空间域核像素范围域核的综合结果:

  1. 在图像的平坦区域,像素值变化很小,那么像素差值接近于0,对应的像素范围域权重接近于1,此时空间域权重起主要作用,相当于进行高斯模糊;

  2. 在图像的边缘区域,像素值变化很大,那么像素差值大,对应的像素范围域权重变大,即使距离远空间域权重小,加上像素域权重总的系数也较大,从而保护了边缘的信息。

双边滤波在突变的边缘上,使用了像素差权重,很好的保留了边缘。

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_statistic_demo(Mat &image);
void form_paint_random();
void polyline_drawing_demo();
void mouse_drawing_demo(Mat &image);
void norm_demo(Mat &image);
void resize_demo(Mat &image);
void flip_demo(Mat &image);
void rotate_demo(Mat &image);
void video_demo(Mat &image);
void histogram_demo(Mat &image);
void histogram_2d_demo(Mat &image);
void histogram_eq_demo(Mat &image);
void blur_demo(Mat &image);
void gaussian_blue_demo(Mat &image);
void bifilter_demo(Mat &image);
};

quickdemo.cpp

void QuickDemo::bifilter_demo(Mat &image) {
Mat dst;
bilateralFilter(image, dst, 0, 100, 10);
imshow("双边模糊", dst);
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/lena.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.bifilter_demo(src); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

3、案例:实时人脸识别

先下载三个文件置于opencv的face_detector路径下:D:\environment\opencv\sources\samples\dnn\face_detector

下载地址及文件如下:

quickopencv.h

#pragma once

#include<opencv2/opencv.hpp>

using namespace cv;

class QuickDemo {
public:
void colorSpace_Demo(Mat &image);
void mat_creation_demo();
void pixel_visit_demo(Mat &image);
void operators_demo(Mat &image);
void tracking_bar_demo(Mat &image);
void key_demo(Mat &image);
void color_style_demo(Mat &image);
void bitwise_demo(Mat &image);
void channels_demo(Mat &image);
void inrange_demo(Mat &image);
void pixel_statistic_demo(Mat &image);
void form_paint_random();
void polyline_drawing_demo();
void mouse_drawing_demo(Mat &image);
void norm_demo(Mat &image);
void resize_demo(Mat &image);
void flip_demo(Mat &image);
void rotate_demo(Mat &image);
void video_demo(Mat &image);
void histogram_demo(Mat &image);
void histogram_2d_demo(Mat &image);
void histogram_eq_demo(Mat &image);
void blur_demo(Mat &image);
void gaussian_blue_demo(Mat &image);
void bifilter_demo(Mat &image);
void face_detection_demo();
};

quickdemo.cpp

#include<quickopencv.h>
#include<opencv2/dnn.hpp> using namespace cv;
using namespace std; void QuickDemo::face_detection_demo() {
std::string root_dir = "D:/environment/opencv/sources/samples/dnn/face_detector/";
dnn::Net net = dnn::readNetFromTensorflow(root_dir + "opencv_face_detector_uint8.pb", root_dir + "opencv_face_detector.pbtxt");
VideoCapture capture("D:/images/video/example_dsh.mp4");
Mat frame;
while (true) {
capture.read(frame);
if (frame.empty()) {
break;
}
Mat blob = dnn::blobFromImage(frame, 1.0, Size(300, 300), Scalar(104, 177, 123), false, false);
net.setInput(blob); //NCHW
Mat probs = net.forward();
Mat detectionMat(probs.size[2], probs.size[3], CV_32F, probs.ptr<float>());
//解析结果
for (int i = 0; i < detectionMat.rows; i++) {
float confidence = detectionMat.at<float>(i, 2);
if (confidence > 0.5) {
int x1 = static_cast<int>(detectionMat.at<float>(i, 3)*frame.cols);
int y1 = static_cast<int>(detectionMat.at<float>(i, 4)*frame.rows);
int x2 = static_cast<int>(detectionMat.at<float>(i, 5)*frame.cols);
int y2 = static_cast<int>(detectionMat.at<float>(i, 6)*frame.rows);
Rect box(x1, y1, x2 - x1, y2 - y1);
rectangle(frame, box, Scalar(0, 0, 255), 2, 8, 0);
}
}
imshow("人脸检测演示", frame);
//TODO: do something...
int c = waitKey(1);
if (c == 27) { //退出
break;
} }
}

test440.cpp

#include<opencv2/opencv.hpp>
#include<quickopencv.h>
#include<iostream> using namespace cv;
using namespace std; int main(int argc, char**argv) {
// imread函数的第二个参数有很多,默认为IMREAD_COLOR,还有IMREAD_UNCHANGED,IMREAD_GRAYSCALE,IMREAD_ANYCOLOR等等,实现对不同图片的读取操作
// B,G,R
Mat src = imread("D:/images/lena.jpg"); //Mat为matrix,二维图像都是Mat类型,第一个参数为图片绝对路径
if (src.empty()) {
printf("could not load image...\n");
return -1;
}
//namedWindow("输入窗口", WINDOW_FREERATIO); //不管图片大小,都能进行调整,图像很小可以不使用这个函数
//imshow("输入窗口", src); //第一个参数为窗口名 QuickDemo qd;
qd.face_detection_demo(); waitKey(0); //窗口停留时间,0为一直停留,数值为停留的毫秒数
destroyAllWindows(); //关闭所有打开的窗口
return 0;
}

效果

OpenCV4之C++入门详解的更多相关文章

  1. Linq之旅:Linq入门详解(Linq to Objects)

    示例代码下载:Linq之旅:Linq入门详解(Linq to Objects) 本博文详细介绍 .NET 3.5 中引入的重要功能:Language Integrated Query(LINQ,语言集 ...

  2. SQL注入攻防入门详解

    =============安全性篇目录============== 本文转载 毕业开始从事winfrm到今年转到 web ,在码农届已经足足混了快接近3年了,但是对安全方面的知识依旧薄弱,事实上是没机 ...

  3. SQL注入攻防入门详解(2)

    SQL注入攻防入门详解 =============安全性篇目录============== 毕业开始从事winfrm到今年转到 web ,在码农届已经足足混了快接近3年了,但是对安全方面的知识依旧薄弱 ...

  4. Quartz 入门详解

    Quartz是OpenSymphony开源组织在Job scheduling领域又一个开源项目,它可以与J2EE与J2SE应用程序相结合也可以单独使用.Quartz可以用来创建简单或为运行十个,百个, ...

  5. Redis快速入门详解

    Redis入门详解 Redis简介 Redis安装 Redis配置 Redis数据类型 Redis功能 持久化 主从复制 事务支持 发布订阅 管道 虚拟内存 Redis性能 Redis部署 Redis ...

  6. [转]SQL注入攻防入门详解

    原文地址:http://www.cnblogs.com/heyuquan/archive/2012/10/31/2748577.html =============安全性篇目录============ ...

  7. [置顶] xamarin android toolbar(踩坑完全入门详解)

    网上关于toolbar的教程有很多,很多新手,在使用toolbar的时候踩坑实在太多了,不好好总结一下,实在浪费.如果你想学习toolbar,你肯定会去去搜索androd toolbar,既然你能看到 ...

  8. 转:JAVAWEB开发之权限管理(二)——shiro入门详解以及使用方法、shiro认证与shiro授权

    原文地址:JAVAWEB开发之权限管理(二)——shiro入门详解以及使用方法.shiro认证与shiro授权 以下是部分内容,具体见原文. shiro介绍 什么是shiro shiro是Apache ...

  9. webpack入门详解

    webpack入门详解(基于webpack 3.5.4  2017-8-22) webpack常用命令: webpack --display-error-details    //执行打包 webpa ...

随机推荐

  1. 【Azure 存储服务】Java Azure Storage SDK V12使用Endpoint连接Blob Service遇见 The Azure Storage endpoint url is malformed

    问题描述 使用Azure Storage Account的共享访问签名(Share Access Signature) 生成的终结点,连接时遇见  The Azure Storage endpoint ...

  2. Matplotlib的小入门

    Matplotlib专门用于开发2D图表(包括3D图表),在日常数据处理中经常需要运用到它,它的用法非常多样,这里记录一些基础用法,算是一个小入门,后面如果有更复杂的画图要求,再进一步学习. 如果有需 ...

  3. 3000帧动画图解MySQL为什么需要binlog、redo log和undo log

    全文建立在MySQL的存储引擎为InnoDB的基础上 先看一条SQL如何入库的: 这是一条很简单的更新SQL,从MySQL服务端接收到SQL到落盘,先后经过了MySQL Server层和InnoDB存 ...

  4. ER图/模型转换为关系模型

    ER图中的主要成分是实体类型和联系类型,转换规则就是如何把实体类型.联系类型转换成关系模式. 1. 二元联系转换 规则1.1(实体类型的转换):将每个实体类型转换成一个关系模式,实体的属性即为关系模式 ...

  5. Keytool配置 Tomcat的HTTPS双向认证

    Keytool配置 Tomcat的HTTPS双向认证 证书生成 keytool 简介 Keytool是一个Java数据证书的管理工具, Keytool将密钥(key)和证书(certificates) ...

  6. 中国天气api接口xml,json

    http://m.weather.com.cn/data/101110101.html 大坑有木有??反应慢不说了,还老不更新!! 想贴段代码的,现在又打不 开了(貌似3月4号以后没更新过) ==== ...

  7. Vue几行代码实现搜索功能

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. Linux的文件路径和访问文件相关命令

    Linux的绝对和相对路径 绝地路径 绝对路径:以根作为起来的路径 相对路径 相对路径:以当前位置作为起点 文件操作命令 显示当前工作目录: pwd命令 pwd:显示文件所在的路径 基名:basena ...

  9. 简单实现python接口自动化(一)

    目的:excel中维护接口用例数据,通过python中requests库进行读取用例,并把运行结果与excel中的预期结果对比,最后把执行情况写入到excel中去. excel维护数据: 具体的接口名 ...

  10. HashMap的实现原理?如何保证HashMap线程安全?

    A:HashMap简单说就是它根据建的hashcode值存储数据的,大多数情况下可以直接定位到它的值,因而具有很快的访问速度,但遍历的顺序是不确定的. B:HashMap基于哈希表,底层结构由数组来实 ...