最近在做基于双目视觉的三维重建。比较opencv和matlab工具箱的立体标定结果精度时,发现貌似如果手工选取角点不那么离谱的话,matlab标定结果精度更高也更鲁棒。就想先用matlab标定好相机,再把结果供opencv函数加载使用。如何将Matlab标定结果的.mat文件转成需要的CvMat矩阵,就是本篇博客所要讲的。

主要参考:http://www.jianshu.com/p/ad6a2f8a3fc8

这里分以下三步来讲:

1、先在matlab中加载.mat文件成matlab中的矩阵;

(1)生成MAT文件
eg1:
>>A=[1 2;3 4];%matlab中矩阵按列保存而非opencv中按行保存
>>save mydata A;%mydata表示文件名

eg2:
>>A=[1 2;3 4];
>>B=[2 3;5 6];
>>save mydata A B;%保存多个矩阵直接将矩阵名都写上,简单方法是save mydata;回车即可则将运行空间中的所有变量都保存到文件中.

(2)从.mat文件中读取所有数据
首先将想打开的mat文件所在的目录设置为当前工作目录(cd 路径);
然后执行:load mydata;即可,想看哪个变量的值直接输入变量名回车即可.

若只想读取mat文件指定数据,eg:load mydata A;则运行空间中将不出现B

2、再将该矩阵按yml格式保存成yml文件;
matlab中int类型对应i,float类型对应f,double类型对应d.
定义了函数的.m脚本文件,若想在命令行窗口中直接调用,即使当前运行路径与脚本文件相同也需要将脚本文件所在目录添加到设置路径中才能够直接调用,否则会说该函数未定义.(在脚本中调用某个脚本函数,只需要将两个脚本文件放在同一目录下即可)

*************************创建脚本matlab2opencv.m**************************************

%该函数将matlab中的mat矩阵保存成yml文件

function matlab2opencv( variable, fileName, flag)

[rows cols] = size(variable);

% Beware of Matlab's linear indexing
variable = variable';

% Write mode as default
if ( ~exist('flag','var') )
    flag = 'w';
end

if ( ~exist(fileName,'file') || flag == 'w' )
    % New file or write mode specified
    file = fopen( fileName, 'w');%不存在则创建写入模式
    fprintf( file, '%%YAML:1.0\n');
else
    % Append mode
    file = fopen( fileName, 'a');%存在则追加模式
end

% Write variable header
fprintf( file, '%s: !!opencv-matrix\n', inputname(1));
fprintf( file, '    rows: %d\n', rows);
fprintf( file, '    cols: %d\n', cols);
fprintf( file, '    dt: d\n');%double类型
fprintf( file, '    data: [ ');

% Write variable data
for i=1:rows*cols
    fprintf( file, '%.16d', variable(i));%16表示小数点后有16位
    if (i == rows*cols), break, end
    if mod(i+1,4) == 0
        fprintf( file, ',\n        ');
    else
        fprintf( file, ', ');
    end
end

fprintf( file, ']\n');

fclose(file);

************************************************************************

接着就可以从.mat立体标定结果文件中提取需要的信息保存到CvMat中:

*******************************创建脚本savemat2yml.m****************************
%利用matlab2opencv函数从matlab标定结果矩阵中提取所需的数值保存到对应的yml文件中(按opencv函数所需矩阵的顺序设置值),以供opencv直接利用cvLoad等加载调用.

cd D:\MATLAB\R2014a\toolbox\TOOLBOX_calib\calib_images;%切换到立体标定结果的目录下
load Calib_Results_stereo.mat;%加载标定结果矩阵

%左摄像机内参数矩阵3x3
%fx 0 cx
%0 fy cy
%0 0 1
M1(1,1)=fc_right(1); M1(1,2)=0;           M1(1,3)=cc_right(1);
M1(2,1)=0;           M1(2,2)=fc_right(2); M1(2,3)=cc_right(2);
M1(3,1)=0;           M1(3,2)=0;           M1(3,3)=1;

%左畸变参数向量1x5(貌似也可以是5x1则直接用),记录的顺序为k1,k2,p1,p2,k3
D1(1,1)=kc_right(1);
D1(1,2)=kc_right(2);
D1(1,3)=kc_right(3);
D1(1,4)=kc_right(4);
D1(1,5)=kc_right(5); %一般为0

%右摄像机内参数矩阵3x3
%fx 0 cx
%0 fy cy
%0 0 1
M2(1,1)=fc_right(1); M2(1,2)=0;           M2(1,3)=cc_right(1);
M2(2,1)=0;          M2(2,2)=fc_right(2);  M2(2,3)=cc_right(2);
M2(3,1)=0;          M2(3,2)=0;           M2(3,3)=1;

%右畸变参数向量1x5(貌似也可以是5x1则直接用),记录的顺序为k1,k2,p1,p2,k3
D2(1,1)=kc_right(1);
D2(1,2)=kc_right(2);
D2(1,3)=kc_right(3);
D2(1,4)=kc_right(4);
D2(1,5)=kc_right(5);

%摄像机间的旋转矩阵3x3,可直接用
%摄像机间的平移矩阵3x1,也可直接用

%调用matlab2opencv函数保存矩阵到yml文件
matlab2opencv(M1,'M1.yml');%注意该函数脚本要与本脚本在同一目录下或者该函数脚本已设置路径了
matlab2opencv(D1,'D1.yml');
matlab2opencv(M2,'M2.yml');
matlab2opencv(D2,'D2.yml');
matlab2opencv(R,'R.yml');
matlab2opencv(T,'T.yml');
***********************************************************************

3、最后opencv加载该yml文件,并以Mat、CvMat的格式保存到一个变量中.
若yml文件中只有一个矩阵可以直接调用cvSave和cvLoad保存和加载yml文件.eg:

 1 #include <cv.h>
2 #include <highgui.h>
3 #include<iostream>
4 using namespace std;
5
6 ostream& operator<<(ostream& out,CvMat* mat)
7 {
8 cout<<"C++方式输出矩阵:"<<endl;
9 cout<<"mat.rows="<<mat->rows<<",mat.cols="<<mat->cols<<"\n["<<endl;
10 for(int i=0;i<mat->rows;i++)
11 {
12 for(int j=0;j<mat->cols;j++)
13 {
14 //设置输出宽度为25,按左对齐,数值的有效数字位数为20(整数+小数)
15 cout<<setw(25)<<setiosflags(ios::left)<<setprecision(20)<<CV_MAT_ELEM(*mat,double,i,j);
16 }
17 if(i==mat->rows-1)
18 cout<<"\n]\n\n";
19 else
20 cout<<endl;
21 }
22 return out;
23 }
24
25
26 void main()
27 {
28 CvMat* M1=(CvMat*)cvLoad("C:/Users/shark/Desktop/M1.yml");
29 cout<<M1<<endl;
30 getchar();
31 }

博主matlab入门级,解决该问题还是花费了一定时间,望本博客对可能同是菜鸟的你有所帮助。

Matlab立体标定mat转换成Opencv的CvMat的更多相关文章

  1. python base64 编解码,转换成Opencv,PIL.Image图片格式

    二进制打开图片文件,base64编解码,转成Opencv格式: # coding: utf-8 import base64 import numpy as np import cv2 img_file ...

  2. cv::mat转换成QImage的问题

    在进行cv::mat转换为QImage过程中,经常出现问题: cv::Mat image; ...QImage img=QImage((const unsigned char*)(image.data ...

  3. Matlab 将RGB 图像转换成YCrCb图像

    >> im = imread('trees.jpg');>> imshow(im)>> ycrcb_trees = rgb2ycbcr(im);>> f ...

  4. 深度图从ros数据类型转换成opencv数据类型

    摘要:ros下,利用realsense D435采集深度图,并将其转换成opencv的数据类型. 一. RGBD图像采集 通过image_transport包,根据给定的采集速度从realsense ...

  5. OpenCV 学习笔记(9)RGB转换成灰度图像的一个常用公式Gray = R*0.299 + G*0.587 + B*0.114

    https://blog.csdn.net/fly_wt/article/details/86432886 RGB转换成灰度图像的一个常用公式是:Gray = R*0.299 + G*0.587 + ...

  6. matlab stereo_gui立体标定

    http://www.vision.caltech.edu/bouguetj/calib_doc/index.html#examples 文档中举了几个例子,有关双目的是第5个, 这个例子展示了如何使 ...

  7. 「新手必看」Python+Opencv实现摄像头调用RGB图像并转换成HSV模型

    在ROS机器人的应用开发中,调用摄像头进行机器视觉处理是比较常见的方法,现在把利用opencv和python语言实现摄像头调用并转换成HSV模型的方法分享出来,希望能对学习ROS机器人的新手们一点帮助 ...

  8. 实现同时将一批.bmp文件转换成.mat格式

    %% 功能:实现同时对一批.bmp文件的转换成.mat格式PicFormat = {'*.bmp','Bitmap image (*.bmp)';... '*.jpg','JPEG image (*. ...

  9. 【小工具系列】Python + OpenCV 图片序列转换成视频

    图片序列转换成视频 最近一直在找一个工具,能够将一堆图片转化成视频.网上找了一些小软件,还有 win10 的照片自带的视频制作功能,都不是很满意. 又不想下载那些专业的视频剪辑软件大材小用. 然后找到 ...

随机推荐

  1. UVa 481 - What Goes Up

    题目大意:给你一系列数,找出它的最长(严格)递增子序列. 由于数据量较大,使用O(n2)的LIS算法会超时,要使用O(nlogn)的LIS算法,这里有详细的介绍. #include <cstdi ...

  2. spring security 跨域防伪攻击

    applicationContext-security.xml中配置 <http use-expressions="true" disable-url-rewriting=& ...

  3. OD提示 "为了执行系统不支持的动作, OllyICE 在这个被调试的程序中注入了一点代码, 但是经过5秒仍未收到响应..." 解决办法

    别的OD就可以,我自己整合过的一个很顺手的OD就是不行,最后找到了解决办法: 转自:http://bbs.pediy.com/showthread.PHP?t=97629 -------------- ...

  4. JMeter使用代理录制脚本

    用JMeter做接口测试,有时候接口数量比较多,用录制方式可以节省很多时间,录制接口可以配合badboy使用,但是badboy访问的浏览器是基于ie6的,基本上现在的网站不会对ie6做兼容了,使用代理 ...

  5. docker tag

    docker tag 命令以及其中的一些概念--之我见 1.  重要的本质的东西是 image - docker 最有用的东西是image,这个应该可以被大部分人接受 - 查看官网的 tag 命令,一 ...

  6. #搜索# #BFS# #优先队列# ----- OpenJudge鸣人和佐助

    OpenJudge 6044:鸣人和佐助 总时间限制: 1000ms  内存限制: 65536kB 描述 佐助被大蛇丸诱骗走了,鸣人在多少时间内能追上他呢? 已知一张地图(以二维矩阵的形式表示)以及佐 ...

  7. 【angularjs】【学习心得】路由继续研究篇

    原文:http://www.imooc.com/wenda/detail/236998 其实路由的功能是比较复杂的,我们实际应用中页面的状态也是非常多的,上面简单的路由是肯定不能满足我们的需求的,所以 ...

  8. [ Android 五种数据存储方式之四 ] —— ContentProvider存储数据

    Android这个系统和其他的操作系统还不太一样,我们需要记住的是,数据在Android当中是私有的,当然这些数据包括文件数据和数据库数据以及一些其他类型的数据.那这个时候有读者就会提出问题,难道两个 ...

  9. because of many connection errors; unblock with &#39;mysqladmin flush-hosts

    环境:linux,mysql5.5.37 错误:Host is blocked because of many connection errors; unblock with 'mysqladmin ...

  10. SQL server 定时自动执行SQL存储过程

    当一个存储过程是为了生成报表,并且是周期性的,则不需要人工干预,由SQL作业定时自动执行些SQL存储过程即可. 本示例,假设已需要定时执行的存储过程为:Pr_test 工具/原料 SQL Server ...