opencv 求矩阵的特征向量矩阵和特征值_opencv求矩阵特征值_Sugite的博客-程序员秘密

技术标签: 6-OpenCV  

因为要对一个矩阵求特征向量矩阵和特征值,本想使用MTL库,因为MTL从成熟程度和运算效率都有保证,没想到使用MTL库求特征向量矩阵和特征值还要依赖其它库,只好另辟蹊径了。幸好我找到了OpenCV,一个由intel资助的开源库,全称叫Open Source Computer Vision Library(大意就是开源计算机视觉库吧)。

 

要下载OpenCV库,可以从OpenCV中文站上下载,网址是:http://www.opencv.org.cn/index.php/Download。下载下来,我发现OpenCV库做得真的是很人性化——可以通过安装包进行安装。安装好后已经有支持VS 2005的解决方案文件了,你基本不用配置编译选项了。因为我只想里面的矩阵运算,因此这次我只编译了cxcore工程(呵呵,更深的学习还有待以后)。运行VS 2005的生成命令后生成库文件,debug模式下生成:cxcored.lib和cxcore100d.dll,release模式下生成cxcore100.dll和cxcore.lib(可以看到debug文件比release文件多了一个字母d)。

 

现在正式开始使用OpenCV库,要使用它,当然得把相关头文件拷出来,这里使用它的矩阵运算就是把安装目录下的cv文件夹拷出来,然后在你的程序中include。

 

使用库的第一个问题就是实现标准类型向库类型的转化(有时我就搞不懂,为何库不使用标准C的类型呢?比如char、int之类的,也许这个是出于效率方面的考虑吧)。OpenCV库求特征值和特征向量的函数是:

void cvEigenVV( CvArr* mat, CvArr* evects, CvArr* evals, double eps=0 );
mat 
输入对称方阵。在处理过程中将被改变。
 
evects 
特征向量输出矩阵, 连续按行存储
 
evals 
特征值输出矩阵,按降序存储(当然特征值和特征向量的排序是同步的)。
 
eps 
对角化的精确度 (典型地, DBL_EPSILON=≈10-15 就足够了)。

 

测试开始,建一个控制台程序,写一个测试函数:

 

[Csharp]  view plain copy
  1. <font size="3"><font color="#000000">void TestOpenCV(void)  
  2.   
  3. {  
  4.   
  5.   // a为输入对称方阵  
  6.   
  7.     double a[5][5] =   
  8.   
  9.     {     
  10.   
  11.        {10.0,  1.0,  2.0,  3.0,  4.0},  
  12.   
  13.        { 1.0,  9.0, -1.0,  2.0, -3.0},  
  14.   
  15.        { 2.0, -1.0,  7.0,  3.0, -5.0},  
  16.   
  17.        { 3.0,  2.0,  3.0, 12.0, -1.0},  
  18.   
  19.        { 4.0, -3.0, -5.0, -1.0, 15.0}   
  20.   
  21.     };  
  22.   
  23. // 构造输入方阵  
  24.   
  25.     CvMat SrcMatrix =cvMat(5,5, CV_64FC1,a);  
  26.   
  27.    
  28.   
  29.     double b[5][5] =   
  30.   
  31.     {     
  32.   
  33.        {0.0,  0.0,  0.0,  0.0,  0.0},  
  34.   
  35.        { 0.0,  0.0, 0.0,  0.0, 0.0},  
  36.   
  37.        { 0.0, 0.0,  0.0,  0.0, 0.0},  
  38.   
  39.        { 0.0,  0.0,  0.0, 0.0, 0.0},  
  40.   
  41.        { 0.0, 0.0, 0.0, 0.0, 0.0}   
  42.   
  43.     };  
  44.   
  45. // 构造输出特征向量矩阵  
  46.   
  47.    CvMat ProVector =cvMat(5, 5, CV_64FC1, b);  
  48.   
  49. // 构造输出特征值矩阵  
  50.   
  51.    double c[5] = {0.0,  0.0,  0.0,  0.0,  0.0};  
  52.   
  53.    
  54.   
  55.    CvMat ProValue = cvMat(5,1, CV_64FC1, c);   
  56.   
  57.    
  58.   
  59.    cvEigenVV(&SrcMatrix,&ProVector,&ProValue,1.0e-6F);  
  60.   
  61.    
  62.   
  63.    printf("/n");  
  64.   
  65.    
  66.   
  67.    int i =0;  
  68.   
  69.    int j =0;  
  70.   
  71.    for(i=0;i<5;i++)  
  72.   
  73.    {  
  74.   
  75.        for(j=0;j<5;j++)  
  76.   
  77.           printf("%f/t",cvmGet(&ProVector,i,j));  
  78.   
  79.        printf("/n");  
  80.   
  81.    }  
  82.   
  83.    for(i=0;i<5;i++)  
  84.   
  85.    {  
  86.   
  87.        printf("%f/n",cvmGet(&ProValue,i,0));  
  88.   
  89.    }  
  90.   
  91. }  
  92.   
  93. </font></font>  

使用cvEigenVV函数要注意以下三点:

1.       构造对称方阵、特征向量输出矩阵和特征值输出矩阵必须分静态数组和动态开辟内存的数组,如果是静态数组如上面测试程序就可以使用上面的构造矩阵的方式,如果是动态开辟内存的数组,那么在构造矩阵类时就要使用下面的方式:

      

[Csharp]  view plain copy
  1. <font color="#000000">double** pfMatrix =new double*[nInBandNum];  
  2.   
  3.      double** pfVector=new double*[nInBandNum];  
  4.   
  5.    
  6.   
  7.      double* pProValue =new double[nInBandNum];  
  8.   
  9.    
  10.   
  11.    
  12.   
  13.      for(i=0;i<nInBandNum;i++)  
  14.   
  15.      {  
  16.   
  17.         pfMatrix[i]=new double[nInBandNum];  
  18.   
  19.         pfVector[i]=new double[nInBandNum];  
  20.   
  21.    
  22.   
  23.         pProValue[i]= 0.0;  
  24.   
  25.      }  
  26.   
  27.      // 初始化参数  
  28.   
  29.      for(i=0;i<nInBandNum;i++)  
  30.   
  31.      {  
  32.   
  33.         for(j=0;j<nInBandNum;j++)  
  34.   
  35.         {  
  36.   
  37.             pfMatrix[i][j]=0.0;  
  38.   
  39.              pfVector[i][j] = 0.0;  
  40.   
  41.         }  
  42.   
  43.      }  
  44.   
  45.    
  46.   
  47. // 对输入对称方阵进行赋值,这一步放过  
  48.   
  49.    
  50.   
  51.    
  52.   
  53. // 下面是构造输入方阵、特征向量矩阵和特征值矩阵  
  54.   
  55.    
  56.   
  57.    CvMat *pSrcMatrix = cvCreateMat(nBandNum, nBandNum, CV_64FC1);  
  58.   
  59.    
  60.   
  61.     CvMat *pProVector =  cvCreateMat(nBandNum, nBandNum, CV_64FC1);  
  62.   
  63.    
  64.   
  65.     CvMat *pProValue  =   cvCreateMat(nBandNum,1, CV_64FC1);  
  66.   
  67.    
  68.   
  69.     for(i=0;i<nBandNum;i++)  
  70.   
  71.     {  
  72.   
  73.    
  74.   
  75.         cvmSet(pProValue,i,0,pfProVector[i]);   
  76.   
  77.        for(j=0;j<nBandNum;j++)  
  78.   
  79.        {  
  80.   
  81.            cvmSet(pSrcMatrix,i,j,pfMatrix[i][j]);   
  82.   
  83.             cvmSet(pProVector,i,j,pfVector[i][j]);   
  84.   
  85.        }  
  86.   
  87.     }  
  88.   
  89.    
  90.   
  91.     cvEigenVV(pSrcMatrix,pProVector,pProValue);  
  92.   
  93.    
  94.   
  95.     // 释放矩阵所占内存空间  
  96.   
  97. cvReleaseMat(&pSrcMatrix);  
  98.   
  99.     cvReleaseMat(&pProVector);  
  100.   
  101. cvReleaseMat(&pProValue);  
  102.   
  103. </font>  

呵呵,是不是感觉有点麻烦。我想究其原因,是因为OpenCV的矩阵类是一个一维数组,静态数组的地址是连续的,因为直接使用数组的首地址就可以访问其它数组元素,而多维动态数组的行与行的地址是不连续的,因此必须通过赋值进行构造。

 

2.       对称方阵、特征向量输出矩阵和特征值矩阵的行列必须保证匹配,比如对称方阵是5行5列,那么特征向量输出矩阵就是5行5列,特征值矩阵就是1行5列。

 

3.       特征值矩阵是降序排列的(从大到小)。

 

有兴趣的朋友可以看看cvEigenVV的源码是如何求特征向量矩阵和特征值矩阵,我大致看了一下,是使用雅可比法的。

 

参考网站及文献:

1.       http://www.opencv.org.cn/index.php

2.      OpenCV参考手册,中文翻译者:于仕琪,中科院自动化所自由软件协会,HUNNISH,阿须数码


转自:http://blog.csdn.net/clever101/article/details/2693101

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/Sugite/article/details/8673987

智能推荐

UVA-1025 A Spy in the Metro + dp_LInguistic凛的博客-程序员秘密

这题是按紫书上思路做的,算是我做的的第一个dp类的题了,看题看得很迷糊,还好书上有具体的翻译。感觉dp有点让人难受啊。#include&amp;amp;amp;amp;amp;lt;bits/stdc++.h&amp;amp;amp;amp;amp;gt;using namespace std;const int INF=1e5;int n,T;int t[250];bool has_train[250][250][2];int dp[250][250];in...

JavaScript 轮播图(含过渡动画)_weixin_30856965的博客-程序员秘密

&lt;!DOCTYPE html&gt;&lt;html&gt; &lt;head&gt; &lt;meta charset="UTF-8"&gt; &lt;title&gt;&lt;/title&gt; &lt;style type="text/css"&gt; *{ ...

【c语言】字符串逆序_c语言字符串逆序头文件_是派大星吖的博客-程序员秘密

题目:利用递归函数调用方式,将所输入的 5 个字符,以相反顺序打印出来。#include &lt;stdio.h&gt;void fun(char *arr){ if(*arr){ fun(arr+1); putchar(*arr); }}int main(){ char list[]={"Hello world!"}; fun(list); return 0;}...

【Linux】Linux/ubuntu上部署ftp服务进行上传下载文件_linuxubuntu ftp如何下载_GLL_的博客-程序员秘密

Linux/ubuntu上部署ftp服务进行上传下载文件目录一.安装并启动 FTP 服务1.安装 VSFTPD2.启动 VSFTPD3.配置用户访问目录1)新建用户主目录2)新建用户 uftp 并设置密码3)限制该用户仅能通过 FTP 访问4)修改 vsftpd 配置5)设置访问权限二.访问uftp目录1.ftp客户端(ubuntu)2.通过Fi...

kettle-8.3.0.0:在MySQL中,将A库的某张表的数据插入到B库(B库中的目的表要事先创建好) 全量同步_浅汐王的博客-程序员秘密

应用场景:为了方便演示,在数据库A和数据库B中分别创建表userA和表userB。最终目标为将数据表userA中的数据插入到数据表userB中。create database testA;use testA;create table `userA`( `id`int(10) primary key, `name` varchar(50), `age` int(...

Ubuntu更改镜像源两种方式_ubuntu改源_laoluobo76的博客-程序员秘密

所谓的镜像源:可以理解为提供下载软件的地方因为使用 apt-get 命令默认是从国外的服务器下载安装软件的,会导致下载安装速度很慢,所以需要更改成国内的镜像源服务器。一、可视化方式更改镜像源1. 打开“软件和更新”设备Ubuntu 将“软件和更新”从“设置”中独立出来了2. 选择 “Ubuntu软件 / 其它站点 / 选择最佳服务器 ”,自动选择最佳服务器,3.重新载入可用软件列表,完成更新二、手动修改镜像源如:将镜像源改成清华大学TUNA镜像源:https.

随便推点

Android VideoView 无法播放https网络视频问题_android 播放https_约翰先森不喝酒的博客-程序员秘密

最近项目里遇见一个奇葩问题,由于项目之前的服务器地址是http,然而最近又换成https的,本来从不安全的证书换成安全的证书一切应该ok,但重新打包运行却出现了新问题,(怀疑证书压根就是不安全的)1 项目主体为,cordova+vue+crosswalk 我负责写原生插件,但自从换成https的服务器地址后 项目莫名的弹出Ssl? 首先想到的是网络请求忽略不安全的证书问题,但回头想想 ...

狂卖270万块的日本​变态小黑皂,把大油头、秃头、头屑一网打尽!_普通网友的博客-程序员秘密

程序员严选丨为您甄选全球好物同事小露几乎每次见到我,都会问:“你猜我什么时候洗的头?”“一礼拜没洗了吧。”她说:“不,我昨天洗的。”油头就像油脸,头皮都没清洁干净,啥...

Static修饰的变量定义在头文件(.h)中的影响_电梯人来人往的博客-程序员秘密

static修饰的全局变量的作用范围会被限制在声明的源文件内。举个例子, a.cb.cc.h其中c.h被a.c,b.c引用, 而且c.h中定义了:static int test = 0;在编译的时候,a.c会和c.h一起编译, 然后b.c也会和c.h一起编译, 但是要注意, 编译器分别编译这两组文件的时候, 变量test会分别分配地址, 然后初始值也都为0;这就意味着, 在a.c中如果调用了tes...

编程小白的第一本Python入门书学习笔记_《编程小白的python入门书》pdf_darerD的博客-程序员秘密

编程小白的第一本Python入门书学习笔记最近在学习Python的过程中,发现一本对小白非常友好的入门书-《编程小白的第一本Python入门书》,书中对知识点的讲解很易懂,一些以前不太理解的概念,在看完这本书之后也有眉目了。这里主要介绍下自己学习时做的一些笔记,如果其中有理解错误的地方,麻烦评论或者私信告知。有幕布账号的小伙伴也可以去幕布链接文章目录编程小白的第一本Python入门书学习笔...

PowerBuilder鼠标移入移出事件_happymagic的博客-程序员秘密

PowerBuilder中只有窗口和富文本有mouse事件外,其他都没有PowerBuiler中没有鼠标移入移出的直接事件,需要我们自己定义1.首先需要定义一个结构,用来存储鼠标的坐标(position)2.声明两个全局外部函数FUNCTION ulong GetCursorPos(ref position lpPoint) LIBRARY "user32.dll"FUNCTION ulong ScreenToClient(ulong hwnd,ref position lpPoint)

TBB之concurrent_hash_map_健雄的博客-程序员秘密

Intel TBB 提供高并发的容器类,Windows或者Linux线程能使用这些容器类或者和基于task编程相结合(TBB)。一个并发容器允许多线程同时对容器访问和更改条例,典型的C++STL容器类不允许 并发更新,尝试并行更改他们引起恶化容器。STL容器能使用互斥锁来包装,目的让他们安全访问,通过只让一个线程同时操作一个容器,但是这种方式消除了并行,限制了并行提速。Intel TBB提供的容器有

推荐文章

热门文章

相关标签