Opencv 学习笔记(二)

第二篇:介绍具体函数用法

图片读取、保存

  • namedWindow():使用该函数创建一个空图片的窗口时,需要手动释放窗口资源(不推荐这种用法)
	// imread()
    Mat  pic = imread("图片路径",  读取方式_可缺省);  // 默认读取原图

	// imshow()
	imshow("窗口名", Mat对象名);

	// imwrite()
	imread("图片存储路径",  写入方式_可缺省);  

视频操作

  • VideoCapure 、VideoWrite
  • VideoCapure 是一个类,对视频相关的操作进行了封装,类似于CWnd 对 HWND 的封装
  • 可以先定义类对象 》打开视频 》视频的各种属性和操作就保存在类对象的成员中 》通过成员函数访问视频属性。
  • 其资源的释放由类自己管理,也可以手动管理:类对象.release();
  • 要注意不同 opencv 版本中,成员函数的参数写法。
	VideoCapture video;
	video.open("视频路径"); // video.open(1); 表示从摄像头读取数据
	// 判断视频是否加载成功
	if (!video.isOpened())
	{
		cout << "打开视频失败" << endl;
	}else
	{
		cout << "打开视频成功" << endl;
		
		// 获取视频属性
		cout << video.get(CAP_PROP_FRAME_COUNT) << endl;

		// 读取视频:视频 》 图片
		while(1)
		{
			Mat flame;
			video >> flame;
			// 如果图片读取结束,推出循环
			if(flame.empty())
			{
				break;
			}
			
			// 添加对每一帧图像的处理代码:
			...
			...
			// 以下为显示原视频的代码:
			imshow("播放视频", frame); // 显示当前帧
			uchar kdown = waitKey(1000 / video.get(CAP_PROP_FPS));// 控制两帧之间的时间间隔,从而实现快放和慢放,其中video.get(CAP_PROP_FPS)表示获得视频帧率,即原视频中每秒的图片张数。
			// 如果在播放过程中,键盘按下 q ,则退出播放视频
			if(kdown == 'q')
			{
				break;
			}
		}
	}

图像颜色模型:BGR、HSV

  • BGR 模型:色彩空间是一个立方体
    在这里插入图片描述

BGR 模型数据类型转换
【0~255】 CV_8UC3
【0~1】CV_32FC3:小于0表示全黑,大于1表示全白
【0~1】CV_64FC3:小于0表示全黑,大于1表示全白

Mat a(3, 3, CV_8UC3);
a.convertTo(b, CV_32F, 1/255.0, 0); // convertTo 对Mat对象数据处理
b表示转换后的Mat对象
CV_32F:转换后的数据格式
1/255.0:缩放系数
0:平移系数

  • HSV 模型:色彩空间是一个锥形:锥形横截面(圆)的旋转角度、径向长度、锥深度,依次表示色调、饱和度、亮度
    在这里插入图片描述

  • GRAY 灰度模型:只有一种颜色灰色
    在这里插入图片描述

  • 3种颜色空间模型互相转换

	void cv::cvtColor(Mat src, Mat gray, 转换格式)
	// 特别注意:
	// COLOR_BGR2GRAY,默认选用这个!因为默认是 BGR 格式
	// COLOR_RGB2GRAY
	// 二者的区别

多通道分离、融合

split 、merge,通过通道分离、融合可以验证:opencv默认存储顺序是 B、G、R,即第一个通道存储的是蓝色的数据

	void cv::split(Mat src, Mat * dst);  
	// src :多通道图像; 
	// dst:向量形式的单通道图像,可以是 Mat img[3]

	void cv::merge(Mat * src, int 通道数, Mat dst);  
	void cv::merge(vevtor<Mat> src, Mat dst);  
	// src:向量形式的单通道图像, 每个分量的大小和数据类型必须相同 
	// dst:合并后的Mat

像素运算

	// 按照每个像素一一比较,将比较结果存储在 dst 中
	// 灵活运用 黑白掩码图像,就可以实现对图片内容的遮盖
	void cv::min(Mat src1, Mat src2, Mat dst); 
	void cv::max(Mat src1, Mat src2, Mat dst); 
	
	// 最大值最小值寻址:掩码作用???
	// 只能处理单通道图像
	void cv::minMaxLoc( Mat     src, 
						doube * pSaveMin, 
						doube * pSaveMax, 
						Point * pSaveMinLoc = Null, 
						Point * pSaveMaxLoc = Null, 
						Mat     mask = 缺省
						); 

	// 逻辑运算
	void cv::bitwise_or(Mat  src1,  Mat  src2, Mat  dst, Mat  mask = 缺省); 
	void cv::bitwise_xor(Mat  src1, Mat  src2, Mat  dst, Mat  mask = 缺省); 
	void cv::bitwise_not(Mat  src,  Mat  dst,  Mat  mask = 缺省); 
	void cv::bitwise_and(Mat  src1, Mat  src2, Mat  dst, Mat  mask = 缺省); 

图像二值化

  • 简单来说就是对图像像素值按照某一标准划分为两个数值,非此即彼。
	// 固定阈值
	double cv::threshold(); 
	
	// 自适应阈值
	// 本质是将原图切割成多个子图,对每个子图进行二值化处理
	double cv::adaptiveThreshold(); 					

type 还可以位或 大津法 和 三角形法,如:

LUT 查找表

  • 本质是一个映射表,是 二值化多值化 的一个推广
	void cv::LUT(Mat   src,   // 只能是 CV_8U
				 Mat   lut,   
				 Mat   dst,   // 类型与 lut 相同
				);
	// lut 查找表可以是单通道,也可以是多通道(与src相同)
	// lut 的每个通道必须是 1*256 的一个矩阵,对应0-255个像素值 所对应的映射值
	// 这样就可以定向过滤、调整某些灰度的像素,
	// 例如,将凸显中高亮的部分(>250)全部调整为 250,而其他的不变,那么 lut 就是 [0 1 2 ...249 250 ... 250 250]

缩放、翻转、拼接

  • 图像插值
    根据已有像素估计位置像素:最邻近插值、线性插值、双线性插值
  • 图像缩放
	void cv::resize(Mat   src,   
				    Mat   dst, 
				    Size  dsize,    // 缩放后尺寸
				    double fx = 0,  // 缩放后 x 轴比例
				    double fy = 0,  // 缩放后 y 轴比例
				    int   interpolation = INTER_LINEAR  // 标记了插值方式,默认双线性插值
				   );
				   // 如果 fx fy 与 dsize 冲突,则以 dsize 为准
				   INTER_AREA     缩小的时候用?
				   INTER_NEAREST  最近邻
				   INTER_LINEAR   双线性
				   INTER_CUBIC    双三次
				   
  • 图像翻转
	void cv::flip(Mat   src,   
				  Mat   dst, 
				  int   flipflag // 翻转方式:>0 绕y轴翻;=0 绕x轴翻;<0 现后绕x、y轴翻;
				 );
  • 图像拼接
	void cv::hconcat(Mat src1, Mat src1, Mat dst);
	void cv::vconcat(Mat src1, Mat src1, Mat dst);

仿射变换(三点变换)

  • 仿射 = 平移 + 缩放 + 旋转 + 翻转 + 错切
  • 也就是图片在二维空间上的变换
    X = [x, y]’
    仿射过程就是线性变换过程
    T = A* X + B
    仿射变换矩阵:
    M = [A B]
	void cv::warpAffine(Mat   src,   
				  		Mat   dst, 
				  		Mat   M,     // 仿射变换矩阵, 在二维平面上,只能是 2*3 大小 
				  		Size  dsize, // 输出图像尺寸
				  		int   flags, // 图像尺寸变化的时候的插值方式
				  		int   borderMode, // 因旋转而多出的部分图像像素外推方法
				  		const Scalar & borderValue, // 因旋转而多出的部分图像像素制定填充值(默认0)
				 		);
	// borderMode、borderValue 都有指定的宏来标记具体方法			 
  • 旋转 是一种特殊的仿射变换,没有提供专门的旋转函数,提供了计算 仿射矩阵 M 的函数
	// 计算旋转变换仿射矩阵
	Mat cv::getRotation2D(Point2f center,   // 旋转中心,浮点型
				          double  angle,    // 旋转角,单位 度,逆时针为正
				          double  scale		// 两个轴的旋转缩放比例,缺省为 1
				          );	 
  • 获得仿射变换矩阵
	Mat cv::getAffineTransform(const Point2f * src[],  // 原图中的三个坐标
	 						   const Point2f * dst[]); // 目标图中的三个坐标	 

透视变换(四点变换)

即三维图片在空间上的变换

  • 获得透视变换矩阵
	Mat cv::getPerspectiveTransform(const Point2f * src[],  // 原图中的 4 个坐标,浮点数
	 						        const Point2f * dst[]   // 目标图中的 4 个坐标
	 						        int   solveMethod = DECOMP_LU
									); 	 
  • 透视变换函数
	void cv::warpPerspective(Mat   src,   
				  		     Mat   dst, 
				  			 Mat   M,     // 投射变换矩阵, 只能是 3*3 大小 
				  			 Size  dsize, // 输出图像尺寸
				  			 int   flags, // 图像尺寸变化的时候的插值方式
				  			 int   borderMode, // 因旋转而多出的部分图像像素外推方法
				  			 const Scalar & borderValue, // 因旋转而多出的部分图像像素制定填充值(默认0)
				 			 );
	// borderMode、borderValue 都有指定的宏来标记具体方法			 

在图像中绘制内容

  • 直线、圆、椭圆、矩形、多边形、文字
  • line()
  • circle()
  • putText()

图像截取

	Range(int  iRow, int iCol)
	
	Rect_(int x_lefttop, 
          int y_lefttop, 
          int width,
          int height)
	
	// 深拷贝:
	cv::copyTO()
	Mat::copyTO()
	Mat::clone

高斯图像金字塔_(略)

作用:???

	void cv::pyrDown(Mat src,   
				     Mat dst,   
				     Size dsize,  // 输出图像尺寸,可缺省
				     int borderType  // 像素边界外推法的标志   
				    );	

拉普拉斯金字塔_(略)

	void cv::pyrUp(Mat src,   
				   Mat dst,   
				   Size dsize,  // 输出图像尺寸,可缺省
				   int borderType  // 像素边界外推法的标志   
				  );	

创建滑动条,调整图片参数

	// 1. 定义滑块变量
	int value	
	
	// 2. 定义回调函数
	void barCallBack(int value, void * p)
	{
		// To do...
	}
	
	// 3. 按照以下格式创建滚动条 
	int cv::createTrackbar(const String & trackName,// 滑动条名称
						   const String & WndName,  // 窗口名称
						   int * value,    // 滑动条的位置数值由此数定义
						   int   countMax, // 滑动条最大数值
						   void onChange(int value, void *), // 回调函数名
						   void * data  // 传递给回调函数的参数(缺省)					  
						  )			
	// 说明:函数 createTrackbar 内部已经包含了“消息循环”,不需要
	// 额外定义循环						  	 

鼠标时间响应函数_(略)

	void cv::setMouseCallback(const String & WndName,// 响应窗口名
							  onMouse(), // 鼠标消息响应函数名
							  void * data  // 传递给回调函数的参数(缺省)		
						      )	
	MouseCallback(具体用法及其参数略过,
	              使用的时候再详细了解
	)

绘制统计直方图

  • 本质是统计图片中各个像素的分布情况,
  • 通过对这部分的图像进行处理,就可以实现对图像特定部分进行处理
  • 数据匹配
  • 图片匹配
  • 函数:
	void cv::calcHist(省略)	
	// 该函数只输出统计数据,并不提供绘图功能
	// 通常就是用之前讲到的,recTangle 函数画图

直方图均衡化

  • 先获得直方图(图像灰度分布)
  • 只能处理灰度图(单通道,CV_8UC1)
  • 如果图片中部分过暗,隐藏了部分信息,需要提高这部分亮度,而不增加已经很亮的部分的亮度;反之也是如此。
  • 均衡化最大作用就是:局部调整图片中过暗、过亮的部分,使图片中的信息更好的显示出来,而这种调整方式就涉及到部分数学知识,也就是数据处理
  • 在直方图上体现为:将瘦高且偏左或偏右的灰度分布曲线,用数学的方式调整为宽胖且居中的曲线
	void cv::equalizeHist(省略)	

直方图匹配

  • 人为指定/按照指定图片 中像素的分布模式,来对需要处理的图像进行均衡化处理
  • 整个过程没有现成的接口函数,需要手动编写函数
  • 在直方图上体现为:让灰度分布曲线重心集中在某一个地方
  • 使用累计概率
  • 让一张图的灰度图分布规律模仿另一张图的分布规律
  • 即,按照看起来舒服的图的样子调整

图像模板匹配

  • 在目标图像中搜索与模板图像一致的部分
	void cv::matchTemplate(省略)
	// 仅针对 CV_8U 和 CV_32F	
	// 获得图像中最大最小位置、最大最小值
	void cv::minMaxLoc(省略)

图像卷积

  • 常用于 图像边缘检测、去除噪声、图像压缩等过程
  • 卷积核对所有像素进行操作(前提是扩充一圈像素)
  • 卷积核要进行180°旋转 和 归一化(加权平均)
  • 之所以具备滤波的功能,是因为 卷积核 的操作实际上是对像素周围的所有点(卷积核一般是技术的正方形)进行加权平均
	// 从函数名来看,函数功能是进行二维滤波
	void cv::filter2D(省略)

图像噪声的产生

  • 椒盐噪声:随机产生的脉冲噪声,噪声点非黑即白

  • 高斯噪声:噪声的分布密度服从高斯分布噪声的亮度不同

  • 椒盐噪声没有特定的函数来生成模拟,只能随机函数来模拟

	double cvflann::rand_double(省略)
	int    cvflann::rand_int(省略)	

Q :噪声有什么用??

  • 高斯噪声提供了函数:
	void cv::RNG::fill(省略)

线性滤波

  • 滤波效果是使图片变得模糊,边界不清晰

均值滤波与卷积类似,对像素中每一个像素位置进行处理,滤波器是一个 全1的奇数方阵/方阵和

	// 均值滤波的函数
	// 适用于单通道所有数据类型
	void cv::blur()

方框滤波与均值滤波等价,不同之处在于,它不强制归一化,包含了均值滤波

	// 该函数通过设置参数 包含了 blur()
	void cv::boxFilter()

高斯滤波 滤波器可以不是方的,但必须是奇数,元素中心对称,数值按照高斯分布,中心位置值最大,所有元素和为1; 即是一种加权平均,中心权重最大, 其他地方权重负荷高斯分布

	void cv::GaussianBlur()

非线性滤波

  • 中值滤波 取滤波器的中值,如果滤波器中的像素分布中出现了一个异常的较大值或者较小值,就可以很好的滤除最大值、最小值,也就是椒盐噪声
  • 滤波器必须是奇数
	void cv::medianBlur()

线性滤波的可分离性

就是将原来矩形的滤波器分解成两个向量的乘积的形式,用两次滤波来代替原来的一次滤波

	void cv::sepFilter2D()

边缘检测

图像的像素灰度值的梯度最大的地方,定义为边缘
所谓的边缘检测就是求解最大的梯度,
而求解梯度的过程就要用到上述的滤波、卷积的计算过程
实际上就是矩阵运算

以下算子本质是检测的矩阵——滤波器矩阵不同

  • Sobel() 边缘检测算子获得边缘信息过多,包括虚假边缘
	void cv::Sobel()
  • Scharr() 边缘检测算子 (基于Sobel算子,在较小梯度的边缘检测的时候更有优势) 更多细节
	void cv::Scharr()

以上两个算子都是调用getDerivKernels(略) 函数实现的,是两种特殊的情况,他们都是依次检测X、Y方向的边缘后叠加获得整幅图的边缘,
特点是:X方向更容易检测出Y反向的边缘,Y方向更容易检测出X反向的边缘,这就造成倾斜的边界被重复检测,当两个结果叠加的时候,这种倾斜的边缘亮度过高。

  • Laplacian算子在一个识别过程中,对整幅图进行提取边缘,不用检测两次,由于使用了两次求导,更容易收到噪声的影响。它可以是彩色图。Laplacian() 函数的计算结果可能有负数,需要计算绝对值,用函数 convertScaleAbs()
	void cv::Laplacian()
  • Canny算子 对 Sobel算法进行优化,滤除虚假边缘(弱边缘),保留真实(强边缘)
	void cv::Canny()

连通域分析(连通域分割)

连通域的概念:4邻域, 8邻域

  • 1 通常先二值化处理
  • 一层一层像素的分类,最后找到不同的连通域
	// 函数1 :
	// 只能处理 单通道 CV_8U 数据类型
	int cv::connectedComponents()
	
	// 函数2: 功能扩展
	// 1. 输出每个连通域最大外边框的坐标、高宽、面积
	// 2. 输出质心坐标
	int cv::connectedComponentsWithStats()	

图像距离判断

欧氏距离、街区距离、棋盘距离
具体怎么应用???

图像腐蚀

  • 用于去除图像中的微小物体
  • 分离较近的两个物体
  • 处理二值化图像
  • 简单理解就是设计一个结构元素,如果在原图像中能完全覆盖该结构元素,就保留该像素点,
  • 实现的效果就是把粗线条变成细线条
	// 生成结构元素函数
	Mat cv::getStructingElement()
	// 图像腐蚀操作函数
	void cv::erode()

图像膨胀

  • 与腐蚀对应
  • 腐蚀是删除像素
  • 膨胀是填充像素(不增加图幅)
  • 也是需要用到结构元素
	// 生成结构元素函数
	Mat cv::getStructingElement()
	// 图像腐蚀操作函数
	void cv::dilate()

图像形态学操作(运用膨胀和腐蚀产生其他更多操作)

开运算 = 腐蚀 + 膨胀
  • 可以去除图像中的噪声,消除较小连通域,保留较大连通域
  • 腐蚀去除噪点(小连通域),膨胀还原大小(保留大连通域)
闭运算 = 膨胀 + 腐蚀
  • 可以去除图像中的小空洞,平滑物体轮廓,连接两个临近的连通域
形态学梯度 = 原图膨胀结果 - 原图腐蚀结果
  • 得到轮廓梯度(获得轮廓)
  • 使用相同结构元素操作
顶帽运算 = 原图 - 原图开运算(???)
  • 分离比邻近点亮一些的斑块(提取原图中分散的,较小的区域)
  • 使用相同结构元素操作
黑帽运算 = 原图闭运算 - 原图(???)
  • 分离比邻近点暗一些的斑块(提取原图中分散的,较小的区域)
击中击不中变换
  • 找到与结构元素完全相同的布局
	// 以上的通用接口函数,包括基础的膨胀与腐蚀
	void cv::morphologyEx()

图像细化

  • 将图像中的宽线条细化未单像素的过程,即骨架化,删除部分像素
	// 扩展的 opencv 库函数
	void cv::ximgproc::thinning()

轮廓检测、信息提取

  • 用4个元素的数组来表示各个轮廓的层级关系 :[右边轮廓索引, 左边轮廓索引, 下边轮廓索引, 上边轮廓索引
	findContours()
	drawContours()
	contourArea()
	arcLenth()

轮廓外接多边形(拟合轮廓)

  • 将图像的轮廓拟合成凹凸多边形
	Rect cv::boundingRect()     // 矩形拟合:返回轮廓外接正交矩形四个顶点
	RotateRect cv::minAreaRect()  // 矩形拟合:返回旋转矩形顶点
	void cv::approxPolyDP()       // 多边形拟合

凸包检测

  • 将图像的轮廓拟合成凸多边形
	void cv::convexHull() 

直线检测

  • 霍夫变换:二维直角坐标系中(原空间),通过一个点的直线族,表示为: y0 = k*x0 + b, 映射到 k 和 b 的坐标系中(参数空间),就表示一条直线,这就形成了 点—>线 的映射关系,由于 y=kx+b 不能映射垂直的直线,所以改进为用角度和距离这种方式映射,但不影响对原理的理解。
  • 如果将原空间图像中每个非0点都映射成参数空间的一条直线,如果将参数空间离散化,映射的直线就是一系列方格,并在直线所在的方格上标记一次;
  • 原空间中一条线中的两个点所表示的两个直线族,在参数空间中表示两条相交的直线;那么在参数空间中,就有一个点被重复标记了一次,如果参数空间中某个点被标记了足够多的次数,那么说明参数空间中,通过该点的所有直线 所对应的 原空间中的点都在一条直线上。
	void cv::HoughLines() 
	void cv::HoughLinesP() 	

点集拟合

  • 将离散的数据点进行拟合成确定的形状,允许拟合后的形状不通过数据点
  • 直线拟合、圆形拟合、三角形拟合
  • 用于数据处理
	// 直线拟合
	void cv::fitLine()
	// 三角形拟合
	void cv::minEnclosingTriangle()
	// 圆形拟合
	void cv::minEnclosingCircle() 

QR二维码识别(略)

积分图像

  • 对积分点左上角的矩形区域 求和/平方和
  • 操作目的:加速图像处理过程,减少计算量
	void cv::integral()

图像分割

  • 漫水填充法
	int cv::floodFill()
  • 分水岭法
	void cv::watershed()

角点检测

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值