这篇文章主要是为了保存一下之前学习的opencv代码,其次是希望能帮助到其他人。
B站网课链接贾志刚老师43讲 课程感觉有点没用免费课程干货太少,简单的介绍OpenCV常见函数的用法,并没有深入讲解源码。可能是免费课程的原因,建议看一下源码就行。目前在看C++的OpenCV课程推荐有夏曹俊老师的课程。这个应该是教育机构的推销课程相对其他OpenCV相比还是比较优秀的。
一、什么是OpenCV
OpenCV的全称是Open Source Computer Vision Library,是一个跨平台的计算机视觉处理开源软件库,是由Intel公司俄罗斯团队发起并参与和维护,支持与计算机视觉和机器学习相关的众多算法,以BSD许可证授权发行,可以在商业和研究领域中免费使用。OpenCV可用于开发实时的图像处理、计算机视觉以及模式识别程序,该程序库也可以使用英特尔公司的IPP进行加速处理。
二、OpenCV官方下载链接
Opencv官网地址为官方地址,网站提供了各个版本源码、发行版的下载地址及说明文档,其中Windows的下载包是一个自解压程序,解压之后有两个文件夹,其中sources文件夹里包含源码,build中包含编译好的库文件,以供Windows下编译opencv使用。
GitHub上的地址为Git地址,该网址下有多个opencv相关的仓库,其中opencv仓库中包含了opencv的源码。
三、Visual Studio配置OpenCV环境
之前写过一篇这方面的配置方法跳转接口
综合比较了几篇CSDN其他大佬的配置环境的文章比较推荐这一篇OpenCV配置
四、代码实现功能目录
void colorSpace_demo(Mat& image); //图像色彩空间转换
void mat_creation_demo(Mat& image); //图像对象的创建与赋值
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 drawing_demo(Mat& image); //图像几何图形绘制
void random_drawing_demo(Mat& image); //随机数与随机颜色
void polyline_drawing_demo(Mat& image); //多边形天聪与绘制
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 videokeep_demo(Mat& image); //视频处理与保存
void showHistogram_demo(Mat& image); //图像直方图
void histogram_2d_demo(Mat& image); //二维直方图
void hisogram_eq_demo(Mat& image); //直方图均衡化
void blur_demo(Mat& image); //图像卷积操作
void gaussian_blur_demo(Mat& image); //高斯模糊
void bifilter_demo(Mat& image); //高斯双边模糊
五、源代码
quickopencv.h
#pragma once
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
class QuickDemo {
public:
void colorSpace_demo(Mat& image); //图像色彩空间转换
void mat_creation_demo(Mat& image); //图像对象的创建与赋值
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 drawing_demo(Mat& image); //图像几何图形绘制
void random_drawing_demo(Mat& image); //随机数与随机颜色
void polyline_drawing_demo(Mat& image); //多边形天聪与绘制
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 videokeep_demo(Mat& image); //视频处理与保存
void showHistogram_demo(Mat& image); //图像直方图
void histogram_2d_demo(Mat& image); //二维直方图
void hisogram_eq_demo(Mat& image); //直方图均衡化
void blur_demo(Mat& image); //图像卷积操作
void gaussian_blur_demo(Mat& image); //高斯模糊
void bifilter_demo(Mat& image); //高斯双边模糊
};
quickdemo.cpp
#include "quickopencv.h"
void QuickDemo::colorSpace_demo(Mat& image)
{
Mat gray, hsv;
cvtColor(image, hsv, COLOR_BGR2HSV);
//HSV 三通道 H0~180 S0~255 V0~255 V是亮度
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("HSV", hsv);
imshow("hh", gray);
imwrite("D:\\系统默认\\桌面\\OpenCV\\OpenCV_S02\\hsv.jpg",hsv);
imwrite("D:\\系统默认\\桌面\\OpenCV\\OpenCV_S02\\gray.jpg",gray);
}
void QuickDemo::mat_creation_demo(Mat& image)
{
Mat m1, m2;
m1 = image.clone();
image.copyTo(m2);
//创建空白图像
Mat m3 = Mat::ones(Size(8, 8), CV_8UC3); //8位无符号的单通道数据
cout << "width: " << m3.cols << "height: " << m3.rows << "channels " << m3.channels() << endl;
m3 = Scalar(0, 0,255);
//Mat m4 = m3;
//clone 克隆 而直接等于就会改变两个,随便用 “= ”会重构
Mat m4 = m3.clone();
m4 = Scalar(0, 255, 255);
imshow("m3", m3);
imshow("m4", m4);
}
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++)
{
uchar* current_row = image.ptr<uchar>(row);
for (int col = 0; col < w; col++)
{
if (dims == 1) //灰度图像
{
int pv = image.at<uchar>(row, col);
image.at<uchar>(row, col) = 255 - pv;
}
if (dims == 3) //彩色图像
{
//Vec3b 一次性获取是三个值
Vec3b bgr = image.at<Vec3b>(row, col);
image.at<Vec3b>(row, col)[0] = 255 - bgr[0]-34;
image.at<Vec3b>(row, col)[1] = 255 - bgr[1]-34;
image.at<Vec3b>(row, col)[2] = 255 - bgr[2]-34;
}
}
}
imshow("像素读写", image);
}
void QuickDemo::operators_demo(Mat& image)
{
Mat dst = Mat::zeros(image.size(), image.type());;
//创建图像全是0
Mat m = Mat::zeros(image.size(), image.type());
m=Scalar(50, 50, 50);
//opencv中两个图像相乘与专有函数multiply
//dst = image * m;
//multiply(image, m, dst);
//加法
//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 一次性获取是三个值
// Vec3b p1 = image.at<Vec3b>(row, col);
// Vec3b p2 = m.at<Vec3b>(row, col);
// //saturate_cast<uchar>()类型数值限定uchar------>0~255
// 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);
imshow("减法操作",dst);
//subtract(image, m, dst);
imshow("乘法操作",dst);
//multiply(image, m, dst);
imshow("除法操作",dst);
//divide(image, m, dst);
}
static void on_lightness(int b, void* userdata)
{
Mat image = *((Mat*)userdata);
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
m = Scalar(b, b, b);
//图像融合 1:数组通常为图片,2.第一个数组的权重3.第二的数组图片
//,4,第二过数组的权重,5一个加到权重总和的标量,6:输出数组,7:可选深度
addWeighted(image, 1.0, m, 0.0, b, dst);
imshow("亮度与对比度调节", dst);
}static void on_contrast(int b, void* userdata)
{
Mat image = *((Mat*)userdata);
Mat dst = Mat::zeros(image.size(), image.type());
Mat m = Mat::zeros(image.size(), image.type());
double contrast = b / 100.0;
//图像融合
addWeighted(image,contrast,m,0.0,0,dst);
imshow("亮度与对比度调节", dst);
}
void QuickDemo::tracking_bar_demo(Mat& image)
{
namedWindow("亮度与对比度调节",WINDOW_AUTOSIZE);
int lightness = 50;
int max_value = 100;
//回调参数错:1:滑动栏名称,2:吸附窗口名称,3.滑动条初始值,指针,4.最大值,5.回调函数,6.void*类型指针 //向回调函数传输数据
createTrackbar("Value Bar:","亮度与对比度调节", &lightness, max_value, on_lightness,(void*)(&image));
createTrackbar("Contrast Bar:", "亮度与对比度调节", &max_value, 200, on_contrast, (void*)(&image));
}
void QuickDemo::key_demo(Mat& image)
{
Mat dst = Mat::zeros(image.size(), image.type());
while (true)
{
char c = waitKey(100);
if (c == 27)
{
break;
}
if (c == 49)
{
cout << "you key #1" << endl;
cvtColor(image, dst, COLOR_BGR2GRAY);
}
if (c == 50)
{
cout << "you key #2" << endl;
cvtColor(image, dst, COLOR_BGR2HSV);
}
if (c == 51)
{
cvtColor(image, dst, COLOR_BGR2HSV); //不加会卡死
cout << "you key #3" << endl;
dst = Scalar(50, 50, 50);
add(image, dst, dst);
}
imshow("键盘响应", dst);
}
}
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 = Mat::zeros(image.size(), image.type());
int index = 0;
while (true)
{
char c = waitKey(2000);
if (c == 27)
{
break;
}
//滤镜函数1输入图像,2.输出图像,3.颜色类型
applyColorMap(image, dst, colormap[index % 19]);
index++;
imshow("颜色style", dst);
}
}
void QuickDemo::bitwise_demo(Mat& image)
{
Mat m1 = Mat::zeros(Size(256,256),CV_8UC3);
Mat m2 = Mat::zeros(Size(256,256),CV_8UC3);
// 矩形函数1.图像,2.矩形顶点,3.对角线定点 3.线条颜色,4.线条粗细 ,5.线条类型,6.坐标小数点位数
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;
//图像位运算函数,1,图片1,2.图片2,3.得到的图片
//bitwise_or bitwise_and
bitwise_xor(m1, m2, dst);
imshow("像素位操作",dst);
}
void QuickDemo::channels_demo(Mat& image)
{
vector<Mat> mv;
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);
int from_to[] = { 0,2,1,1,2,0 };
//1.输入对象,2.输入对象个数,3.输出对象, 4.输出对象个数,5.拷贝构造
mixChannels(&image,1, &dst, 1,from_to,3);
imshow("通道混合", dst);
}
void QuickDemo::inrange_demo(Mat& image)
{
Mat hsv;
cvtColor(image, hsv, COLOR_BGR2HSV);
Mat mask;
//二值化HSV 1·处理图像,2·下界数组,3·上边界数组,4·输出图像
inRange(hsv, Scalar(35, 43, 46), Scalar(77, 255, 25), mask);
imshow("mask", mask);
Mat redback = Mat::zeros(image.size(), image.type());
redback = Scalar(40, 40, 200);
bitwise_not(mask, mask);
image.copyTo(redback, mask);
}
void QuickDemo::pixel_statistic_demo(Mat& image)
{
double minv, maxv;
Point minLoc, maxLoc;
vector<Mat> mv;
split(image, mv);
cout << endl;
for (int i = 0; i <mv.size(); i++)
{
//功能:从一个矩阵中找出全局的最大值和最小值。
/* 参数1:InputArray类型的src,输入单通道数组(图像)。
参数2:double* 类型的minVal,返回最小值的指针。若无须返回,此值置为NULL。
参数3:double* 类型的maxVal,返回最大值的指针。若无须返回,此值置为NULL。
参数4:Point* 类型的minLoc,返回最小位置的指针(二维情况下)。若无须返回,此值置为NULL。
参数5:Point* 类型的maxLoc,返回最大位置的指针(二维情况下)。若无须返回,此值置为NULL。
参数6:InputArray类型的mask,用于选择子阵列的可选掩膜。*/
minMaxLoc(mv[i], &minv, &maxv, &minLoc, &maxLoc, Mat());
cout <<"No.channels:" <<i<< " " << "min value:" << minv << " "<<"max value:" << maxv << endl;
}
Mat mean, stddev;
// 参数 说明 用于:平均值和标准方差统计
//src 输入数组(图像)1 - 4通道都可以
//mean 均值
//stddev 标准差
//mask 用于选择子阵列的可选掩码
meanStdDev(image, mean, stddev);
cout << "means:" <<endl<< mean << endl;
cout <<"stddev:" <<endl<< stddev << endl;
}
void QuickDemo::drawing_demo(Mat& image)
{
Rect rect;
rect.x = 170;
rect.y = 100;
rect.width = 100;
rect.height = 120;
Mat bg = Mat::zeros(image.size(), image.type());
/* 参数 说明
img Mat类型 输入输出图像
rec Rect类型 绘制好的矩形框(左上角坐标和长宽已确定)
color 用Scalar函数绘制颜色
thickness 矩形框填充方式 thickness > 0为矩形框, thickness < 0为填充 默认为1
lineType 矩形框的线条类型 默认为8
shift 点坐标小数数位 默认为0*/
rectangle(image, rect, Scalar(0, 0, 255), -1, 8, 0);
// 参数 说明
//img Mat类型 输入输出图像
//center 画圆的圆心坐标
//radius 圆的半径
//color 用Scalar函数绘制圆颜色
//thickness 如果是正数,表示组成圆的线条的粗细程度。否则,表示圆是否被填充
//lineType 线条类型 默认为8
//shift 圆心坐标点和半径值的小数点位数
circle(image, Point(300, 450),20, Scalar(255, 0, 0), -1, 8, 0);
/* 参数 说明
img Mat类型 输入输出图像
ptr1 point类型 线段起点
ptr2 point类型 线段终点
color 用Scalar函数绘制圆颜色
thickness 如果是正数,表示组成圆的线条的粗细程度。否则,表示圆是否被填充
lineType 线条类型 默认为8
shift 坐标点的小数点位数*/
line(bg, Point(100, 100), Point(350, 400), Scalar(0, 255, 0), 2, 8, 0);
RotatedRect rrt;
rrt.center = Point(200, 200);
rrt.size = Size(100, 200);
rrt.angle = 90.0;
/* 参数 说明
img Mat类型 输入输出图像
box RotatedRect类型 旋转好的外接矩阵内嵌椭圆(包括外接矩形的中心,变长和旋转角度)
color 用Scalar函数绘制圆颜色
thickness 如果是正数,表示组成圆的线条的粗细程度。否则,表示圆是否被填充
lineType 线条类型 默认为8*/
ellipse(bg, rrt, Scalar(0,255,255), 2, 8);
Mat dst;
addWeighted(image, 0.7, bg, 0.3, 0,dst);
imshow("绘制演示",dst);
}
void QuickDemo::random_drawing_demo(Mat& image)
{
Mat canvas = Mat::zeros(Size(512, 512), CV_8UC3);
RNG rng(12345);
int w = canvas.cols;
int h = canvas.rows;
while (true)
{
int c = waitKey(10);
if (c == 27)
{
break;
}
int x1 = rng.uniform(0, w);
int y1 = rng.uniform(0, h);
int x2 = rng.uniform(0, w);
int y2 = rng.uniform(0, h);
int b = rng.uniform(0, 255);
int g = rng.uniform(0, 255);
int r = rng.uniform(0, 255);
canvas = Scalar(0, 0, 0);
line(canvas, Point(x1, y1), Point(x2, y2), Scalar(b,g,r), 1, LINE_AA, 0);
imshow("显示",canvas);
}
}
void QuickDemo::polyline_drawing_demo(Mat& image)
{
Mat canvas = 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(70, 400);
vector<Point> pts;
pts.push_back(p1);
pts.push_back(p2);
pts.push_back(p3);
pts.push_back(p4);
pts.push_back(p5);
/*
fillPoly(img,ppt,npt,1,Scalar(255,255,255),lineType);
1、多边形将被画到img上
2、多边形的顶点集为ppt
3、绘制的多边形顶点数目为npt
4、要绘制的多边形数量为1
5、多边形的颜色定义为Scarlar(255, 255, 255),即RGB的值为白色*/
fillPoly(canvas, pts, Scalar(255, 0, 0),8,0);
/*
void polylines(Mat& img, const Point** pts, const int* npts, int ncontours,
bool isClosed, const Scalar& color, int thickness=1, int lineType=8, int shift=0 );
参数 说明
img 作为画布的矩阵
pts 折线顶点数组
npts 折线顶点个数
ncontours 待绘制折线数
isClosed 是否是闭合折线(多边形)
color 折线的颜色
thickness 折线粗细
lineType 线段类型
shift 缩放比例(0是不缩放, 4是1 / 4)
*/
polylines(canvas, pts, true, Scalar(0, 255, 0), 2,LINE_AA, 0);
vector<vector<Point>> contours;
contours.push_back(pts);
/*
void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx,
const Scalar & color, int thickness = 1, int lineType = 8, InputArray hierarchy = noArray(),
int maxLevel = INT_MAX, Point offset = Point())
函数参数详解:
第一个参数image表示目标图像,
第二个参数contours表示输入的轮廓组,每一组轮廓由点vector构成,
第三个参数contourIdx指明画第几个轮廓,如果该参数为负值,则画全部轮廓,
第四个参数color为轮廓的颜色,
第五个参数thickness为轮廓的线宽,如果为负值或CV_FILLED表示填充轮廓内部,
第六个参数lineType为线型,
第七个参数为轮廓结构信息,
第八个参数为maxLevel
*/
drawContours(canvas, contours, -1, Scalar(0, 255, 0), 2);
imshow("多边形绘制", canvas);
}
Point sp(-1, -1);
Point ep(-1, -1);
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;
cout << "start point:" << sp << 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);
rectangle(image,box, Scalar(0, 0, 255), 2, 8, 0);
imshow("鼠标绘制", image);
imshow("ROI区域", temp(box));
//为下一次画图准备 更新操作
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:: QuickDemo::mouse_drawing_demo(Mat& image)
{
namedWindow("鼠标绘制", WINDOW_AUTOSIZE);
namedWindow("ROI区域", WINDOW_NORMAL);
setMouseCallback("鼠标绘制",on_draw,(void*)(&image));
setMouseCallback("ROI区域", on_draw, (void*)(&image));
imshow("鼠标绘制", image);
temp = image.clone(); imshow("ROI区域", temp);
}
void QuickDemo::norm_demo(Mat& image)
{
Mat dst;
cout << image.type() << endl;
image.convertTo(dst,CV_32F);
cout << dst.type() << endl;
//归一化函数
normalize(image, dst, 1.0, 0, NORM_MINMAX);
cout << dst.type() << endl;
imshow("图像数据归一化",dst);
}
void QuickDemo::resize_demo(Mat& image)
{
Mat zoomin = Mat::zeros(image.size(), image.type());
Mat zoomax = Mat::zeros(image.size(), image.type());
int h = image.rows;
int w = image.cols;
resize(image, zoomin, Size(w / 2, h / 2), 0, 0, INTER_LINEAR);
imshow("zoomin", zoomin);
resize(image, zoomax, Size(w*1.5, h*1.5), 0, 0, INTER_LINEAR);
imshow("zoomax", zoomax);
}
void QuickDemo::flip_demo(Mat& image)
{
Mat dst;
/* 参数 src 输入矩阵.
参数 dst 输出矩阵,和输入矩阵一样大小。
参数 flipCode 一个标志,决定怎么翻转矩阵; 0 是围绕着x轴翻转,
正直是围绕着y轴翻转,负值是围绕着两个轴一起翻转。 around both axes.
参考 transpose, repeat, completeSym
*/
flip(image, dst, 0);
imshow("图像翻转",dst);
}
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));
double nw = cos * w + sin * h;
double 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(0,255,0));
imshow("旋转演示", dst);
}
void QuickDemo::video_demo(Mat& image)
{
VideoCapture capture(0);
Mat frame;
while (true)
{
capture.read(frame);
flip(frame, frame,1);
if (frame.empty())
{
break;
}
imshow("frame", frame);
int c = waitKey(10);
if (c == 27)
{
break;
}
}
}
void QuickDemo::videokeep_demo(Mat& image)
{
VideoCapture capture("D:\\HONOR Magic-link\\Screenshot\\20220708_144725.mp4");
double frame_width = capture.get(CAP_PROP_FRAME_WIDTH);
double frame_height = capture.get(CAP_PROP_FRAME_HEIGHT);
double frame_count = capture.get(CAP_PROP_FRAME_COUNT);
double frame_fps = capture.get(CAP_PROP_FPS);
cout << " frame_fps: " << frame_fps << endl;
cout << "frame_width: "<<frame_width << endl;
cout << "frame_height:"<<frame_height << endl;
cout << "frame_count: "<<frame_count << endl;
VideoWriter writer("D://HONOR Magic-link//Screenshot//text.mp4", capture.get(CAP_PROP_FOURCC),frame_fps,Size(frame_width,frame_height),true);
Mat frame;
while (true)
{
capture.read(frame);
flip(frame, frame, 1);
if (frame.empty())
{
break;
}
imshow("frame", frame);
colorSpace_demo(frame);
writer.write(frame);
int c = waitKey(10);
if (c == 27)
{
break;
}
}
capture.release();
writer.release();
}
void QuickDemo::showHistogram_demo(Mat& image)
{
//三通道分离
vector <Mat> bgr_plane;
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, 8, 0);
line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(g_hist.at<float>(i - 1))),
Point(bin_w * (i), hist_h - cvRound(g_hist.at<float>(i))), Scalar(0, 255, 0), 2, 8, 0);
line(histImage, Point(bin_w * (i - 1), hist_h - cvRound(r_hist.at<float>(i - 1))),
Point(bin_w * (i), hist_h - cvRound(r_hist.at<float>(i))), Scalar(0, 0, 255), 2, 8, 0);
}
//显示直方图
namedWindow("Histogram Demo", WINDOW_AUTOSIZE);
imshow("Histogram Demo", histImage);
}
void QuickDemo::histogram_2d_demo(Mat& image)
{
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);
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, COLORMAP_JET);
imshow("H_s", hist2d_image);
}
void QuickDemo::hisogram_eq_demo(Mat& image)
{
Mat gray;
cvtColor(image, gray, COLOR_BGR2GRAY);
imshow("灰度图像", gray);
Mat dst;
equalizeHist(gray, dst);
imshow("直方图均衡化",dst);
}
void QuickDemo::blur_demo(Mat& image)
{
Mat dst;
blur(image, dst, Size(3, 3), Point(-1, -1));
imshow("图像模糊",dst);
}
void QuickDemo::gaussian_blur_demo(Mat& image)
{
Mat dst;
GaussianBlur(image, dst, Size(5, 5), 15);
imshow("高斯模糊",dst);
}
void QuickDemo::bifilter_demo(Mat& image)
{
Mat dst;
bilateralFilter(image, dst, 0,100, 10);
imshow("双边模糊", dst);
}
main.cpp
#include "quickopencv.h"
#include <fstream>
#include <string>
int main(int argc, char** argv)
{
//Mat 矩阵
//imread() 读图片,参数1:图片位置(注意反斜线方向) 参数2:色域
Mat src = imread("D:\\系统默认\\桌面\\OpenCV\\OpenCV_S02\\text.jpg");
//判断是否找到图片位置,防止报错
if (src.empty())
{
cout << "没找到图片" << endl;
return -1;
}
namedWindow("windowname",WINDOW_FREERATIO);
imshow("windowname", src);
QuickDemo qd;
//qd.colorSpace_Demo(src);
//qd.mat_creation_demo(src);
//qd.pixel_visit_demo(src);
//qd.operators_demo(src);
//qd.tracking_bar_demo(src);
//qd.key_demo(src);
//qd.color_style_demo(src);
//qd.bitwise_demo(src);
//qd.channels_demo(src);
//qd.inrange_demo(src);
//qd.pixel_statistic_demo(src);
//qd.drawing_demo(src);
//qd.random_drawing(src);
//qd.polyline_drawing_demo(src);
//qd.mouse_drawing_demo(src);
//qd.norm_demo(src);
//qd.resize_demo(src);
//qd.flip_demo(src);
//qd.rotate_demo(src);
//qd.video_demo(src);
//qd.videokeep_demo(src);
//qd.showHistogram_demo(src);
//qd.histogram_2d_demo(src);
//qd.hisogram_eq_demo(src);
//qd.blur_demo(src);
//qd.gaussian_blur_demo(src);
//qd.bifilter_demo(src);
waitKey(0); //因为阻塞就会一直停留
destroyAllWindows();
system("cls");
return 0;
}