【OpenCV】矩阵和图像的操作总结查询
矩阵和图像操作
表3-3列出了一些操作矩阵图像的函数,其中的大部分对于图像处理非常有效。它们实现了图像处理中的基本操作,例如对角化、矩阵变换以及一些更复杂的诸如计算图像的统计操作。 【47】
表3-3:矩阵和图像基本操作
函数名称 |
描述 |
cvAbs |
计算数组中所有元素的绝对值 |
cvAbsDiff |
计算两个数组差值的绝对值 |
续表
函数名称 |
描述 |
cvAbsDiffS |
计算数组和标量差值的绝对值 |
cvAdd |
两个数组的元素级的加运算 |
cvAddS |
一个数组和一个标量的元素级的相加运算 |
cvAddWeighted |
两个数组的元素级的加权相加运算(alpha融合) |
cvAvg |
计算数组中所有元素的平均值 |
cvAvgSdv |
计算数组中所有元素的绝对值和标准差 |
cvCalcCovarMatrix |
计算一组n维空间向量的协方差 |
cvCmp |
对两个数组中的所有元素运用设置的比较操作 |
cvCmpS |
对数组和标量运用设置的比较操作 |
cvConvertScale |
用可选的缩放值转换数组元素类型 |
cvConvertScaleAbs |
计算可选的缩放值的绝对值之后再转换数组元素的类型 |
cvCopy |
把数组中的值复制到另一个数组中 |
cvCountNonZero |
计算数组中非0值的个数 |
cvCrossProduct |
计算两个三维向量的向量积(叉积) |
cvCvtColor |
将数组的通道从一个颜色空间转换另外一个颜色空间 |
cvDet |
计算方阵的行列式 |
cvDiv |
用另外一个数组对一个数组进行元素级的除法运算 |
cvDotProduct |
计算两个向量的点积 |
cvEigenVV |
计算方阵的特征值和特征向量 |
cvFlip |
围绕选定轴翻转 |
cvGEMM |
矩阵乘法 |
cvGetCol |
从一个数组的列中复制元素 |
cvGetCols |
从数据的相邻的多列中复制元素值 |
cvGetDiag |
复制数组中对角线上的所有元素 |
cvGetDims |
返回数组的维数 |
cvGetDimSize |
返回一个数组的所有维的大小 |
cvGetRow |
从一个数组的行中复制元素值 |
cvGetRows |
从一个数组的多个相邻的行中复制元素值 |
cvGetSize |
得到二维的数组的尺寸,以CvSize返回 |
cvGetSubRect |
从一个数组的子区域复制元素值 |
cvInRange |
检查一个数组的元素是否在另外两个数组中的值的范围内 |
cvInRangeS |
检查一个数组的元素的值是否在另外两个标量的范围内 |
续表
函数 名称 |
描述 |
cvInvert |
求矩阵的转置 |
cvMahalonobis |
计算两个向量间的马氏距离 |
cvMax |
在两个数组中进行元素级的取最大值操作 |
cvMaxS |
在一个数组和一个标量中进行元素级的取最大值操作 |
cvMerge |
把几个单通道图像合并为一个多通道图像 |
cvMin |
在两个数组中进行元素级的取最小值操作 |
cvMinS |
在一个数组和一个标量中进行元素级的取最小值操作 |
cvMinMaxLoc |
寻找数组中的最大最小值 |
cvMul |
计算两个数组的元素级的乘积 |
cvNot |
按位对数组中的每一个元素求反 |
cvNorm |
计算两个数组的正态相关性 |
cvNormalize |
将数组中元素进行规一化 |
cvOr |
对两个数组进行按位或操作 |
cvOrS |
在数组与标量之间进行按位或操作 |
cvReduce |
通过给定的操作符将二维数组约简为向量 |
cvRepeat |
以平铺的方式进行数组复制 |
cvSet |
用给定值初始化数组 |
cvSetZero |
将数组中所有元素初始化为0 |
cvSetIdentity |
将数组中对角线上的元素设为1,其他置0 |
cvSolve |
求出线性方程组的解 |
cvSplit |
将多通道所组分割成多个单通道数组 |
cvSub |
两个数组元素级的相减 |
cvSubS |
元素级的从数组中减去标量 |
cvSubRS |
元素级的从标量中减去数组 |
cvSum |
对数组中的所有元素求和 |
cvSVD |
二维矩阵的奇异值分解 |
cvSVBkSb |
奇异值回代计算 |
cvTrace |
计算矩阵迹 |
cvTranspose |
矩阵的转置运算 |
cvXor |
对两个数组进行按位异或操作 |
cvXorS |
在数组和标量之间进行按位异或操作 |
cvZero |
将所有数组中的元素置为0 |
cvAbs,cvAbsDiff和cvAbsDiffS
cvAdd,cvAddS, cvAddWeighted和alpha融合
cvAddWeighted()函数同cvAdd()类似,但是被写入dst的结果是经过下面的公式得出的:
这个函数可用来实现alpha 融合 [Smith79; Porter84];也就是说,它可以用于一个图像同另一个图像的融合,函数的形式如下:
可以通过设置α从0到1区间取值,β = 1 – α,γ为0,将前面公式转换为标准alpha融合方程。这就得出下式:
例3-14:src2中alpha融合ROI以(0,0)开始,src1中ROI以(x,y)开始
//alphablend <imageA> <image B> <x> <y> <width><height>
intmain(int argc, char** argv)
if( argc == 9 && ((src1=cvLoadImage(argv[1],1)) != 0
)&&((src2=cvLoadImage(argv[2],1)) != 0 ))
double alpha = (double)atof(argv[7]);
double beta = (double)atof(argv[8]);
cvSetImage ROI(src1, cvRect(x,y,width,height));
cvSetImageROI(src2, cvRect(0,0,width,height));
cvAddWeighted(src1, alpha, src2, beta,0.0,src1);
cvNamedWindow( "Alpha_blend", 1 );
cvShowImage( "Alpha_blend", src1 );
图3-4:一个小孩的脸被alpha融合到一只猫的脸上
cvAnd和cvAndS
尽管支持所有的数据类型,但是对于cvAnd()来说,src1和src2要保持相同的数据类型。如果元素都是浮点型的,则使用该浮点数的按位表示。 【52】
cvAvg
cvAvg()计算数组arr的平均像素值,如果mask为非空,那么平均值仅由那些mask值为非0的元素相对应的像素算出。
cvAvgSdv
此函数同cvAvg()类似,但除了求平均,还可以计算像素的标准差。
cvCalcCovarMatrix
表3-4:cvCalcCovarMatrix()可能用到的标志参数的值
标志参数的具体标志值 |
意义 |
CV_COVAR_NORMAL |
计算均值和协方差 |
CV_COVAR_SCRAMBLED |
快速PCA“Scrambled”协方差 |
CV_COVAR_USE_AVERAGE |
输入均值而不是计算均值 |
CV_COVAR_SCALE |
重新缩放输出的协方差矩阵 |
在所有情况下,在vects中是OpenCV指针数组(即一个指向指针数组的指针),并有一个指示多少数组的参数count。在所有情况下,结果将被置于cov_mat,但是avg的确切含义取决于标志的值(参见表3-4)。
标识CV_COVAR_NORMAL和CV_COVAR_SCRAMBLED是相互排斥的;只能使用其中一种,不能两者同时使用。如果为CV_COVAR_NORMAL,函数便只计算该点的均值和协方差。
因此,标准的协方差由长度为n的m个向量计算,其中被定义为平均向量的第n个元素,由此产生的协方差矩阵是一个n ×n矩阵, 比例z是一个可选的缩放比例,除非使用CV_COVAR_SCALE标志,否则它将被设置为1。 【54】
如果是CV_COVAR_SCRAMBLED标志,cvCalcCovarMatrix ()将如下计算:
这种矩阵不是通常的协方差矩阵(注意转置运算符的位置),这种矩阵的计算来自同样长度为n的m个向量,但由此而来的协方差矩阵是一个m×m矩阵。这种矩阵是用在一些特定的算法中,如针对非常大的向量的快速PCA分析法(人脸识别可能会用到此运算)。
如果已知平均向量,则使用标志CV_COVAR_USE_AVG,在这种情况下,参数avg用来作为输入而不是输出,从而减少计算时间。
最后,标志CV_COVAR_SCALE用于对计算得到的协方差矩阵进行均匀缩放。这是前述方程的比例z,同标志CV_COVAR_NORMAL一起使用时,应用的缩放比例将是1.0 /m(或等效于1.0/count)。如果不使用CV_COVAR_SCRAMBLED,那么z的值将会是1.0/n(向量长度的倒数),cvCalcCovarMatrix()的输入输出矩阵都应该是浮点型,结果矩阵cov_mat的大小应当是n×n 或者 m×m,这取决于计算的是标准协方差还是scrambled的协方差。应当指出的是,在vects中输入的“向量”并不一定要是一维的;它们也可以是两维对象(例如图像)。
cvCmp和cvCmpS
这两个函数都是进行比较操作,比较两幅图像相应的像素值或将给定图像的像素值与某常标量值进行比较。cvCmp()和cvCmpS()的最后一个参数的比较操作符可以是表3-5所列出的任意一个。 【55】
表3-5:cvCmp()和cvCmpS()使用的cmp_op值以及由此产生的比较操作
cmp_op的值 |
比较方法 |
CV_CMP_EQ |
(src1i == src2i) |
CV_CMP_GT |
(src1i > src2i) |
CV_CMP_GE |
(src1i >= src2i) |
CV_CMP_LT |
(src1i < src2i) |
CV_CMP_LE |
(src1i <= src2i) |
CV_CMP_NE |
(src1i != src2i) |
表3-5列出的比较操作都是通过相同的函数实现的,只需传递合适的参数来说明你想怎么做,这些特殊的功能操作只能应用于单通道的图像。
这些比较功能适用于这样的应用程序,当你使用某些版本的背景减法并想对结果进行掩码处理但又只从图像中提取变化区域信息时(如从安全监控摄像机看一段视 频流)。
cvConvertScale
cvConvertScale()的第二个功能是对图像数据执行线性变换。在转换成新的数据类型之后,每个像素值将乘以scale值,然后将shift值加到每个像素上。
至关重要的是要记住,尽管在函数名称中“Convert”在“Scale”之前,但执行这些操作的顺序实际上是相反的。具体来说,在数据类型转变之前,与scale相乘和shift的相加已经发生了。 【56】
cvConvertScaleAbs
cvCopy
cvCountNonZero
int cvCountNonZero( const CvArr* arr );
cvCountNonZero()返回数组arr中非0像素的个数。
cvCrossProduct
cvCvtColor
转换代码 解释 |
|
CV_BGR2RGB CV_RGB2BGR CV_RGBA2BGRA CV_BGRA2RGBA |
在RGB或BGR色彩空间之间转换(包括或者不包括alpha 通道) |
CV_RGB2RGBA CV_BGR2BGRA |
在 RGB或BGR图像中加入alpha 通道 |
CV_RGBA2RGB CV_BGRA2BGR |
从 RGB或BGR图像中删除alpha 通道 |
CV_RGB2BGRA CV_RGBA2BGR CV_BGRA2RGB CV_BGR2RGBA |
加入或者移除alpha通道时,转换RGB到BGR 色彩空间 |
CV_RGB2GRAY CV_BGR2GRAY |
转换RGB或者BGR色彩空间为灰度空间 |
CV_GRAY2RGB CV_GRAY2BGR CV_RGBA2GRAY CV_BGRA2GRAY |
转换灰度为RGB或者BGR色彩空间(在进程中选择移除alpha通道) |
CV_GRAY2RGBA CV_GRAY2BGRA |
转换灰度为RGB或者BGR色彩空间并且加入alpha通道 |
CV_RGB2BGR565 CV_BGR2BGR565 CV_BGR5652RGB CV_BGR5652BGR CV_RGBA2BGR565 CV_BGRA2BGR565 CV_BGR5652RGBA CV_BGR5652BGRA |
在从RGB或者BGR色彩空间转换到BGR565彩色图画时,选择加入或者移除 alpha通道 (16位图) |
CV_GRAY2BGR565 CV_BGR5652GRAY |
转换灰度为BGR565彩色图像或者反变换(16位图) |
转换代码 解释 |
|
CV_RGB2BGR555 CV_BGR2BGR555 CV_BGR5552RGB CV_BGR5552BGR CV_RGBA2BGR555 CV_BGRA2BGR555 |
在从RGB或者BGR色彩空间转换到BGR555色彩空间时,选择加入或者移除 alpha通道(16位图) |
CV_BGR5552RGBA CV_BGR5552BGRA |
|
CV_GRAY2BGR555 CV_BGR5552GRAY |
转换灰度到BGR555色彩空间或者反变换(16位图) |
CV_RGB2XYZ CV_BGR2XYZ CV_XYZ2RGB CV_XYZ2BGR |
转换RGB或者BGR色彩空间到CIE XYZ色彩空间或者反变换(Rec 709和D65 白点) |
CV_RGB2YCrCb CV_BGR2YCrCb CV_YCrCb2RGB CV_YCrCb2BGR |
转换RGB 或者BGR色彩空间到luma-chroma (aka YCC)色彩空间 |
CV_RGB2HSV CV_BGR2HSV CV_HSV2RGB CV_HSV2BGR |
转换RGB或者BGR色彩空间到HSV(hue,saturation,value)色彩空间或反变换 |
CV_RGB2HLS CV_BGR2HLS CV_HLS2RGB CV_HLS2BGR |
转换RGB或者BGR色彩空间到HLS(hue,Lightness,saturation)色彩空间或反变换 |
CV_RGB2Lab CV_BGR2Lab CV_Lab2RGB CV_Lab2BGR |
转换RGB或者BGR色彩空间到CIE LAB色彩空间或反变换 |
转换代码 解释 |
|
CV_RGB2Luv CV_BGR2Luv CV_Luv2RGB CV_Luv2BGR |
转换RGB或者BGR色彩空间到CIE Luv色彩空间 |
CV_BayerBG2RGB CV_BayerGB2RGB |
转换Bayer模式(单通道)到RGB或者BGR色彩空间 |
CV_BayerRG2RGB CV_BayerGR2RGB CV_BayerBG2BGR CV_BayerGB2BGR CV_BayerRG2BGR CV_BayerGR2BGR |
这里不再进一步阐述CIE色彩空间中Bayer模式的细节,但许多这样的转换是很有意义的。我们的目的是,了解OpenCV能够在哪些色彩空间进行转换,这对用户来说很重要。
就HSV色彩模式或者HLS色彩模式来说,色调通常是在0~360之间。在8位图中,这可能出现问题,因此,转换到HSV色彩模式,并以8位图的形式输出时,色调应该除以2。
cvDet
double cvDet(const CvArr* mat);
cvDet()用于计算一个方阵的行列式。这个数组可以是任何数据类型,但它必须是单通道的,如果是小的矩阵,则直接用标准公式计算。然而对于大型矩阵,这样就不是很有效,行列式的计算使用高斯消去法。
值得指出的是,如果已知一个矩阵是对称正定的,也可以通过奇异值分解的策略来解决。欲了解更多信息,请参阅“cvSVD”一节。但这个策略是将U和V设置为NULL,然后矩阵W的乘积就是所求正定矩阵。
cvDiv
cvDotProduct
这个函数主要计算两个N维向量的点积[Lagrange1773]。与叉积函数相同,点积函数也不太关注向量是行或者是列的形式。src1和src2都应该是单通道的数组,并且数组的数据类型应该一致。
cvEigenVV
正如cvDet()(前述),如果被讨论的向量是已知的对称和正定矩阵,那么最好使用SVD计算mat的特征值和特征向量。
cvFlip
本函数是将图像绕着在X轴或Y轴或者绕着X轴或Y轴上同时旋转。当参数flip_mode被设置为0的时候,图像只会绕X轴旋转。 【61】
flip_mode被设置为正值时(例如,+1),图像会围绕Y轴旋转,如果被设置成负值(例如,-1),图像会围绕X轴和Y轴旋转。
在Win32运行视频处理系统时,你会发现自己经常使用此功能来进行图像格式变换,也就是坐标原点在左上角和左下角的变换。
cvGEMM
cvMatMul(A,B, D) |
cvGEMM(A,B,1,NULL,0,D,0) |
cvMatMulAdd(A,B,C,D) |
cvGEMM(A,B,1,C,1,D,0) |
只有大小符合约束的矩阵才能进行乘法运算,并且所有的数据类型都应该是浮点型。cvGEMM()函数支持双通道矩阵,在这种情况下,它将双通道视为一个复数的两个部分。
cvGetCol和cvGetCols
cvGetDiag
cvGetDims和cvGetDimSize
cvGetRow和cvGetRows
cvGetSize
CvSize cvGetSize( const CvArr* arr );
cvGetSubRect
cvInRange和cvInRangeS
void cvInRange(const CvArr* src,
cvInvert
cvInvert()求取保存在src中的矩阵的逆并把结果保存在dst中。这个函数支持使用多种方法来计算矩阵的逆(见表3-8),但默认采取的是高斯消去法。该函数的返回值与所选用的方法有关。 【65】
方法的参数值 |
含义 |
CV_LU |
高斯消去法 (LU 分解) |
CV_SVD |
奇异值分解(SVD) |
CV_SVD_SYM |
对称矩阵的SVD |
就高斯消去法(method=CV_LU)来说,当函数执行完毕,src的行列式将被返回。如果行列式是0,那么事实上不进行求逆操作,并且数组dst将被设置为全0。
就CV_SVD或者CV_SVD_SYM,来说,返回值是矩阵的逆条件数(最小特征值跟最大特征值的比例)。如果src是奇异的,那么cvInvert()在SVD模式中将进行伪逆计算。
cvMahalonobis
CvSize cvMahalonobis(
const CvArr* vec1,
const CvArr* vec2,
CvArr* mat
);
Mahalonobis距离(Mahal)被定义为一点和高斯分布中心之间的向量距离,该距离使用给定分布的协方差矩阵的逆作为归一化标准。参见图3-5。直观上,这是与基础统计学中的标准分数(Z-score)类似,某一点到分布中心的距离是以该分布的方差作为单位。马氏距离则是该思路在高维空间中的推广。
cvMahalonobis()计算的公式如下:
假设向量vec1对应x点,向量vec2是分布的均值。mat是协方差矩阵的逆。
实际上,这个协方差矩阵通常用cvCalcCovarMatrix()(前面所述)来进行计算,然后用cvInvert()来求逆。使用SV_SVD方法求逆是良好的程序设计习惯,因为其中一个特征值为0的分布这种情况在所难免!
图3-5:数据在2D空间分布,3个叠加在一起的椭圆分别对应到分布中心的马氏距离为1.0,2.0和3.0所有点
cvMax和cvMaxS
cvMerge
cvMin和cvMinS
cvMinMaxLoc
cvMul
cvNot
函数cvNot()会将src中的每一个元素的每一位取反,然后把结果赋给dst。因此,一个值为0x00的8位图像将被映射到0xff,而值为0x83的图像将被映射到0x7c。
cvNorm
这一函数可于计算一个数组的各种范数,当为该函数提供了两个数组作为参数时,可选用各种不同的公式来计算相对的距离。在前一种情况下,计算的范数如表3-9所示。
表3-9:当arr2=NULL时,对于不同的norm_type由cvNorm()计算范数的公式
norm_type |
结果 |
CV_C |
|
CV_L1 |
|
CV_L2 |
如果第二个数组参数arr2非空,那么范数的计算将使用不同的公式,就像两个数组之间的距离。前三种情况的计算公式如表3-10所示,这些范数是绝对范数;在后三个情况下,将会根据第二个数组arr2的幅度进行重新调整。 【69~70】
表3-10:arr2非空,且norm_type不同值时函数cvNorm()计算范数的计算
公式
norm_type |
结果 |
CV_C |
|
CV_L1 |
|
CV_L2 |
|
CV_RELATIVE_C |
|
CV_ RELATIVE_L1 |
|
CV_ RELATIVE_L2 |
在所有情况下,arr1和arr2必须具有相同的大小和通道数。当通道数大于1时,将会对所有通道一起计算范数(即是说,在表3-9和表3-10中,不仅是针对x和y,也针对通道数求和)。
cvNormalize
表3-11:函数cvNormalize()的参数norm_type可能的值
norm_type |
结果 |
CV_C |
|
CV_L1 |
续表
norm_type |
结果 |
CV_L2 |
|
CV_MINMAX |
映射到[a, b]的范围上 |
【70】
计算C范数时,数组src将被进行比例变标,使其中绝对值最大的值等于a。当计算L1范数成L2范数时,该数组也将被缩放,如使其范数为a。如果norm_type的值设置为CV_MINMAX,那么将会对数组的所有的值进行转化,使它们线性映射到a和b之间(包括a和b)。
与以前一样,如果参数mask非空,那么只有与掩码非0值对应的像素会对范数的计算有贡献,并且只有那些像素会被cvNormalize()改变。
cvOr和cvOrS
该函数支持所有的数据类型,但在cvOr()中,src1和src2必须有相同的数据类型。如果数组元素是浮点类型,则使用浮点按位表示形式。
cvReduce
表3-12:参数op在cvReduce()中所代表的转化操作
op的值 |
结果 |
CV_REDUCE_SUM |
计算所有向量的总和 |
CV_REDUCE_AVG |
计算所有向量的平均值 |
CV_REDUCE_MAX |
计算所有向量中的最大值 |
CV_REDUCE_MIN |
计算所有向量中的最小值 |
表3-13:参数dim在cvReduce()中控制转化的方向
dim的值 |
结果 |
+1 |
合并成一行 |
0 |
合并成一列 |
-1 |
转化成对应的dst |
cvReduce()支持浮点型的多通道数组。它也允许在dst中使用比src更高精度的数据类型。这关键在于要有正确的CV_REDUCE_SUM和CV_REDUCE_AVG参数,否则那里可能有溢出和累积问题。
cvRepeat
这一函数是将src的内容复制到dst中,重复多次,直到dst没有多余的空间。具体而言,dst相对于src可以是任何大小。它可能比src大或小,它们在大小和维数之间不需要有任何的数值关系。
cvScale
从宏观上讲,函数cvScale()实际上是cvConvertScale()的一个宏,它会将shift参数设置为0.0。因此,它可以用来重新调整数组的内容,并且可以将参数从一种数据类型转换为另一种。
cvSet和cvSetZero
cvSetIdentity
void cvSetIdentity( CvArr* arr );
cvSolve
基于cvInvert()函数cvSolve()为求解线性方程组提供了一条捷径。它的计算公式如下:
应当指出的是,cvSolve()可以用来解决超定的线性方程组。超定系统将使用所谓的伪逆方法进行解决,它是使用SVD方法找到方程组的最小二乘解的。
cvSplit
如果源图像少于4个通道(这种情况经常出现),那么传递给cvSplit()的不必要的目标参数可设置为NULL。 【73】
cvSub,cvSubS和cvSubRS
cvSum
cvSVD
对于函数cvSVD()来说,U和V是可选参数,如果它们的值设置为NULL,则不会返回它们的内容。最后的参数flags可以是表3-14所示三个选项中任何一个或全部(视情况进行布尔型或计算合并)。
参数 |
结果 |
CV_SVD_MODIFY_A |
允许改变矩阵A |
CV_SVD_U_T |
返回UT而不是U |
CV_SVD_V_T |
返回VT而不是V |
cvSVBkSb
函数cvSVBkSb()对矩阵A进行反向替代计算,A已分解为矩阵U,W和V(即SVD)的结构中描述出来。矩阵X的结果可由如下公式计算得出:
矩阵B是可选的,如果设置为NULL,它将会被忽略。当时矩阵W*中的对角线元素定义如下:
ε这个值是一个奇异性阈值,一个非常小的数值,通常与W的对角线元素的总和成正比(即)。
cvTrace
CvScalar cvTrace( const CvArr* mat );
矩阵的迹是对角线元素的总和。在OpenCV中,该功能在函数cvGetDiag()基础上实现,因此输入的数组不需要是方阵。同样支持多通道数组,但是数组mat必须是浮点类型。
cvTranspose与cvT
cvXor和cvXorS
计算支持所有的数据类型,但src1和src2在函数cvXor()中必须是相同的数据类型。如果数组的元素是浮点类型的,那么使用浮点数的二进制表示。
cvZero
我们经常需要绘制图像或者在已有的图像上方绘制一些图形。为此,OpenCV提供了一系列的函数帮助我们绘制直线、方形和圆形等。
直线
cvLine()是绘图函数中最简单的,只需用Bresenham算法[Bresenham65]画一条线 :
下一个属性是CvScalar类型的颜色变量。CvScalar也是一种数据结构,定义如下所示:
圆形和椭圆
对圆形和矩阵等很多封闭图形来说,thickness参数也可以设置为CV_FILL,其值是-1;其结果是使用与边一样的颜色填充圆内部。
angle是指偏离主轴的角度,从X轴算起,逆时针方向为正。同样,start_angle和end_angle表示弧线开始和结束位置的角度。因此,一个完整的椭圆必须分别将这两个值分别设为0°和360°。
CvPoint2D32f是CvPoint的浮点形式,同时CvSizet2D32f也是CvSize的浮点形式。这些,连同倾斜角度,可以有效地描述椭圆的外接矩形。
多边形
上述三种方法依据同一思路又略有不同,其主要区别是如何描述点。
cvFillConvexPoly()和cvFillPoly()类似。不同的是,它一次只能画一个多边形,而且只能画凸多边形。好处是,cvFillConvexPoly()运行得更快。
第三个cvPolyLine(),其参数与cvFillPoly()相同,但因为只需画出多边形的边,不需处理相交情况。因此,这种函数运行速度远远超过cvFillPoly()。
字体和文字
OpenCV有一个主要的函数,叫cvPutText()。这个函数可以在图像上输出一些文本。参数text所指向的文本将打印到图像上,参数origin指定文本框左下角位置,参数color指定文本颜色。
总有一些琐事使我们的工作比预期复杂,此时是CvFont指针表现的机会了。
为了建立一个可以传值给cvPutText()的CvFont,首先必须声明一个CvFont变量,然后把它传递给cvInitFont()。
font_face参数列在表3-15中(效果在图3-6中画出),它可与CV_FONT_ITALIC组合(通过布尔或操作)。
标志名称 描述 |
|
CV_FONT_HERSHEY_SIMPLEX |
正常尺寸sanserif字体 |
CV_FONT_HERSHEY_PLAIN |
小尺寸sanserif字体 |
CV_FONT_HERSHEY_DUPLEX |
正常尺寸sanserif, 比 |
CV_FONT_HERSHEY_COMPLEX |
正常尺寸serif, 比 |
续表
标志名称 描述 |
|
CV_FONT_HERSHEY_TRIPLEX |
正常尺寸serif, 比CV_FONT_ |
CV_FONT_HERSHEY_COMPLEX_SMALL |
小尺寸的 |
CV_FONT_HERSHEY_SCRIPT_SIMPLEX |
手写风格 |
CV_FONT_HERSHEY_SCRIPT_COMPLEX |
比CV_FONT_HERSHEY_SCRIPT_ |
【81】
图3-6:表3-15中的8个字体,绘制时设置hscale= vscale = 1.0,且每行的垂直间距为30像素
hscale和vscale只能设为1.0或0.5。字体渲染时选择全高或半高(宽度同比缩放),绘制效果与指定字体的基本定义有关。
参数shear创建斜体字,如果设置为0.0 ,字体不倾斜。当设置为1.0 时,字符倾斜范围接近45度。
参数thickness与Line_type的定义与其他绘图函数相同。
数据存储
OpenCV提供了一种机制来序列化(serialize)和去序列化(de-serialize)其各种数据类型,可以从磁盘中按YAML或XML格式读/写。在第4章中,我们将专门介绍存储和调用常见的对象IplImages的函数(cvSaveImage()和cvLoadImage())。此外,第4章将讨论读/写视频的特有函数:可以从文件或者摄影机中读取数据的函数cvGrabFrame()以及写操作函数cvCreateVideoWriter()和cvWriteFrame()。本小节将侧重于一般对象的永久存储:读/写矩阵、OpenCV结构、配置与日志文件。
首先,我们从有效且简便的OpenCV矩阵的保存和读取功能函数开始。函数是cvSave()和cvLoad()。例3-15展示了如何保存和读取一个5×5的单位矩阵(对角线上是1,其余地方都是0)。
例3-15:存储和读取CvMat
CvMatA = cvMat( 5, 5, CV_32F,the_matrix_data );
cvSave("my_matrix.xml", &A );
.. .
//to load it then in some other program use …
CvMat*A1 = (CvMat*) cvLoad( "my_matrix.xml" );
CxCore参考手册中有整节内容都在讨论数据存储。首先要知道,在OpenCV中,一般的数据存储要先创建一个CvFileStorage结构(如例3-16)所示,该结构将内存对象存储在一个树形结构中。然后通过使用CV_STORAGE_READ参数的cvOpenFileStorage()从磁盘读取数据,创建填充该结构,也可以通过使用CV_STORAGE_WRITE的cvOpenFileStorage()创建并打开CvFileStorage写数据,而后使用适当的数据存储函数来填充它。在磁盘上,数据的存储格式为XML或者YAML。
例3-16:CvFileStorage结构,数据通过CxCore数据存储函数访问
typedefstruct CvFileStorage
{
... // hidden fields
}CvFileStorage;
CvFileStorage树内部的数据是一个层次化的数据集合,包括标量、CxCore对象(矩阵、序列和图)以及用户定义的对象。
假如有一个配置文件或日志文件。配置文件告诉我们视频有多少帧(10),画面大小(320×240)并且将应用一个3×3的色彩转换矩阵。例3-17展示了如何从磁盘中调出cfg.xml文件。
例3-17:往磁盘上写一个配置文件cfg.xml
CvFileStorage*fs = cvOpenFileStorage(
"cfg.xml",
0,
CV_STORAGE_WRITE
);
cvWriteInt(fs, "frame_count", 10 );
cvStartWriteStruct(fs, "frame_size", CV_NODE_SEQ );
cvWriteInt(fs, 0, 320 );
cvWriteInt(fs, 0, 200 );
cvEndWriteStruct(fs);
cvWrite(fs, "color_cvt_matrix", cmatrix );
cvReleaseFileStorage(&fs );
请留意这个例子中的一些关键函数。我们可以定义一个整型变量通过cvWritelnt()向结构中写数据。我们也可以使用cvStartWriteStruct()来创建任意一个可以任选一个名称(如果无名称请输入0或NULL)的结构。这个结构有两个未命名的整型变量,使用cvEndWriteStruct()结束编写结构。如果有更多的结构体,我们用相似的方法来解决;这种结构可以进行任意深度的嵌套。最后,我们使用cvWrite()编写处色彩转换矩阵。将这个相对复杂的矩阵程序与例3-15中简单的cvSave()程序进行对比。便会发现cvSave()是cvWrite()在只保存一个矩阵时的快捷方式。当写完数据后,使用cvReleaseFileStorage()释放CvFileStorage句柄。例3-18显示了XML格式的输出内容。
例3-18:磁盘中的cfg.xml文件
<?xmlversion="1.0"?>
<opencv_storage>
<frame_count>10</frame_count>
<frame_size>320200</frame_size>
<color_cvt_matrixtype_id="opencv-matrix">
<rows>3</rows> <cols>3</cols>
<dt>f</dt>
<data>...</data></color_cvt_matrix>
</opencv_storage>
我们将会在例3-19中将这个配置文件读入。
例3-19:磁盘中的cfg.xml文件
CvFileStorage*fs = cvOpenFileStorage(
"cfg.xml",
0,
CV_STORAGE_READ
);
intframe_count = cvReadIntByName(
fs,
0,
"frame_count",
5 /* default value */
);
CvSeq*s = cvGetFileNodeByName(fs,0,"frame_size")->data.seq;
intframe_width = cvReadInt(
(CvFileNode*)cvGetSeqElem(s,0)
);
intframe_height = cvReadInt(
(CvFileNode*)cvGetSeqElem(s,1)
);
CvMat*color_cvt_matrix = (CvMat*) cvReadByName(
fs,
0,
"color_cvt_matrix"
);
cvReleaseFileStorage(&fs );
在阅读时,我们像例3-19中那样用cvOpenFileStorage()打开XML配置文件。然后用cvReadlntByName()来读取frame_count,如果有没有读到的数,则赋一个默认值。在这个例子中默认的值是5。然后使用cvGetFileNodeByName()得到结构体frame_size。在这里我们用cvReadlnt()读两个无名称的整型数据。随后使用cvReadByName()读出我们已经定义的色彩转换矩阵。将本例与例3-15中的cvLoad()进行对比。如果我们只有一个矩阵要读取,那么可以使用cvLoad(),但是如果矩阵是内嵌在一个较大的结构中,必须使用cvRead()。最后,释放CvFileStorage结构。
数据函数存储与CvFileStorage结构相关的表单列在表3-16中。想了解更多细节,请查看CxCore手册。
表3-16:数据存储函数
函数名称 |
描述 |
打开并释放 |
|
cvOpenFileStorage |
为读/写打开存储文件 |
cvReleaseFileStorage |
释放存储的数据 |
写入 |
|
cvStartWriteStruct |
开始写入新的数据结构 |
cvEndWriteStruct |
结束写入数据结构 |
cvWriteInt |
写入整数型 |
cvWriteReal |
写入浮点型 |
cvWriteString |
写入字符串 |
cvWriteComment |
写一个XML或YAML的注释字串 |
cvWrite |
写一个对象,例如CvMat |
cvWriteRawData |
写入多个数值 |
cvWriteFileNode |
将文件节点写入另一个文件存储器 |
读取 |
|
cvGetRootFileNode |
获取存储器最顶层的节点 |
cvGetFileNodeByName |
在映图或存储器中找到相应节点 |
cvGetHashedKey |
为名称返回一个惟一的指针 |
cvGetFileNode |
在映图或文件存储器中找到节点 |
cvGetFileNodeName |
返回文件的节点名 |
cvReadInt |
读取一个无名称的整数型 |
cvReadIntByName |
读取一个有名称的整数型 |
cvReadReal |
读取一个无名称的浮点型 |
续表
函数 |
描述 |
cvReadRealByName |
读取一个有名称的浮点型 |
cvReadString |
从文件节点中寻找字符串 |
cvReadStringByName |
找到一个有名称的文件节点并返回它 |
cvRead |
将对象解码并返回它的指针 |
cvReadByName |
找到对象并解码 |
cvReadRawData |
读取多个数值 |
cvStartReadRawData |
初始化文件节点序列的读取 |
cvReadRawDataSlice |
读取文件节点的内容 |
集成性能基元
Intel公司有一个产品叫集成性能基元(IntegratedPerformance Primitives,IPP)库。这个库实际上是一个有着高性能内核的工具箱,它主要用于多媒体处理以及其他计算密集型应用,可发掘处理器架构的计算能力。(其他厂商的处理器也有类似的架构,只不过规模较小。)
就像第一章所探讨的,无论从软件层面还是公司内组织层面OpenCV都与IPP有着紧密的联系。最终,OpenCV被设计成能够自动识别IPP库,自动将性能较低的代码切换为IPP同功能的高性能代码。IPP库允许OpenCV依靠它获得性能提升,IPP依靠单指令多数据(SIMD)指令以及多核架构提升性能。
学会这些基础知识,我们就可以执行各种各样的基本任务。在本书随后的内容中,我们会发现OpenCV具有许多高级功能,几乎所有这些功能都可切换到IPP运行。图像处理经常需要对大量数据做同样的重复操作,许多是可并行处理的。因此如果任何利用并行处理方式(MMX,SSE,SSE2等)的代码获得了巨大性能提升,您不必感到惊讶。
验证安装
用来检查IPP库是否已经正常安装并且检验运行是否正常的方法是使用函数cvGetModulelnfo(),如例3-20所示。这个函数将检查当前OpenCV的版本和所有附加模块。
例3-20:使用cvGetModulelnfo()检查IPP
cvGetModuleInfo(0, &libraries, &modules );
printf("Libraries:%s/nModules: %s/n", libraries, modules );
例3-20中的代码将打印出描述已经安装的库和模块的文本。结果如下所示:
Modules: ippcv20.dll, ippi20.dll,ipps20.dll, ippvm20.dll
【OpenCV】矩阵和图像的操作总结查询相关推荐
- 【OpenCV 4】图像卷积操作(Blur)
一.编程环境: OpenCV 4.1.0 IDE Visual Studio 2017 Enterprise (15.9.13) 操作系统 Windows 10 x64 中文专业版 (1903) 二 ...
- 【opencv】基本图像形态学操作
图像形态学的作用是简化图像数据,保持基本图像特性,取出不相干结构等. 目录: 1.erode() 2.dilate() 3.morphologyEx()//MORPH_OPEN 4.morpholog ...
- 《学习opencv》笔记——矩阵和图像操作——cvCrossProduct and cvCvtColor
矩阵和图像的操作 (1)cvCrossProduct函数 其结构 void cvCrossProdust(//计算两个三维向量的叉积const CvArr* src1,const CvArr* src ...
- 《学习opencv》笔记——矩阵和图像操作——cvMax,cvMaxS,cvMerge,cvMin and cvMinS
矩阵和图像的操作 (1)cvMax函数 其结构 void cvMax(//比较两个图像取最大值const CvArr* src1,//图像1const CvArr* src2,//图像2CvArr* ...
- OpenCV之core 模块. 核心功能(1)Mat - 基本图像容器 OpenCV如何扫描图像、利用查找表和计时 矩阵的掩码操作 使用OpenCV对两幅图像求和(求混合(blending))
Mat - 基本图像容器 目的 从真实世界中获取数字图像有很多方法,比如数码相机.扫描仪.CT或者磁共振成像.无论哪种方法,我们(人类)看到的是图像,而让数字设备来"看"的时候,则 ...
- 独家|OpenCV 1.4 对图像的操作
翻译:陈之炎 校对:吴振东本文约2400字,建议阅读5分钟本文为大家系统地介绍了OpenCV对图像的操作. 图像的输入/输出 从文件中加载图像: 如果读入的是一个JPG文件,默认状态下会创建一个3通道 ...
- OpenCv 如何对图像的像素进行操作
对图像的像素进行操作,我们可以实现空间增强,反色等目的.让我们先来看一下内存空间中图像矩阵,也就是Mat的矩阵数值部分是怎么存储的: 如果图像是一幅灰度图像,他就像这样,从左到右,从上到下,依次是矩阵 ...
- OpenCV与图像处理学习六——图像形态学操作:腐蚀、膨胀、开、闭运算、形态学梯度、顶帽和黑帽
OpenCV与图像处理学习六--图像形态学操作:腐蚀.膨胀.开.闭运算.形态学梯度.顶帽和黑帽 四.图像形态学操作 4.1 腐蚀和膨胀 4.1.1 图像腐蚀 4.1.2 图像膨胀 4.2 开运算与闭运 ...
- OpenCV 矩阵常用操作,比如 addWeighted, flip, hconcat, reduce, merge, norm, repeat, split, sort, mulSpectrum 等
平时经常会用到一些 C++ OpenCV 矩阵 Mat 常用的函数,每次用到都要到官网去查看,现在特地整理了一下. 下面的函数均来自于 https://docs.opencv.org/master/d ...
最新文章
- 使用 Python 的图像隐写术
- @Autowired注解通过源码讲原理
- 美国进入紧急状态:谷歌投入1700名工程师上阵抗疫,马斯克称车祸比新冠病毒危险...
- Castle.MVC框架介绍
- OpenCV | OpenCv常用函数(代码类)
- 性能测试:服务器配置清单分析
- 运维:Windows 系统安全日志中登录类型介绍
- 年货节页面PSD分层模板,拿稳了!应急!
- 微课|中学生可以这样学Python(5.6.2节):生成器推导式
- 【问题记录】python 函数 传入一个对象返回一个对象值得注意
- MongoDB数据库(使用、基本操作)
- Sap S/4 Hana 和Sap ERP有什么不同
- 思科模拟器Cisco Packet Tracer交换机的端口聚合配置
- 趣图 | 小哥哥你怎么那么高冷呀?
- 思维方式-《六顶思考帽》书中的精髓:通过在同一时间只使用一顶思考帽的方法,可以解决思维混乱等问题,从而提升思考效率。
- 用Python实现一个轮盘抽奖小游戏~
- JSP入门教程(一)
- js,if语句(条件判断语句)
- 2345浏览器写CSDN博客错误
- 如何Tomcat部署web应用