Opencv矩阵操作基础笔记

来源:互联网 发布:c语言 bool取反 编辑:程序博客网 时间:2024/06/05 17:37

<下面为个人笔记积累,会持续更新内容,发现不对的希望帮忙指出来微笑>

1.关于协方差矩阵:

Opencv中求协方差矩阵:

函数原型为:

//! computes covariation matrix of a set of samplesCV_EXPORTS void calcCovarMatrix( const Mat* samples, int nsamples, Mat& covar, Mat& mean,                                 int flags, int ctype=CV_64F);//! computes covariation matrix of a set of samplesCV_EXPORTS_W void calcCovarMatrix( const Mat& samples, CV_OUT Mat& covar, CV_OUT Mat& mean,                                 int flags, int ctype=CV_64F);

举例:

假设有矩阵mu要求它的协方差矩阵Su,代码为:

MatSu;Matmeanu;calcCovarMatrix(mu,Su,meanu,CV_COVAR_ROWS|CV_COVAR_NORMAL);Su.convertTo(Su,CV_64FC1,1.0/(mu.rows-1));

其中,

CV_COVAR_ROWS:说明mu中每一行代表一个样本。

CV_COVAR_NORMAL:使用普通的方法求协方差矩阵。

meanu:是按列求出的mu的平均值,是一个行向量。

*跟maltab比较:

*由于opencv求协方差矩阵的时候默认的规范化|CV_COVAR_SCALE是除以mu.rows而MATLAB是除以mu.rows-1,这里为了跟MATLAB算出的结果保持一致,在计算的时候先不规范化,算出后再人为的除以mu.rows-1

2.关于矩阵的范数

向量和矩阵范数的求法:

向量的范数:1-范:所有元素的绝对值之和。

            2-范:所有元素的平方之和再求平方根,即向量模。

            无穷范:绝对值最大的元素的绝对值。

矩阵的范数:1-范:每列元素绝对值之和最大的那一列的绝对值之和。

            2-范:矩阵的最大奇异值,即A.t()*A的最大非负特征值的平方根。

           无穷范:每行元素绝对值之和最大的那一行的绝对值之和。

从上面内容可以看出,矩阵范数的求法和向量范数的求法并不相同。

MATLAB中norm();函数可以求向量的范数,也可以求矩阵的范数,但是,在opencv中norm();函数只能用来求向量的范数。如果用来求矩阵的范数,它会把矩阵当做向量来求,得到的结果当然跟maltab不一样。至于矩阵的范数,我没有找到封装,所以自己写了一个求2范的,并不复杂。

opencv求向量范数norm函数的原型:

//! computes norm of arrayCV_EXPORTS double norm(const Mat& src1, int normType=NORM_L2);//! computes norm of the difference between two arraysCV_EXPORTS double norm(const Mat& src1, const Mat& src2, int normType=NORM_L2);//! computes norm of the selected array partCV_EXPORTS_W double norm(const Mat& src1, int normType, const Mat& mask CV_WRAP_DEFAULT(Mat()));//! computes norm of selected part of the difference between two arraysCV_EXPORTS_W double norm(const Mat& src1, const Mat& src2,                       int normType, const Mat& mask CV_WRAP_DEFAULT(Mat()));

自己实现的求矩阵2范数的函数:

/************************************************//求矩阵的最大奇异值(2范数)//opencv自带的norm只能求向量的,不能求矩阵的!************************************************/double norm2ofMat(Mat src){    double norm2value=0;    Mat srcT=src.t();    Mat multi=srcT*src;    Mat eigenvalues;    eigen(multi,eigenvalues);    for(int i=0;i<eigenvalues.rows;i++){        for(int j=0;j<eigenvalues.cols;j++){            double eigenvalue=eigenvalues.ptr<double>(i)[j];            if(eigenvalue>0){                double eigenvalueSqrt=sqrt(eigenvalue);                if(eigenvalueSqrt>norm2value)                    norm2value=eigenvalueSqrt;            }        }    }    return norm2value;}

3.Mat类的某些行或者列提取出来单独赋值

(1)假设有Mat类型行向量R和列向量C分别要赋值到矩阵A的第i行和第i列;

Mat ri=A.row(i);

R. copyTo(ri);

Mat ci=A.col(i);

C. copyTo(ci);

(2)假设有Mat类型的矩阵R要赋值到矩阵A的第1-r+1行,R的行数为r小于A的行数,列数等于A的列数。

Mat roi=A(Rect(0,1,A.cols,r+1));//roi起点(0,1)宽(A.cols)高(r+1)。

R. copyTo(roi);

4.矩阵算数运算:

【需要注意的是opencv对+、-、*等符号进行了重载,可以直接像标量算数运算那样进行矩阵算数运算,可逆矩阵求逆用Mat::inv();转置为Mat::t();】

Gemm函数:

在MATLAB中矩阵的广义乘法,就是行乘以列的那种,是gemm而不是Mat::dot,也不是multiply();Mat::dot和multiply();是对应的元素相乘,如果被乘数是标量,那么就是矩阵所有的元素乘以这个标量。

gemm函数原型:


//! implements generalized matrix product algorithm GEMM from BLASCV_EXPORTS_W void gemm(const Mat& src1, const Mat& src2, double alpha,                       const Mat& src3, double gamma, CV_OUT Mat& dst, int flags=0);

dst=( alpha*src1)xsrc2+(gamma*src3);

关于gemm函数举例:

doublec[2][2]={{1.0,1.0},{1.0,1.0}};    Matm1(2,2,CV_64FC1,c);    cout<<"m1:"<<m1<<endl;    doubled[2][2]={{2.0,2.0},{2.0,2.0}};    Matm2(2,2,CV_64FC1,d);    cout<<"m2:"<<m2<<endl;    MatE;    Matzero(m1.size(),m1.type());    gemm(m1,m2,1,zero,1,E);    cout<<"E=m1·m2:"<<endl;cout<<E<<endl;
运算结果:

5.关于数组排序和除重的问题

/*这个是c++的,不是opencv的*/

/************************************************
//将输入的double类型的数组进行筛选然后按降序排列
//筛选规则:删除数组中重复的元素
//in:指向源数组,location指向in中元素在排序后的位置
//返回值:double类型的vector
************************************************/
vector<double> uniqueAndSort(double *in,int *location,int lenIn)
{
    vector<double>vec(in,in+lenIn);
    vector<double>::iterator iter = unique(vec.begin(),vec.end());
    vec.erase(iter,vec.end());
    sort(vec.begin(),vec.end());
    reverse(vec.begin(),vec.end());
    int m=0;
    for(iter=vec.begin();iter!=vec.end();m++,iter++){
        double value=*iter;
        for(int i=0;i<lenIn;i++){
            if(in[i]==value)
                location[i]=m;
        }
    }
    return vec;
}
int main(int argc, char *argv[]){    QCoreApplication a(argc, argv);
     double labels[10]={1,1,1,3,3,3,2,2,2,4};     int location[10];     uniqueAndSort(labels,location,10);     cout<<"labels: ";     for(int i=0;i<10;i++)        cout<<labels[i]<<" ";     cout<<endl;     cout<<"location: ";     for(int i=0;i<10;i++)        cout<<location[i]<<" ";     cout<<endl;
    return a.exec();}
运行结果分析:

排序的结果数组A为:4,3,2,1这里函数没有返回,需要可以返回。

location表示labels中的元素在A中的位置,1在A中位置为3, 3在A中位置为1,2在A中位置为2,4在A中位置为0,所以location的结果为:3,3,3,1,1,1,2,2,2,0



















0 0
原创粉丝点击