现在的位置: 首页 > 综合 > 正文

OpenCV中矩阵类详解之二:CvMat

2014年09月05日 ⁄ 综合 ⁄ 共 3330字 ⁄ 字号 评论关闭
  • 综述

    • OpenCV中矩阵CvMat是一个基础的数据结构,在CvCore中(cxcore.h或者core.hpp);
    • OpenCV将向量作为1维矩阵处理,矩阵按行存储,每行有若干字节的校整;
    • 在较早版本里面,CvMat使用的是C语言实现的struct,较新的版本里面有C++实现的class(Mat类)。
  • CvMat的定义
typedef struct CvMat
 {
  int type; /* CvMat 标识 (CV_MAT_MAGIC_VAL), 元素类型和标记 */
  int step; /* 以字节为单位的行数据长度*/
  int* refcount; /* 数据引用计数 */
  union
   {
    uchar* ptr;
    short* s;
    int* i;
    float* fl;
    double* db;
   } data; /* data 指针 */
  #ifdef __cplusplus
  union
   {
     int rows;
     int height;
   };
  union
   {
     int cols;
     int width;
   };
  #else
   int rows; /* 行数 */
   int cols; /* 列数*/
  #endif
 } CvMat;
  • 创建矩阵,分配矩阵空间
//1.用cvCreateMat创建:CvMat* cvCreateMat(int rows, int cols, int type);
// type: 矩阵元素类型. 格式为CV_<bit_depth>(S|U|F)C<number_of_channels>.  
// 例如: CV_8UC1 表示8位无符号单通道矩阵, CV_32SC2表示32位有符号双通道矩阵.
CvMat* M = cvCreateMat(4,4,CV_32FC1);  
//释放矩阵空间
cvReleaseMat(&M); 
//2.从数组创建矩阵
double a[] = { 1,   2,   3,   4,   5,   6,   7,   8, 9, 10, 11, 12 };  
CvMat Ma=cvMat(3, 4, CV_64FC1, a);  

  • 初始化矩阵
//1.使用cvMat初始化
double a[] = { 1,   2,   3,   4,   5,   6,   7,   8, 9, 10, 11, 12 };  
CvMat Ma=cvMat(3, 4, CV_64FC1, a);   

//2.使用cvInitMatHeader初始化
CvMat Ma;  
cvInitMatHeader(&Ma, 3, 4, CV_64FC1, a);  
  • 复制矩阵
  • 存取矩阵元素
假设需要存取一个2维浮点矩阵的第(i,j)个元素:
//1.间接存取矩阵元素
cvmSet(M,i,j,2.0); // Set M(i,j)   
t = cvmGet(M,i,j); // Get M(i,j)  
 
//2.直接存取,假设使用4-字节校正:
CvMat* M = cvCreateMat(4,4,CV_32FC1);  
int n = M->cols;  
float *data = M->data.fl;  
data[i*n+j] = 3.0;  
 
//3.直接存取,校正字节任意:
[cpp] view plaincopyprint?
CvMat* M = cvCreateMat(4,4,CV_32FC1);  
int step = M->step/sizeof(float);  
float *data = M->data.fl;  
(data+i*step)[j] = 3.0;  
 
//4.直接存取一个初始化的矩阵元素:
double a[16];  
CvMat Ma = cvMat(3, 4, CV_64FC1, a);  
a[i*4+j] = 2.0; // Ma(i,j)=2.0;  

  • 矩阵/向量操作(多个)

//1.矩阵-矩阵操作:
CvMat *Ma, *Mb, *Mc;  
cvAdd(Ma, Mb, Mc);       // Ma+Mb    -> Mc   
cvSub(Ma, Mb, Mc);       // Ma-Mb    -> Mc   
cvMatMul(Ma, Mb, Mc);    // Ma*Mb    -> Mc  
 
//2.按元素的矩阵操作:
CvMat *Ma, *Mb, *Mc;  
cvMul(Ma, Mb, Mc);       // Ma.*Mb   -> Mc   
cvDiv(Ma, Mb, Mc);       // Ma./Mb   -> Mc   
cvAddS(Ma, cvScalar(-10.0), Mc); // Ma.-10 -> Mc  
 
//3.向量乘积:
double va[] = {1, 2, 3};  
double vb[] = {0, 0, 1};  
double vc[3];  
CvMat Va=cvMat(3, 1, CV_64FC1, va);  
CvMat Vb=cvMat(3, 1, CV_64FC1, vb);  
CvMat Vc=cvMat(3, 1, CV_64FC1, vc);  
double res=cvDotProduct(&Va,&Vb); // 点乘:    Va . Vb -> res   
cvCrossProduct(&Va, &Vb, &Vc);     // 向量积: Va x Vb -> Vc
//注意 Va, Vb, Vc 在向量积中向量元素个数须相同
  • 矩阵/向量操作(单个)
//1.矩阵操作:
CvMat *Ma, *Mb;  
cvTranspose(Ma, Mb);       // transpose(Ma) -> Mb (不能对自身进行转置)   
CvScalar t = cvTrace(Ma); // trace(Ma) -> t.val[0]    
double d = cvDet(Ma);      // det(Ma) -> d   
cvInvert(Ma, Mb);          // inv(Ma) -> Mb  
 
//2.非齐次线性系统求解:
CvMat* A   = cvCreateMat(3,3,CV_32FC1);  
CvMat* x   = cvCreateMat(3,1,CV_32FC1);  
CvMat* b   = cvCreateMat(3,1,CV_32FC1);  
cvSolve(&A, &b, &x);     // solve (Ax=b) for x  
 
//3.特征值分析(针对对称矩阵):
CvMat* A   = cvCreateMat(3,3,CV_32FC1);  
CvMat* E   = cvCreateMat(3,3,CV_32FC1);  
CvMat* l   = cvCreateMat(3,1,CV_32FC1);  
cvEigenVV(&A, &E, &l);   // l = A的特征值 (降序排列) ,  E = 对应的特征向量 (每行)  
 
//4.奇异值分解SVD:
[cpp] view plaincopyprint?
CvMat* A   = cvCreateMat(3,3,CV_32FC1);  
CvMat* U   = cvCreateMat(3,3,CV_32FC1);  
CvMat* D   = cvCreateMat(3,3,CV_32FC1);  
CvMat* V = cvCreateMat(3,3,CV_32FC1);  
cvSVD(A, D, U, V, CV_SVD_U_T|CV_SVD_V_T); // A = U D V^T :这里的标志CV_SVD_U_T|CV_SVD_V_T使得 U 和 V 返回时被转置
  • 一个示例
// test for cvCreateMat

#include "cxcore.h"

#include <cstdio>

//void Create(CvMat* mat,int rows,int cols)
//一开始使用的是注释掉的那一行,在调用这个函数之后,mat本应该被初始化的,但在后面的访问中会出现问题,后来将参数改为指针引用,才解决错误
void Create(CvMat*& mat,int rows,int cols)
{    
    mat = cvCreateMat(rows,cols,CV_32FC1);
}

void Init(CvMat* mat)
{
    int i=0,j=0,k=0;
    int rows = mat->rows;
    int cols = mat->cols;
    for(i=0;i<rows;i++)
    {
        for(j=0;j<cols;j++)
        {
            cvmSet(mat,i,j,i+1.0*j/10);
        }
    }
}

void Print(CvMat* mat)
{
    int i=0,j=0,k=0;
    int rows = mat->rows;
    int cols = mat->cols;
    float tm = 0;
    for(i=0;i<rows;i++)
    {
        for(j=0;j<cols;j++)
        {
            tm = cvmGet(mat,i,j);
            printf("%4g ",tm);
        }
        printf("\n");
    }
}

int main()
{
    CvMat* mat;
    Create(mat,4,5);
    Init(mat);
    Print(mat);
    return 0;
}


抱歉!评论已关闭.