kwseeker

学编程:找代码,读代码,改代码,写代码;少看书。但少看不是不看,看一本书要限制在一天内。任务是通读书中主要的概念,明白大致是干什么用的,形成一个大概的框架;然后一周内干掉书中全部代码,代码不理解再浏览书中相关章节,注意是浏览。或者刷博客。代码实在刷不懂,可以先刷后面,待日后重新刷;因为书中代码有些部分可能出自后面的章节。代码总是在多次刷过之后,拨开乌云见日月的。。。

导航

opencv矩阵总结

OpenCV 矩阵操作 CvMat
转自:http://hi.baidu.com/xiaoduo170/blog/item/10fe5e3f0fd252e455e72380.html
每回用矩阵都要查,这回查到一个比较正确齐全的,放在自己的博客上以后可查
  • 综述:
    • OpenCV有针对矩阵操作的C语言函数. 许多其他方法提供了更加方便的C++接口,其效率与OpenCV一样.
    • OpenCV将向量作为1维矩阵处理.
    • 矩阵按行存储,每行有4字节的校整.
  • 分配矩阵空间:
    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);
  • 释放矩阵空间:
    CvMat* M = cvCreateMat(4,4,CV_32FC1); cvReleaseMat(&M);
  • 复制矩阵:
    CvMat* M1 = cvCreateMat(4,4,CV_32FC1);
    CvMat* M2;
    M2=cvCloneMat(M1);
  • 初始化矩阵:
    double a[] = { 1, 2, 3, 4,
    5, 6, 7, 8, 9, 10, 11, 12 };

    CvMat Ma=cvMat(3, 4, CV_64FC1, a);
    另一种方法:
    CvMat Ma; cvInitMatHeader(&Ma, 3, 4, CV_64FC1, a);
  • 初始化矩阵为单位阵:
    CvMat* M = cvCreateMat(4,4,CV_32FC1); cvSetIdentity(M); // 这里似乎有问题,不成功

存取矩阵元素

  • 假设需要存取一个2维浮点矩阵的第(i,j)个元素.
  • 间接存取矩阵元素:
  • cvmSet(M,i,j,2.0); // Set M(i,j) t = cvmGet(M,i,j); // Get M(i,j)
  • 直接存取,假设使用4-字节校正:
    CvMat* M = cvCreateMat(4,4,CV_32FC1); int n = M->cols; float *data = M->data.fl; data[i*n+j] = 3.0;
  • 直接存取,校正字节任意:
    CvMat* M = cvCreateMat(4,4,CV_32FC1);
    int step = M->step/sizeof(float);
    float *data = M->data.fl;

    (data+i*step)[j] = 3.0;
  • 直接存取一个初始化的矩阵元素:
    double a[16]; CvMat Ma = cvMat(3, 4, CV_64FC1, a); a[i*4+j] = 2.0; // Ma(i,j)=2.0;

矩阵/向量操作

  • 矩阵-矩阵操作:
    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
  • 按元素的矩阵操作:
    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
  • 向量乘积:
    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 end{verbatim}

    注意 Va, Vb, Vc 在向量积中向量元素个数须相同.

  • 单矩阵操作:
    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
  • 非齐次线性系统求解:
    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
  • 特征值分析(针对对称矩阵):
    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 = 对应的特征向量 (每行)
  • 奇异值分解SVD:
    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

    标号使得 U 和 V 返回时被转置(若没有转置标号,则有问题不成功!!!).

 

访问CvMat数据块(矩阵维度与通道)

通过opencv的函数来访问矩阵的数据
 
cvGet*D,cvSet*D
 
cvGetReal1D, cvGetReal2D, cvGetReal3D, cvGetRealND
cvGet1D, cvGet2D, cvGet3D, cvGetND
cvSet*D,也有相应的函数系列
这些函数的缺点是,效率低
 
Real表示对单通道矩阵的访问,没有Real的表示对多通道矩阵的访问
 
从数据创建矩阵
 
 //数据
                 float data[18] =
                {
                                30,60,40,60, 50,40,
                                67,88,55,33, 22,97,
                                59,69,32,46, 25,45
                };
 
(1)单通道,可以想象有这样一个矩阵
访问CvMat数据块(矩阵维度与通道)
 
(2)双通道(理解为一个元素包含两个数字)

访问CvMat数据块(矩阵维度与通道)
 
 
可以理解为这样一个矩阵
二通道矩阵可以理解为拆分为两个单通道的矩阵
 
访问CvMat数据块(矩阵维度与通道)

 
(3)三通道
访问CvMat数据块(矩阵维度与通道)


 
维 体现为它的坐标
 
代码:
 
#include "stdafx.h"
#include "cv.h"
#include "highgui.h"
#include "cxcore.h"
//#include "cxtypes.h"
 
int main(int argc, char* argv[])
{
                 //数据
                 float data[18] =
                {
                                30,60,40,60, 50,40,
        67,88,55,33, 22,97,
        59,69,32,46, 25,45
                };
 
                CvMat mat;
                 //三行六列单通道
                 //cvInitMatHeader(&mat,3,6,CV_32FC1,data);
                 //三行三列双通道
                 //cvInitMatHeader(&mat,3,3,CV_32FC2,data);
                 //三行二列三通道
                cvInitMatHeader(&mat,3,2,CV_32FC3,data);
 
                 
 
                 for (int y=0;y<mat.rows;y++)
                {
                                 for (int x=0;x<mat.cols;x++)
                                {
                                                 //取矩阵里面的行列
                                                 //float value = cvGetReal2D(&mat,y,x);
                                                CvScalar value = cvGet2D(&mat,y,x);
                                                 //CvScalar value = cvGetReal3D(&mat,z,y,x);
                                                printf( "(%f  %f  %f) " ,value.val[0],value.val[1],value.val[2]);
                                }
                                printf( "\n" );
                }
 
                 return 0;
}

 

posted on 2014-10-12 15:45  kwseeker  阅读(293)  评论(0编辑  收藏  举报