当前位置: 首页 > article >正文

c++视频图像处理

打开视频或摄像头

打开指定视频

	/*VideoCapture(const String &filename, apiPreference);
	filename:读取的视频或者图像序列的名称
	apiPreference:读取数据时设置的属性
	*/
VideoCapture video;  //定义一个空的视频对象
video.open("H:/BaiduNetdiskDownload/01.mp4");
// 判断视频有没有成功打开
	if (!video.isOpened()) {
		cout << "视频打开失败";
		return -1;
	}

打开摄像头

VideoCapture video(1);   //打开一个摄像头

视频的相关操作

通过get获取视频数据
在这里插入图片描述
将视频流赋值给mat对象

	Mat mat;
	video >> mat; 
	bool isColor = (mat.type() == CV_8UC3);  //判断视频是否为3通道彩色

输出视频的帧率

cout <<"视频的帧率"<< video.get(CAP_PROP_FPS);

VideoWriter 视频写入

filename:保存视频的地址和文件名,包含视频格式
fourcc:压缩帧的4字符编解码器代码
fps:保存视频的帧率,即视频中每秒图像的张数
framSize:视频帧的尺寸
isColor:保存视频是否为彩色视频

	VideoWriter writer;
	int codec = VideoWriter::fourcc('M', 'J', 'P', 'G');  //选择MJPG的编码格式
	double fps = 25.0;  //设置视频的帧率
	string filename = "file.avi";	// 视频的名和格式
	writer.open(filename, codec, fps, mat.size(),isColor);   //创建保存文件的视频流
	if (!writer.isOpened()) {   // 判断视频流是否正常打开
		cout << "视频打开失败";
		return -1;
	}

保存视频中的数据

while (1) {   
		// 检查是否执行完毕   
		if (!video.read(video))  // 判断能否从摄像头或者视频文件中读出一帧图像
		{
			cout<<"摄像头或者视频读取完成"<<endl;
			break;
		}
		writer.write(video);  //把图像写入视频流    writer<<mat
		imshow('live', video);  //显示图像 
		char c = waitKey(50);
		if (c == 27) {   //俺esc退出
			break;
		}
	}

颜色空间转换

三种存取数据的区间

  • 8U–存储0-255的数据类型
  • 32F–存储0-1(将0-1区间映射为0-255,大于1的部分映射为白色,小于0的部分映射为黑色)
  • 64F–存储0-1
    convertTo

m:输出图像
rtype:转换后数据类型
alpha:缩放系数
beta:平移系数
转换公式:alpha*I(x,y)+ beta

// 将0-255的图像转为0-1
	mat.convertTo(mat2, CV_32F, 1/255.0, 0);

RGB转灰度图公式:Gray=R0.3+G0.59+B*0.11

图像格式转换cvtColor

src:待转换颜色模型的原始图像
dst:转换颜色模型后的目标图像。
code:颜色空间转换的标志,如由RGB空间到HSV空间。
dstCn:目标图像中的通道数,如果参数为0,则从src和代码中自动导出通道数。

	Mat HSV;
	// 将RGB转为HSV
	cvtColor(mat, HSV, COLOR_BGR2HSV);

通道管理

split多通道分离

split(
InputArray m, //可以输入mat型
OutputArrayOfArrays mv
)
m:待分离的多通道图像
mv:分离后的单通道图像,为向量vector形式

merge多通道合并

merge(
InputArrayOfArrays mv,
OutputArray dst )
mv:需要合并的图像向量vector,其中每个图像必须拥有相同的尺寸和数据类型
dst:合并后输出的图像,通道数等于所有输入图像的通道数的总和

合并两个矩阵,取同一位置中较小的值

min(
InputArray src1,
InoytArray sec2,
OutputArray dst )

合并两个矩阵,取同一位置中较大的值

max(
InputArray src1,
InoytArray sec2,
OutputArray dst )

找出矩阵中的最值

minMaxLoc(
InputArray src, //输入单通道矩阵
CV_OUT double* minVal, //指向最小值的指针,如果不需要,则使用NULL
CV_OUT double* maxVal =0, //指向最大值的指针,如果不需要,则使用NULL
CV_OUT Point* minLoc =0, //指向最小值位置的指针,如果不需要,则使用NULL
CV_OUT Point* maxLoc = 0, //指向最大值位置的指针,如果不需要,则使用NULL
InputArray mask =noArray() //掩码矩阵,用于标记寻找上述四个值的范围,参数默认值为noArray,表示寻找范围是矩阵中所有数据
)

与或非运算

bitwise_not(						//非运算
	InputArray src,					//输入矩阵
	OutputArray dst,				//输出矩阵
	InputArray mask = noArray()		//掩码区域
)
	bitwise_and(					//与运算
		InputArray src1,			//输入矩阵1
		InputArray src2,			//输入矩阵2
		OutputArray dst,			// 输出矩阵
		InputArray mask = noArray());//掩码矩阵
bitwise_or(						//或运算
	InputArray src1,			//输入矩阵1
	InputArray src2,			//输入矩阵2
	OutputArray dst,			// 输出矩阵
	InputArray mask = noArray());//掩码矩阵
)

阈值化(二值化)

在这里插入图片描述
threshold( //图像二值化
InputArray src, //待二值化图像,图像只能是CV_8U和CV_32F两种数据类型
OutputArray dst, //二值化后的图像
double thresh, //阈值
double maxval, //二值化过程中的最大值,非必须参数
int type //二值化方式
);

adaptiveThreshold(			//自适应阈值化,只支持灰度图
	InputArray src,			//待二值化图像
	OutputArray dst,		//输出图像
	double maxValue,		//二值化的最大值
	int adaptiveMethod,		//自适应确定阈值的方法,分为均值法ADAPTIVE_THRESH_MEAN_C和高斯法ADAPTIVE_THRESH_GAUSSIAN_C
	int thresholdType,		//选择二值化方法
	int blockSize,			//自适应确定阈值的像素邻域大小
	double C);				//从平均值或者加权平均值中减去的常数

LUT查找表
LUT(
InputArray src, //输入图像,类型只能是8U
InputArray lut, //256个像素的查找表,如果为多通道,通道数必须和输入图像通道数相同
OutputArray dst //输出矩阵,数据类型和查找表相同
);

图像尺寸缩放、翻转、拼接

resize(
	InputArray src,							//输入图像
	OutputArray dst,						//输出图像
	Size dsize,								//输出图像的尺寸
	double fx = 0,							//水平轴的比例因子,变为原来的几倍
	double fy = 0,							//垂直轴的比例因子
	int interpolation = INTER_LINEAR		//插值方法,INTER_AREA最近邻插值,INTER_LINEAR双线性插值,INTER_CUBIC三线性插值
);

flip(   图像翻转
	InputArray src,		//输入图像
	OutputArray dst,	//输出图像
	int flipCode		//翻转方式标志,数值大于0表示绕y轴翻转,数值等于0表示围绕x轴翻转,数值小于0表示围绕两个轴翻转
);
resize(INTER_AREA,INTER_LINEAR,INTER_CUBIC)

hconcat(//横向拼接
	InputArray src1,		// 输入图像 
	InputArray src2,		//输入图像,需要两个输入图像高度相同
	OutputArray dst			//输出图像
)	



vconcat(//纵向拼接
	InputArray src1,		// 输入图像 
	InputArray src2,		//输入图像,需要两个输入图像高度相同
	OutputArray dst			//输出图像
)

仿射变换和旋转

// 仿射变换:由平移,缩放,旋转,翻转和错切组合得到,也叫三点变换

在这里插入图片描述

warpAffine(      仿射变换
	InputArray src,								//输入图像
	OutputArray dst,							//输出图像
	InputArray M,								//2*3变换矩阵,仿射变换矩阵
	Size dsize,									//输出图像尺寸
	int flags = INTER_LINEAR,					//插值方法标志
	int borderMode = BORDER_CONSTANT,			//像素边界外推方法的标志
	const Scalar& borderValue = Scalar());		//填充边界使用的数值,默认情况下为0

像素边界外推方法
BORDER_CONSTANT = 0,用特定值填充//!< iiiiii|abcdefgh|iiiiiii
BORDER_REPLICATE = 1,两端复制填充//!< aaaaaa|abcdefgh|hhhhhhh
BORDER_REFLECT = 2, 倒叙填充//!< fedcba|abcdefgh|hgfedcb
BORDER_WRAP = 3, 正序填充//!< cdefgh|abcdefgh|abcdefg
BORDER_REFLECT_101 = 4, 不包含边界值倒叙填充//!< gfedcb|abcdefgh|gfedcba
BORDER_TRANSPARENT = 5, //随机填充!< uvwxyz|abcdefgh|ijklmno
BORDER_REFLECT101 = BORDER_REFLECT_101, //!与BORDER_REFLECT_101相同
BORDER_DEFAULT = BORDER_REFLECT_101, //!与BORDER_REFLECT_101相同
BORDER_ISOLATED = 16 //!< 不关心感兴趣区域之外的部分

c++中并没有直接进行图像旋转的函数,需要求取一个旋转变换的仿射矩阵,通过仿射矩阵实现图像的旋转
getRotationMatrix2D( 图像旋转,返回一个2*3的矩阵
Point2f center, 图像旋转的中心位置
double angle, 图像旋转的角度,正值为逆时针旋转
double scale 两个轴的比例因子,可以实现旋转过程中的图像缩放,不缩放输入1
);
图像旋转的计算公式
在这里插入图片描述
三点对应方式计算仿射变换矩阵
getAffineTransform(
const Point2f src[], 原图像的三个点坐标
const Point2f dst[] 仿射变换后的三个点坐标
);

透视变换(透视投影,又叫四点变换)

在这里插入图片描述
从一个点出发把一个平面内人形状投影到另一个平面上
计算公式:
在这里插入图片描述
getPerspectiveTransform( 计算透视变换矩阵
const Point2f src[], 原图像中的三个坐标
const Point2f dst[], 目标图像中的三个像素坐标
int solveMethod = DECOMP_LU 计算透视变换矩阵的方法
);

	计算透视变换矩阵的方法
		DECOMP_LU = 0,			最佳主轴元素的高斯消元法 
		DECOMP_SVD = 1,			奇异值分解法 
		DECOMP_EIG = 2,			特征值分解法 
		DECOMP_CHOLESKY = 3,	Cholesky分解法
		DECOMP_QR = 4,			QR分解法
		DECOMP_NORMAL = 16		使用正规方程公式,可以去前面的标志一起使用


	warpPerspective(							透视变换函数
		InputArray src,							输入图像
		OutputArray dst,
		InputArray M,							3*3的透视变换矩阵
		Size dsize,								输出图像尺寸
		int flags = INTER_LINEAR,				插值方式 
		int borderMode = BORDER_CONSTANT,		像素边界外推方法的标志 
		const Scalar& borderValue = Scalar()	填充边界使用的数值,默认为0
	);

绘制图形

绘制直线

line(						
	InputOutputArray img,		//绘制的图像
	Point pt1,					//起点坐标
	Point pt2,					//终点坐标
	const Scalar& color,		//颜色
	int thickness = 1,			//宽度
	int lineType = LINE_8,		//边界类型
	int shift = 0				//中心坐标的半径数值中的小数点数
);	

边界类型:

	FILLED = -1,   填充型
	LINE_4 = 4, //!< 4-connected line    四连接
	LINE_8 = 8, //!< 8-connected line	8连接
	LINE_AA = 16 //!< antialiased line

绘制圆形

circle(
	InputOutputArray img,		
	Point center,		
	int radius,			半径长度
	const Scalar& color, 
	int thickness = 1,		线的宽度,-1为绘制实心圆
	int lineType = LINE_8,
	int shift = 0
);

绘制椭圆

ellipse(InputOutputArray img, 
	Point center,
	Size axes,
	double angle,			//椭圆旋转的角度
	double startAngle,		起始角度
	double endAngle,		终止角度
	const Scalar& color,
	int thickness = 1,
	int lineType = LINE_8, 
	int shift = 0);

矩形绘制

	rectangle(
		InputOutputArray img,
		Point pt1, 
		Point pt2,
		const Scalar& color, 
		int thickness = 1,
		int lineType = LINE_8, 
		int shift = 0);

绘制多边形

fillPoly(
		InputOutputArray img, 
		const Point** pts,		所有顶点坐标(可以是多重数组,绘制多个多边形)
		const int* npts,		定点数
		int ncontours,			绘制的多边形的个数
		const Scalar& color, 
		int lineType = LINE_8, 
		int shift = 0,
		Point offset = Point()
	);

绘制文字

putText(
	InputOutputArray img, 
	const String& text, 
	Point org,					//文字字符串左下角像素的坐标
	int fontFace, 
	double fontScale, 
	Scalar color,
	int thickness = 1, 
	int lineType = LINE_8,
	bool bottomLeftOrigin = false
);

ROI分割和拷贝

img(
	Range(
		int start,	//区间的开始
		int end;	//区间的结束	
	),
	Range(
		int start,	//区间的开始
		int end;	//区间的结束	
	)
)

Rect_(
	_Tp _x,						//左上角x坐标
	_Tp _y,						//左上角y坐标
	_Tp _width,					//宽
	_Tp _height)				//高

矩阵存储图
在这里插入图片描述
浅拷贝:只拷贝矩阵头
mat1=mat2
深拷贝:拷贝所有内容

cv::copyTo
copyTo(
		InputArray src,
		OutputArray dst, 
		InputArray mask
	);
	
Mat::copyTo
	Mat mat1;
	mat.copyTo(
		OutputArray dst,
		InputArray mask
	) const

图像金字塔

高斯图像金字塔:不断下采样
拉普拉斯金字塔:第k层的高斯图像下采样,再上采样,然后上采样和第k层的高斯图像求和得到拉普拉斯金字塔

pyrDown(		//下采样
		InputArray src, 
		OutputArray dst,
		const Size& dstsize = Size(), 
		int borderType = BORDER_DEFAULT			//填充方式
	);

pyrUp(		上采样
		InputArray src,
		OutputArray dst,
		const Size& dstsize = Size(), 
		int borderType = BORDER_DEFAULT
	);

创建滑动条和鼠标监控

创建滑动条

createTrackbar(
		const String& trackbarname, 
		const String& winname,			//创建滑动条的窗口的名称
		int* value,						//反应当前滑块的位置
		int count,						//最大值
		TrackbarCallback onChange = 0,	//回调函数
		void* userdata = 0				//传递给回调函数的参数
	);

案例代码

Mat img;

void callBack(int value, void*) {
	float a = value / 100;
	Mat img2 = img * a;
	imshow("img", img2);
}

int main()
{
	img = imread("H:/1732413934315.png");
	namedWindow("img");
	imshow("img", img);

	int value = 100;
	createTrackbar(
		"滑动条名称",
		"img",
		&value,
		200,
		callBack,
		0
		);

	waitKey(0);

	return 0;
}

鼠标监控

setMouseCallback(		鼠标时间响应函数
		const String& winname, 
		MouseCallback onMouse, 
		void* userdata = 0
	)

	MouseCallback(
		int event,			鼠标响应事件标志,瞬间动作
		int x, 
		int y, 
		int flags,			鼠标相应标识,长时间的操作
		void* userdata		传递给回调函数的可选参数
	)

	鼠标响应时间标志
	enum MouseEventTypes {
	EVENT_MOUSEMOVE = 0, //!< 鼠标指针再窗口上移动
	EVENT_LBUTTONDOWN = 1, //!<按下鼠标左键
	EVENT_RBUTTONDOWN = 2, //!< 按下鼠标右键
	EVENT_MBUTTONDOWN = 3, //!< 按下鼠标中键
	EVENT_LBUTTONUP = 4, //!< 释放鼠标左键
	EVENT_RBUTTONUP = 5, //!< 释放鼠标右键
	EVENT_MBUTTONUP = 6, //!< 释放鼠标中键
	EVENT_LBUTTONDBLCLK = 7, //!< 双击鼠标左键
	EVENT_RBUTTONDBLCLK = 8, //!< 双击鼠标右键
	EVENT_MBUTTONDBLCLK = 9, //!< 双击鼠标中键
	EVENT_MOUSEWHEEL = 10,//!< 正值表示向前滚动,负值表示向后滚动
	EVENT_MOUSEHWHEEL = 11 //!< 正值表示向左滚动,负值表示向右滚动
	

	鼠标相应标识
	EVENT_FLAG_LBUTTON = 1, //!< 按住左键拖拽
	EVENT_FLAG_RBUTTON = 2, //!< 按住右键拖拽
	EVENT_FLAG_MBUTTON = 4, //!< 按住中键拖拽
	EVENT_FLAG_CTRLKEY = 8, //!< 按下ctrl键
	EVENT_FLAG_SHIFTKEY = 16,//!< 按下SHIFT键
	EVENT_FLAG_ALTKEY = 32 //!< 按下ALT键

normalize(   归一化
	InputArray src, 
	OutputArray dst, 
	double alpha = 0, 
	double beta = 1, 
	int norm_type = NORM_MINMAX, 
	int dtype = -1, 
	InputArray mask = noArray()
);
	NORM_MINMAX: 数组的数值被线性变换到alpha和beta之间(通常是0到1)。
	NORM_L2 : :归一化后的值 = 像素值 / sqrt(所有像素值平方和)
	NORM_INF : 归一化后的值 = 像素值 / 最大绝对值像素值
	NORM_L1 : 归一化后的值 = 像素值 / (所有像素值绝对值的和)

calcHist(     统计图像像素
	const Mat* images,
	int nimages,
	const int* channels, //需要统计哪些区域
	InputArray mask,
	SparseMat& hist, 
	int dims,
	const int* histSize, 
	const float** ranges,		//每个图像通道中灰度值的取值范围
	bool uniform = true,		//直方图是否均匀
	bool accumulate = false		//是否累积统计直方图,是否分别统计每个通道
);

equalizeHist(          直方图均衡化
		InputArray src,		输入图像必须是8UC1
		OutputArray dst
	);


LUTLUT(图像直方图匹配,将图像分布映射为指定分布
	InputArray src, 
	InputArray lut,			变换矩阵
	OutputArray dst
);
	

matchTemplate(
	InputArray image,				只能为8U或32F格式,两个输入图像类型必须相同
	InputArray templ,
	OutputArray result,
	int method,						匹配方法 
	InputArray mask = noArray());
	
匹配方法
TM_SQDIFF = 0,        平方差匹配法 
	TM_SQDIFF_NORMED = 1,	归一化平方差匹配法 
	TM_CCORR = 2,			相关匹配法
	TM_CCORR_NORMED = 3,	归一化相关匹配法 
	TM_CCOEFF = 4,			系数匹配法 
	TM_CCOEFF_NORMED = 5	归一化相关系数匹配法

http://www.kler.cn/a/409185.html

相关文章:

  • vue项目中中怎么获取环境变量
  • 使用树莓派安装shairport-sync使老音响变身AirPlay音响
  • 【SQL】【数据库】语句翻译例题
  • 七天掌握SQL--->第四天:事务处理与并发控制
  • Springboot系列之:创建Springboot项目,Springboot整合MyBatis-plus
  • 通过DataWorks实现MaxCompute跨项目迁移
  • Linux连接网络的三种方式
  • 【JavaEE初阶 — 多线程】定时器的应用及模拟实现
  • 设计模式——拦截过滤器模式
  • ISAAC Gym 7. 使用箭头进行数据可视化
  • 伪数组和真数组
  • java Scanner
  • 【PHP】 环境以及插件的配置,自学笔记(一)
  • 【Ubuntu24.04】服务部署(虚拟机)
  • 微信万能门店小程序系统存在任意文件读取漏洞
  • 中标麒麟部署k8sV1.31版本详细步骤
  • 5.最长回文子串 python
  • Diffusion 和Stable Diffusion的数学和工作原理详细解释
  • 【君正T31开发记录】8.了解rtsp协议及设计模式
  • golang学习6-指针
  • 探索智能时代:从AI生成PPT到自动化未来
  • 【Elasticsearch入门到落地】2、正向索引和倒排索引
  • C++自动化测试:GTest 与 GitLab CI/CD 的完美融合
  • 如何做鸿蒙系统里的App开发需要哪些技术栈
  • Node.js 安装与环境配置详解:从入门到实战
  • 数据结构(顺序队列——c语言实现)