1opencv中矩阵和图像可以用相同的函数进行操作,主要包含以下几种类型:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
操作函数
1:获取元素与天剑
2:copy 添加
3:变化和置换
4:算术逻辑
5:统计
6:线性代数
7:数学函数
8:离散变化
大致将每种类型列出表格,对重要的函数进行说明
1:copy add
void cvCopy( const CvArr* src, CvArr* dst, const CvArr* mask=NULL );
|
复制数据,如果图像设置了ROI,就会使用ROI |
void cvSet( CvArr* arr, CvScalar value, const CvArr* mask=NULL );
|
设置数组为指定值 |
void cvSetZero( CvArr* arr );
|
清空数组
|
void cvRange( CvArr* mat, double start, double end );
|
必须指向单通道32位,arr(i,j)=(end-start)*(i*cols(arr)+j)/(cols(arr)*rows(arr))
|
2:变化和置换
void cvFlip( const CvArr* src, CvArr* dst=NULL, int flip_mode=0);
|
垂直或者水平翻转,flip_mode = 0 沿X-轴翻转, flip_mode > 0 (如 1) 沿Y-轴翻转, flip_mode < 0 (如 -1) 沿X-轴和Y-轴翻转 |
void cvSplit( const CvArr* src, CvArr* dst0, CvArr* dst1, CvArr* dst2, CvArr* dst3 );
|
分割多通道数组成几个单通道数组或者从数组中提取一个通道 ,应用:彩色图像分割出HSV分量
|
void cvMerge( const CvArr* src0, const CvArr* src1, const CvArr* src2, const CvArr* src3, CvArr* dst );
|
从几个单通道数组组合成多通道数组或插入一个单通道数组 |
void cvCvtColor( const CvArr* src, CvArr* dst, int code );
|
色彩空间变换,用的比较多,灰度变换,HSV变换等 |
void cvResize( const CvArr* src, CvArr* dst, int interpolation=CV_INTER_LINEAR );
|
图像大小变换,可以使用CV_INTER_NN - 最近邻插值, CV_INTER_LINEAR - 双线性插值 (缺省使用) CV_INTER_AREA - 使用象素关系重采样。当图像缩小时候,该方法可以避免波纹出现。当图像放大时,类似于 CV_INTER_NN 方法..CV_INTER_CUBIC - 立方插值. |
这几个函数在图像处理中都比较常用,比如:
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
HSV
cvCvtColor(m_SrcRgbImg,HsvImg,CV_BGR2HSV); //彩色转HSV
cvSplit(HsvImg,H_Img,S_Img,V_Img,0); //分离通道
/*对S H V分量进行处理
*/
3.算术逻辑
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
算术逻辑
逻辑运算
void cvAnd(const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL);//元素相与
void cvAndS(const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL);//元素和数相与
void cvOr(const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL);//
void cvOrS(const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL);//
void cvXor(const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL);//
void cvXorS(const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL);//
void cvNot(const CvArr* src,CvArr* dst);//矩阵取反
矩阵算术运算
void cvAbs(const CvArr* src,CvArr* dst); //绝对值
void cvAbsDiff(const CvArr* src1,const CvArr* src2, CvArr* dst);//两矩阵相减取绝对值
void cvAbsDiffS(const CvArr* src, CvArr* dst,CvScalar value);//矩阵减去一个数取绝对值
加减
void cvAdd(const CvArr* src1,const CvArr* src2,CvArr* dst,const CvArr* mask = NULL);//两数组相加,dst(I)=src1(I)+src2(I) if mask(I)!=0
void cvAddS(const CvArr* src,CvScalar value,CvArr*dst,const CvArr* mask = NULL);//数组和一个数相加,dst(I)=src(I)+value if mask(I)!=0
void cvAddWeighted(const CvArr* src1,double alpha,const CvArr* src2,double beta,double gamma,CvArradded to each sum* dst);//带权相加相当于dst(x,y) = α ? src1(x,y) + β ? src2(x,y) + γ
void cvSub(const CvArr* src1, const CvArr* src2, CvArr* dst, const CvArr* mask=NULL);//矩阵减法,dst(I)=src1(I)-src2(I) if mask(I)!=0
void cvSubS(const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL);//矩阵减数,dst(I)=src(I)-value if mask(I)!=0
void cvSubRS(const CvArr* src, CvScalar value, CvArr* dst, const CvArr* mask=NULL);//数减矩阵,dst(I)=value-src(I) if mask(I)!=0
乘除
void cvDiv(const CvArr* src1, constvoid cvDiv(const CvArr* src1, const CvArr* src2, CvArr* dst, double scale=1);//scale*src1(i)/src2(i),如果src1=NULL,则计算scale/src2(i)
void cvMul(const CvArr* src1,const CvArr* src2,CvArr* dst,double scale=1);//两矩阵元素之间的简单乘法(对应数据),矩阵乘法用cvGEMM();
次方
void cvPow(const CvArr* src, CvArr* dst, double power);//为每个src的数求power次方
指数
void cvExp(const CvArr* src, CvArr* dst);//dst(I)=EXP(src(I))
对数
void cvLog(const CvArr* src, CvArr* dst);//
4.统计
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
统计
void cvMax(const CvArr* src1, const CvArr* src2, CvArr* dst);
void cvMaxS(const CvArr* src, double value, CvArr* dst);//找较大值放到dst中,是每一个元素都进行比较
void cvMin(const CvArr* src1,const CvArr* src2,CvArr* dst);
void cvMins(const CvArr* src,double value,CvArr* dst);//找较小值放到dst中,,是每一个元素都进行比较
/* 找出全局某个通道中最大最小的值,和她们的位置,如果不止一个通道,一定要设置COI,可以使用ROI*/
void cvMinMaxLoc(const CvArr* arr, double* min_val, double* max_val, CvPoint* min_loc=NULL, CvPoint* max_loc=NULL, const CvArr* mask=NULL);
int cvCountNonZero( const CvArr* arr );//统计非零的个数
void cvInRange(const CvArr* src,const CvArr* lower,const CvArr* upper,CvArr* dst);
void cvInRangeS(const CvArr* src,CvScalar lower,CvScalar upper,CvArr* dst);//判断原数组中的每个数大小是否落在对应的lower、upper数组位置数值的中间
/*if( lower(i)<=src(i)<upper(i) ){ dst(i)=0xff; }else{ dst(i)=0; }*/
CvScalar cvAvg(const CvArr* arr,const CvArr* mask = NULL);//计算mask非零位置的所有元素的平均值,如果是图片,则单独计算每个通道上的平均值,如果COI设置了,只计算该COI通道的平均值
void cvAvgSdv(const CvArr* arr, CvScalar* mean, CvScalar* std_dev, const CvArr* mask=NULL);//计算各通道的平均值,标准差,支持COI
CvScalar cvSum( const CvArr* arr ); //函数 cvSum 独立地为每一个通道计算数组元素的和 S :
double cvNorm(const CvArr* arr1,const CvArr* arr2=NULL,int norm_type=CV_L2,const CvArr* mask=NULL);//计算一个数组的各种范数
5.线性代数
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
统计加&乘
void cvScaleAdd(const CvArr* src1, CvScalar scale, const CvArr* src2, CvArr* dst);//src1和scale的乘积加上src2
void cvCrossProduct(const CvArr* src1,const CvArr* src2,CvArr* dst);//计算两个3D向量(单通道)的叉乘运算
double cvDotProduct(const CvArr* src1, const CvArr* src2);//两个向量点乘
void cvGEMM(const CvArr* src1, const CvArr* src2, double alpha, const CvArr* src3, double beta, CvArr* dst, int tABC=0);//乘加运算的始祖由通用乘加函数参与定义的两个具体宏
cvMatMul(const CvArr* src1,const CvArr* src2,CvArr* dst);
cvMatMulAdd(const CvArr* src1,const CvArr* src2,const CvArr* src3,CvArr* dst);
CvScalar cvTrace(const CvArr* mat);//计算对角线上的元素和
转置
void cvTranspose(const CvArr* src, CvArr* dst); //dst(i,j)=src(j,i)
void cvMulTransposed(const CvArr* src, CvArr* dst, int order, const CvArr* delta=NULL, double scale=1.0);//(src-delta)乘以它的转置再乘以scale
逆矩阵
double cvInvert(const CvArr* src,CvArr* dst,int method=CV_LU);//求原矩阵的逆矩阵,默认使用高斯消去法
方阵可逆的充要条件是|A|!=0
//method取值为CV_LU高斯消去法(默认) CV_SVD 奇异值分解SVD CV_SVD_SYM对称矩阵的SVD
解方程
int cvSolve( const CvArr* src1, const CvArr* src2, CvArr* dst, int method=CV_LU );
/*求解线性系统或者最小二乘法问题 ,method
CV_LU - 最佳主元选取的高斯消除法
CV_SVD - 奇异值分解法 (SVD)
CV_SVD_SYM - 对正定对称矩阵的 SVD 方法 */
奇异值分解 /*函数 cvSVD 将矩阵 A 分解成一个对角线矩阵和两个正交矩阵的乘积*/
void cvSVD( CvArr* A, CvArr* W, CvArr* U=NULL, CvArr* V=NULL, int flags=0 );
矩阵的特征值和特征向量
void cvEigenVV( CvArr* mat, CvArr* evects, CvArr* evals, double eps=0 );
//马氏距离
double cvMahalanobis( const CvArr* vec1, const CvArr* vec2, CvArr* mat );//
//PCA
void cvCalcPCA( const CvArr* data, CvArr* avg,CvArr* eigenvalues, CvArr* eigenvectors, int flags );//对一个向量集做PCA变换
void cvProjectPCA( const CvArr* data, const CvArr* avg,const CvArr* eigenvectors, CvArr* result )//把向量向某个子空间投影
void cvBackProjectPCA( const CvArr* proj, const CvArr* avg,const CvArr* eigenvects, CvArr* result );
6.数学函数
![](https://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif)
一般算数运算
int cvRound(double value ); int cvFloor( double value ); int cvCeil( double value);//求和double最(上/下)接近的整数
float cvSqrt(float value);//求平方根
float cvInvSqrt(float value);//求平方根倒数
float cvCbrt(float value);//求立方根
float cvCbrt(float value);//求两个向量的夹角
int cvIsNaN(double value);//判断是否是合法数
int cvIsInf(double value);//判断是否无穷
void cvCartToPolar(const CvArr* x, const CvArr* y, CvArr* magnitude, CvArr* angle=NULL, int angle_in_degrees=0);//计算二维向量的长度和/或者角度
void cvPolarToCart(const CvArr* magnitude, const CvArr* angle, CvArr* x, CvArr* y, int angle_in_degrees=0);//计算极坐标形式的二维向量对应的直角坐标
void cvSolveCubic(const CvArr* coeffs, CvArr* roots);//求三次方方程解,coeffs作为三次方程的系数,可以是三元(三次方系数为1)或者四元
就总结这么多了先,对这些画个小时时间,至少脑子里面系统了一些哈,给出我自己写的双摄像机的标定程序(opencv中已经使用另外一个函数实现):其实公式很简单,如下:
![image image](https://images.cnblogs.com/cnblogs_com/zsb517/201206/201206041734211614.png)
opencv的实现如下:
sys_Rotion_array.RemoveAll() ;
sys_Trans_array.RemoveAll();
for( CurrentImage=0 ; CurrentImage < sys_ImgChessPram.ImageNum ; CurrentImage++)
{
cvGetRow(sys_CalibratePram_cur.rotation_vectors,temp_Vector,CurrentImage); //获取1*3旋转向量
cvRodrigues2(temp_Vector,temp_cur_Rotion_Max,0); //转换为3*3旋转矩阵
cvGetRow(sys_CalibratePram_other.rotation_vectors,temp_Vector,CurrentImage);
cvRodrigues2(temp_Vector,temp_other_Rotion_Max,0);
cvGetRow(sys_CalibratePram_cur.translation_vectors,temp_cur_trans_Vector,CurrentImage); //获取1*3平移向量
cvGetRow(sys_CalibratePram_other.translation_vectors,temp_other_trans_Vector,CurrentImage); //获取1*3平移向量
CvMat *temp_sys_rotion = cvCreateMat(3,3,CV_32FC1);
CvMat *temp_sys_trans = cvCreateMat(1,3,CV_32FC1);
GetSysParam(temp_cur_Rotion_Max,temp_cur_trans_Vector,temp_other_Rotion_Max,temp_other_trans_Vector,temp_sys_rotion,temp_sys_trans );
sys_Rotion_array.Add(temp_sys_rotion) ; //添加到序列中
sys_Trans_array.Add(temp_sys_trans);
}
cvSetZero(temp_Rotion_Max_Sum);
cvSetZero(temp_trans_Vector_Sum);
for( CurrentImage=0 ; CurrentImage < sys_ImgChessPram.ImageNum ; CurrentImage++)
{
cvAdd(temp_Rotion_Max_Sum , sys_Rotion_array.GetAt(CurrentImage),temp_Rotion_Max_Sum);
cvAdd(temp_trans_Vector_Sum , sys_Trans_array.GetAt(CurrentImage),temp_trans_Vector_Sum);
}
cvMul(temp_Rotion_Max_Sum ,div_r_mat,m_MedLeftRotionMax);
cvMul(temp_trans_Vector_Sum,div_t_mat,m_MedLeftTranstionMax);