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

智能推荐

1010 一元多项式求导 (25 分) C语言_墨海之南的博客-程序员秘密

1010 一元多项式求导 (25 分)设计函数求一元多项式的导数。(注:x^​n(n为整数)的一阶导数为n*x^(n-1)​)输入格式:以指数递降方式输入多项式非零项系数和指数(绝对值均为不超过 1000 的整数)。数字间以空格分隔。输出格式:以与输入相同的格式输出导数多项式非零项的系数和指数。数字间以空格分隔,但结尾不能有多余空格。注意“零多项式”的指数和系数都是 0,但是表示为 0...

Delphi 的字符及字符串[6] - Char(AnsiChar)、WideChar 与其编码的相互转换_weixin_34364071的博客-程序员秘密

//Char 类型与其编码值的转换:var b: Byte; c: Char;begin b := Ord('A'); {返回: 65} b := Ord(#65); {返回: 65} b := Ord($41); {返回: 65} b := Ord(#$41); {返回: 65} b := Byte('A'); {返回: ...

Centos7.6_1810安装LEMP过程详解(nginx1.14.2+php7.3.1+MariaDB10.3.12)_lggirls的博客-程序员秘密

    经过两天的搜索和学习,终于在CentOS7.6 1810版本的最小化安装服务器上完成了LEMP搭建,全都用的是最新的稳定版组件(截止2019-01-26),这里做个记录,以便后继再应用到。 1.nginx1.14.2的安装nginx的安装完全参考nginx官网的安装步骤即可。1.1在centos7 的 /etc/yum.repos.d目录中新建一个nginx的源地址引用文件...

DL之LSTM:基于《wonderland爱丽丝梦游仙境记》小说数据集利用LSTM算法(层加深,基于keras)对单个character字符预测_单字符预测_一个处女座的程序猿的博客-程序员秘密

DL之LSTM:基于《wonderland爱丽丝梦游仙境记》小说数据集利用LSTM算法(层加深,基于keras)对单个character字符预测目录基于《wonderland爱丽丝梦游仙境记》小说数据集利用LSTM算法(层加深,基于keras)对单个character字符预测设计思路输出结果核心代码基于《wonderland爱丽丝梦游仙境记》小说数据集利用LSTM算法(层加深,基于keras)对单个character字符预测设计思路数据集下...

HTML input 输入限制_strong90的博客-程序员秘密

1.只能输入数字和英文的:&amp;lt;input onkeyup=&quot;value=value.replace(/[/W]/g,'') &quot;onbeforepaste=&quot;clipboardData.setData('text',clipboardData.getData('text').replace(/[^/d]/g,''))&quot;ID=&quot;Text1&quot; NAME=&quot;Text1&quot;&amp;gt;2.只能输入数字...

解决问题 “You don't have permission to access /index.html on this server.”_weixin_33802505的博客-程序员秘密

前几天装一个linux 企业版5.0安装了apache,打开测试页面的时候出现如下错误:ForbiddenYou don't have permission to access /index.html on this server.开始我以为我配置出错,花半天时间都没有搞定,今天终于搞定了.原因:index.html是用root用户建的文件,apache权限不够。解决方法:...

随便推点

数据库应用_表结构_键值_ansheng0239的博客-程序员秘密

随笔结构:1.数据导入导出; 2.管理表格的记录; 3.数据的匹配条件.一,数据的导入与导出* mysql默认的导入导出路径为/var/lib/mysql-files/* 定义路径的变量名secure_file_priv* 修改路径的方式:1).创建目录mkdir /myfile; 2).赋权chown mysql ...

聚合函数——nvl()_nvl算聚合函数吗?_巴达子的博客-程序员秘密

当某个为空的字段需要被显示成其他值时使用。nvl(字段名,显示值)如:nvl(name,"未定义")这样当表中的name字段为空时,就会返回"未定义"。

UVM实战CH2:04 验证平台加入objection机制_m0_52174404的博客-程序员秘密

验证平台加入objection机制objection机制my_driver中的main_phase是一个完整的任务,上节输出了“main_phase is called”,但是“data is drived”并没有输出。main_phase执行过程中中止。UVM中通过objection机制来控制验证平台的关闭UVM会检查是否有objection被提起(raise_objection),如果有,那么等待这个objection被撤销(drop_objection)后停止仿真;如果没有,则马上结束当前

JSP开发之JSP 标准标签库(JSTL)之SQL标签update标签的使用_luyaran的博客-程序员秘密

&amp;lt;sql:update&amp;gt;标签用来执行一个没有返回值的SQL语句,比如SQL INSERT,UPDATE,DELETE语句。感受下语法:&amp;lt;sql:update var=&quot;&amp;lt;string&amp;gt;&quot; scope=&quot;&amp;lt;string&amp;gt;&quot; sql=&quot;&amp;lt;string&amp;gt;&quot; dataSource=&quot;&amp;lt;string&am

软件园里的流氓(1)——2005年的故事_CommerceServer的博客-程序员秘密

Normal 0 0 2 false false false MicrosoftInternetExplorer4 <!-- /* Font Definitio

Emeditor正则表达式语法_emedit 搜索16进制_draling的博客-程序员秘密

Emeditor正则表达式语法(Regular expression, 简写Regexes或Regex)1 普通字符普通字符是指除了 ".", "*", "?", "+", "(", ")", "{", "}", "[", "]", "^", "$" 和 "\" 这些特殊字符之外的所有其他字符。而这些特殊字符也可以通过前面加上"\"前缀而变为普通字符。比如, 搜索"CCF"即为在文本中

推荐文章

热门文章

相关标签