OpenCV使用中的一些函数记录

新推出的OpenCV 4是通过C++ 11标准建立的,因此要求编译器兼容C++ 11标准,所需的CMake至少要是3.5.1版。
OpenCV 4仅支持Visual Studio 2015和2017两个版本

当常数与Mat变量进行数值运算时,运算的结果的类型保留Mat变量的类型

在OpenCV定义的数据类型Vec3x中,x表示基础的数据类型,b为uchar的缩写,s为short的缩写,w为ushort的缩写,d为double的缩写,f为float的缩写,i为int的缩写。

Mat类变量同时也是一个容器变量,因此,Mat类变量拥有迭代器,用于访问Mat类变量中的数据,例如:

cv::MatIterator_<uchar> it = a.begin<uchar>();
for (; it != a.end<uchar>(); it++)
{
	do_something();
}

除图像数据外,有时程序中的尺寸较小的Mat类矩阵、字符串、数组等数据也需要进行保存,这些数据通常保存成XML文件(.xml)或YAML文件(.yml或.yaml)。
OpenCV提供了用于生成和读取XML文件和YAML文件的FileStorage类。
可以使用FileStorage来访问数据中的节点FileNode。

OpenCV中的max()和min()函数,求取两幅图像中的每个像素的较大或较小值,并将其组成一个Mat返回
OpenCV中的bitwise_xx()函数,是对图像中的每个像素,将其转换为二进制数后对二进制数进行操作

OpenCV中的图像截取以及通过=赋值方式获得的都是浅拷贝,只有通过函数copyTo()获得的是深拷贝。

在使用图像金字塔时,由于每次图像的尺寸都缩小为原来的一半,图像尺寸缩小的速度非常快,因此常见的高斯金字塔的层数为3-6层

由于同一物体无论是旋转还是平移,在图像中都具有相同的灰度值,因此直方图具有平移不变性、缩放不变性等优点,可以用来查看图像整体的变化形式,例如图像是否过暗、图像像素灰度值主要集中在哪些范围等。在特定的条件下,也可以利用图像直方图进行图像的识别。
在直方图的使用过程中,一般需要对其进行归一化处理
从一定程度上讲,虽然两幅图像的直方图分布相似不代表两幅图像相似,但两幅图像相似则两幅图像的直方图分布一定相似。

在进行图像卷积时,需要先将模板旋转180°,然后再进行交互计算。OpenCV提供了filter2D()函数用于实现图像和卷积模板之间的卷积,但该函数不会将卷积模板进行旋转,如果卷积模板不对称,则需要手动将模板旋转180°,再调用该函数。
而图像滤波则不需要将模板旋转180°。

图像中的椒盐噪声是由相机成像、图像传输、解码处理等过程产生的黑白相机的亮暗点噪声。
高斯噪声是相机在拍摄时视场较暗且亮度不均匀所产生的,相机长时间工作使得温度过高同样会引起高斯噪声,电路元器件自身噪声和相互影响也会引起高斯噪声。

OpenCV提供了blur()函数用于实现图像的均值滤波,提供boxFilter()函数用于实现方框滤波。方框滤波是均值滤波的一般形式。在均值滤波中,将滤波器中所有的像素值求和后的平均值作为滤波后结果,而方框滤波可以选择不进行归一化,将所有像素值的和作为滤波结果。
OpenCV还提供sqrBoxFilter()函数用于实现对滤波器内每个像素值的平方求和。
OpenCV提供了可以输入两个方向滤波器实现滤波的分离滤波函数sepFilter2D()函数。

当bilateralFilter()中的sigmaSpace参数值大于150时,滤波效果会非常强烈,呈卡通式效果。

OpenCV中的distanceTransform()函数的distanceType参数的值为DIST_L1计算的是街区距离,DIST_L2计算的是欧式距离(欧式距离的掩模尺寸取5效果更为准确),DIST_C计算的是棋盘距离。

OpenCV的形态学操作函数,可以处理的图像矩阵类型有CV_8U,CV_16U,CV_16S,CV_32F,CV_64F
OpenCV还提供了将二值图像细化的函数thinning(),实心圆细化后为一个像素点,圆环细化后仍然是个圆形。

OpenCV提供了直线检测函数。HoughLines()提取直线时无法准确知道图像中直线或者线段的长度,只能得到图像中是否存在符号要求的直线,以及直线的极坐标解析式。HoughLinesP()可以得到图像中满足条件的直线或线段的两个端点的坐标,进而确定直线或线段的位置
前两个函数都是检测图像中是否存在直线,但在实际工程或任务需求中,可能得到的是图像中一些点的坐标而不是一幅完整的图像。因此,OpenCV提供了能够在含有坐标的众多点中寻找是否存在直线的HoughLinesPointSet()函数。
OpenCV提供了利用最小二乘方法拟合直线的fitLine()函数。

OpenCV提供求取轮廓最大外接矩形的boundingRect()函数和求取轮廓最小外接矩形的minAreaRect()函数。寻找轮廓外接最大矩形就是寻找轮廓X方向和Y方向两端的像素,该矩形的长和宽分别与图像的两条轴平行。minAreaRect()获得的是旋转矩形。
有时候用矩形逼近轮廓会造成较大的误差,此时可使用approxPolyDP()求取逼近的多边形轮廓
函数pointPolygonTest()提供计算像素点距离轮廓的最小距离。当measureDist参数为true时,点在轮廓内部时距离为正,点在轮廓外部时距离为负。
有时物体的形状过于复杂,用多边形逼近后处理起来依然较为复杂,此时可使用凸包。

由于Hu矩具有旋转、平移和缩放不变性,因此可以通过Hu矩实现图像轮廓的匹配。

一般来说,离散傅里叶变换对于最佳尺寸的图像处理速度较快,因此常见的方法是在原矩阵的周围增加多层0值像素,以调整图像到最佳尺寸。在实际处理中,使用copyMakeBorder()函数来处理,较好的处理方式是在原图像两侧添加等量的0像素,这样对于变换后的频域图像具有更好的视觉展示效果
根据公式可知,傅里叶变换后的原点位于4个顶点,为了展示,应该通过图像变换,将求得结果的原点调整到图像中心。例如:

// 进行离散傅里叶变换
Mat result;
dft(complex, result);
// 将复数转换为幅值
Mat resultC[2];
split(result, resultC);
Mat amplitude;
magnitude(resultC[0], resultC[1], amplitude);
// 使用对数公式M1 = log(1+M) 保证所有数都大于0
amplitude = amplitude + 1;
log(amplitude, amplitude);
// 重新排列傅里叶图像中的象限,使得原点位于图像中心
int centerX = amplitude.cols / 2;
int centerY = amplitude.rows / 2;
// 分解为4个子区域
Mat Qlt(amplitude, Rect(0, 0, centerX, centerY));
Mat Qrt(amplitude, Rect(centerX, 0, centerX, centerY));
Mat Qlb(amplitude, Rect(0, centerY, centerX, centerY));
Mat Qrb(amplitude, Rect(centerX, centerY, centerX, centerY));
// 交换象限
Mat med;
Qlt.copyTo(med);
Qrb.copyTo(Qlt);
med.copyTo(Qrb);
Qrt.copyTo(med);
Qlb.copyTo(Qrt);
med.copyTo(Qlb);

傅里叶变换可以将两个矩阵的卷积转换成两个矩阵傅里叶变换结果的乘积,通过这种方式可以极大提高卷积的计算速度。但是图像傅里叶变换结果是具有复数共轭对称性的复数矩阵,两个矩阵相乘需要计算对应位置的两个复数的乘积。OpenCV提供了计算两个复数矩阵的乘积的mulSpectrums()函数。

离散余弦变换经常使用在信号处理和图像处理领域中,主要用于对信号和图像的有损数据压缩。离散余弦变换具有能量集中的特性,信号经过变换后能量主要集中在结果的低频部分。
目前dct()函数只支持偶数大小的数组,因此在使用该函数处理数据时,需要将数据填充到指定的尺寸。在实际使用中,最佳尺寸可以通过2*getOptimalDFTSize((N+1)/2)计算得到。

根据积分图像计算规则的不同,可以分为3种主要的积分图像,分别是标准求和积分图像、平方求和积分图像和倾斜求和积分图像。

Grabcut法是重要的图像分割算法,其使用高斯混合模型估计目标区域的前景和背景。
Mean-Shift法是一种基于颜色空间分布的图像分割算法。该算法输出是一个滤色的分色图像,其颜色会渐变,并且细微纹理会变得平滑。OpenCV提供的相应函数是pyrMeanShiftFiltering()。

图像修复技术就是利用图像中损坏区域边缘的像素,即根据像素值的大小以及像素间的结构关系,估计出损坏区域可能的像素排列,从而去除图像中受“污染”的区域。图像修复不但可以去除图像中的划痕,而且可以去除图像中的水印和日期等。

Harris角点主要用于检测图像中线段的端点或者两条线段的交点。
通过Harris角点评价系数的大小不能完全地概况两个特征向量间的大小关系,Shi-Tomas对Harris角点的判定指标进行调整,将特征向量的最小值作为角点评价系数。
OpenCV中使用goodFeaturesToTrack()来检测Shi-Tomas角点。

特征点与角点在宏观定义上相同,都是能够表现图像中局部特征的像素点,但是特征点区别于角点的是其具有能够唯一描述像素点特征的描述子。通常特征点由关键点和描述子组成。
特征点匹配由于数据量小、匹配精确而被广泛应用在三维重建、视觉定位、运动估计、图像配准等领域。
OpenCV提供了快速最近邻搜索库FLANN用于实现特征点的高效匹配。
为了更好的提高特征点匹配精度,我们可以使用RANSAC算法,在FLANN匹配的基础上,改进匹配准确度。
OpenCV使用findHomography()函数计算RANSAC的匹配

单目视觉是指通过单一的相机成像对环境进行观测和测量的视觉系统。一个精确的内参系数是通过单目相机对观景进行观测和测量的首要保证。虽然在制作相机时可以生产指定标准的元器件并按照指定的尺寸装配摄像头,通过这些标准可以计算出摄像头的内参。但不幸的是,由于工艺水平有限,元器件尺寸与标准值存在误差,同时装配位置也会与期望值也有偏差,使得真实的内参系数与理论值具有一定偏差。另外,由于振动原因,在摄像头使用过程中,镜头可能产生位移或者松动,使得内参系数再次发生改变。

检测视频中移动的物体并对移动物体进行跟踪的主要方法有:差值法、均值迁移法(meanShift和camShift)和光流法。
差值法直接计算像素值差值,容易受到光照、噪声等干扰的影响,因为有些像素值发生改变并不是由移动的物体引起,因此在计算差值后需要进一步处理,以减少噪声的影响,如二值化、开闭运算等。

光流法是利用图像序列中像素的变化寻找前一帧图像和当前帧图像间的对应关系,进而得到两帧图像间物体运动状态的一种方法。光流法具有两个很强的前提假设:第一,同一物体在图像中对应的像素亮度不变。第二要求两帧图像必须具有较小的运动。较小运动的假设使得光流法主要应用在视频数据的目标跟踪,当视频的帧率过小或者物体移动过快时,也会影响光流法的跟踪效果。
光流法要求像素移动较小距离,但是有时得到的连续图像中像素的移动距离较大,此时需要采用图像金字塔来解决大尺度移动的问题。通过构建图像金字塔,可以缩小图像的尺寸,进而解决物体移动较快的问题。
根据计算光流速度的像素点数目,光流法可以分为稠密光流法和稀疏光流法。稠密光流法(主要用于相机固定的视频数据的目标跟踪)是指计算光流时图像中所有像素均要使用,稀疏光流法是指计算光流时只使用部分像素点。
calcOpticalFlowFarneback()函数计算稠密光流,其输出是包含x和y方向位移的双通道图像矩阵。使用较大的均值窗口对噪声具有较好的鲁棒性,为快速运动提供更好的检测机会,但是会产生更模糊的光流运动场。在求取过程中使用高斯滤波器比使用方框滤波器的结果更为准确,但处理时间会更长。
当使用光流法时,可设置当位移变化较小时不跟踪目标,即设置运动速度为0,例如:

// 判断角点是否移动,如果不移动,则删除
size_t i, k;
for (i=k=0; i<nextPts.size(); i++)
{
	// 距离与状态测量
	double dist = abs(prevPts[i].x - nextPts[i].x) + \
	abs(prevPts[i].y - nextPts[i].y);
	if (status[i] && dist>2)
	{
		prevPts[k] = prevPts[i];
		initPoints[k] = initPoints[i];
		nextPts[k++] = nextPts[i];
		circle(nextframe, nextPts[i], 3, Scalar(0, 255, 0), -1, 8);
	}
}

在使用OpenCV的机器学习模块时,通常将数据保存为3个文件,分别是保存模型参数的yml文件,保存训练数据的文件(图片格式或yml格式)和标记文件
保存模型参数时,可使用训练器的save函数。例如:

Ptr<KNearset> knn = KNearest::create();
knn->setDefaultK(5);
knn->setIsClassifier(true);
knn->train(tData);
knn->save("knn_model.yml");

加载训练好的模型时,使用Algorithm类额load()函数。例如:

Ptr<KNearest> knn = Algorithm::load<KNearest>("knn_model.yml");

载入保存为图像格式的训练和标记数据时,可使用:

Mat data = imread("train_data.png", IMREAD_ANYDEPTH);
Mat label = imread("label_data.png", IMREAD_ANYDEPTH):

对于深度学习,则提供dnn::readNet()函数用于读取训练好的模型。其支持的深度学习模型格式为
Caffe:模型文件格式:.caffemodel,配置文件格式:.prototxt
TensorFlow:.pb,.pbtxt
Torch:.t7|.net,–
Darknet:.weights,.cfg

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值