matlab 手机如何保存动态图片图

Posts - 56,
Articles - 6,
Comments - 32
success belongs to the one with clear and long-term goals!
13:35 by DarkHorse, ... 阅读,
如题,多的就不说了,先上一个效果:
每隔0.1秒,绿色的直线转动一个角度。
再看看代码如何实现:
fuction main
%%%%%%%%%%%%%%%%%%%%%%%%%%主函数%%%%%%%%%%%%%%%%%%%%%%%%%%%
bTimeStep = 0.1; %%重绘时间间隔
bSaveAVI = 1;
%%是否将重绘过程保存到视频文件
initDegree = 0; %%初始位置,位于零度角
if bSaveAVI
aviname = input('input the file name for avi: ','s');
aviobj=avifile(aviname);
%定义一个视频文件用来存动画
aviobj.quality=60;
aviobj.Fps=5;
r = 1; %%背景图中圆的半径
DrawBackGround(r); %%画背景
[xcoor,ycoor] = GetCorrByDegree(r, TransDegToRad(initDegree)); %%画初始位置,零度角
x = [0 xcoor];
y = [0 ycoor];
h = plot(x,y,'g-');
degreeStepForTest = 20;%%用于测试用的角度增量
for sita = initDegree+degreeStepForTest:degreeStepForTest:360
[xcoor,ycoor] = GetCorrByDegree(r, TransDegToRad(sita)); %%获取当前的角度对应的坐标
x = [0 xcoor];
y = [0 ycoor];
set(h,'XData',x,'YData',y); %%重置绘图对象
if bSaveAVI
frame=getframe(gca);
%把图像存入视频文件中
im=frame2im(frame);
aviobj=addframe(aviobj,im);
pause(bTimeStep); %%暂停间隔
if bSaveAVI
aviobj=close(aviobj); %%关闭视频文件句柄
%%%%%%%%%%%%%%%%%%%%%%%%%%子函数%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function radian = TransDegToRad(degree)
%%将角度转换为弧度
radian = degree * pi / 180;
function [x y] = GetCorrByDegree(R, Degree)
%%根据角度和半径计算当前点的坐标
x = R * cos(Degree);
y = R * sin(Degree);
function DrawBackGround(r)
%%%画背景图
x = linspace(-r,r,1000);
y1 = sqrt(r^2-x.^2);
plot(x,y1,'b-'); %%画上半圆
y2 = -sqrt(r^2-x.^2); %%画下半圆
plot(x,y2,'b-');
plot([0 0],[-r r],'b-'); %%画纵直径
plot([-r r],[0 0],'b-'); %%画横直径
注释写的很详细,不多说了。&& 查看话题
matlab图像保存
下面是我的matlab代码,很简单的运算,A是那一天白天的温度数据,B是那一天晚上的温度数据,mean就是计算出来的那一天的平均温度,现在就是想把这个结果也保存为tif格式,这里应该再怎么办啊?求教!!!之前用过imwrite函数,但是这个保存出来的数据值不是原来的mean值了:数据类型从double变成了uint8&&平均温度值变成了0和255这两个值。。。
A=double(imread('247116_.LTD.V1.TIF'));
B=double(imread('247117_.LTN.V1.TIF'));
mean=(A+B)/2;
QQ图片36.jpg
这是我在帮助文档查到的关于imwrite函数描述里面的一条&&是不是这个原因造成的?
帮助文档.jpg
A=double(imread('247116_.LTD.V1.tif'));
B=double(imread('247117_.LTN.V1.tif'));
C=(A+B)/2;
imwrite(uint8(C),);
这个段代码我刚试过,没有问题,将两幅图相加后平均了一下,你的问题出现了二值化,不知道你是怎么将据类型从double变成了uint8 ?先试试这个吧 两种做法,第一种如楼上所示,直接imwrite(image,);
第二种做法:如果用 Vec 表示图像向量,
Vec = (Vec-min(Vec))/(max(Vec)-min(Vec));
image = reshape(Vec, row,col);
imwrite(virImg,);
我觉得这两种方法第二种会更好,因为增加了保存图像的对比度,更加清晰!第二种做一个归一化处理,使得图像数据都在0-1之间,可以用MATLAB直接写进文件!
此外,imwrite函数有一个好处,保存的图像都是原始图像,没有白边! 我错了,忘了一件事
imwrite(uint8(image),);
上面回复少了一个unit8,这是图像的类型! 两种做法,第一种如楼上所示,直接imwrite(uint8(image),);
第二种做法:如果用 Vec 表示图像向量,
Vec = (Vec-min(Vec))/(max(Vec)-min(Vec));
image = reshape(Vec, row,col);
imwrite(image ,);
我觉得这两种方法第二种会更好,因为增加了保存图像的对比度,更加清晰!第二种做一个归一化处理,使得图像数据都在0-1之间,可以用MATLAB直接写进文件!
此外,imwrite函数有一个好处,保存的图像都是原始图像,没有白边!matlab中的动态图怎么保存到word里面_百度知道
matlab中的动态图怎么保存到word里面
提问者采纳
第二种方法保存的图没有第一种的效果好、tif等)一般都是选择jpg或tif格式、选择File-&gt、bmp、选择edit-&gt,然后把图粘贴到word里2。不过个人觉得、copy figure,可以把图存成各种格式(export主要有两种操作方式1、jpg
这两问保存的是个静态的图,不是动态的
动态图纸jif,用第二种试试
还是不行,没法选择jif的形式
gif写错了,或加入代码先avi保存再转gif格式,或用snigt录制下来。网上:本来就可以保存为fig,eps,jpeg,gif,png,bmp等格式的 包含了gif 不知你指的动态图是否gif? 如果是一幅一幅的程序生成可以在生成后用saveas(gca,filename,fileformat)再执行下一条命令
还是不行,我的图是用程序编出来的动态图,现在想让这个动态图直接加如到一个word文档里面
不支持,用,或用软件录制保存再插入W0rd
提问者评价
其他类似问题
为您推荐:
matlab的相关知识
等待您来回答
下载知道APP
随时随地咨询
出门在外也不愁1889人阅读
之前在网上也没有现成的代码,现在把库中的sample拿出来,分享下
结合大牛的博客,好好学习下:
stereo_match.cpp
calibration
Created by Victor
Eruhimov on 1/18/10.
Copyright 2010 Argus Corp. All rights reserved.
#include &opencv2/calib3d/calib3d.hpp&
#include &opencv2/imgproc/imgproc.hpp&
#include &opencv2/highgui/highgui.hpp&
#include &opencv2/contrib/contrib.hpp&
#include &stdio.h&
static void print_help()
printf(&\nDemo stereo matching converting L and R images into disparity and point clouds\n&);
printf(&\nUsage: stereo_match &left_image& &right_image& [--algorithm=bm|sgbm|hh|var] [--blocksize=&block_size&]\n&
&[--max-disparity=&max_disparity&] [--scale=scale_factor&] [-i &intrinsic_filename&] [-e &extrinsic_filename&]\n&
&[--no-display] [-o &disparity_image&] [-p &point_cloud_file&]\n&);
static void saveXYZ(const char* filename, const Mat& mat)
const double max_z = 1.0e4;
FILE* fp = fopen(filename, &wt&);
for(int y = 0; y & mat. y++)
for(int x = 0; x & mat. x++)
Vec3f point = mat.at&Vec3f&(y, x);
if(fabs(point[2] - max_z) & FLT_EPSILON || fabs(point[2]) & max_z)
fprintf(fp, &%f %f %f\n&, point[0], point[1], point[2]);
fclose(fp);
int main(int argc, char** argv)
const char* algorithm_opt = &--algorithm=&;
const char* maxdisp_opt = &--max-disparity=&;
const char* blocksize_opt = &--blocksize=&;
const char* nodisplay_opt = &--no-display&;
const char* scale_opt = &--scale=&;
if(argc & 3)
print_help();
const char* img1_filename = 0;
const char* img2_filename = 0;
const char* intrinsic_filename = 0;
const char* extrinsic_filename = 0;
const char* disparity_filename = 0;
const char* point_cloud_filename = 0;
enum { STEREO_BM=0, STEREO_SGBM=1, STEREO_HH=2, STEREO_VAR=3 };
int alg = STEREO_SGBM;
int SADWindowSize = 0, numberOfDisparities = 0;
bool no_display =
float scale = 1.f;
StereoSGBM
for( int i = 1; i & i++ )
if( argv[i][0] != '-' )
if( !img1_filename )
img1_filename = argv[i];
img2_filename = argv[i];
else if( strncmp(argv[i], algorithm_opt, strlen(algorithm_opt)) == 0 )
char* _alg = argv[i] + strlen(algorithm_opt);
alg = strcmp(_alg, &bm&) == 0 ? STEREO_BM :
strcmp(_alg, &sgbm&) == 0 ? STEREO_SGBM :
strcmp(_alg, &hh&) == 0 ? STEREO_HH :
strcmp(_alg, &var&) == 0 ? STEREO_VAR : -1;
if( alg & 0 )
printf(&Command-line parameter error: Unknown stereo algorithm\n\n&);
print_help();
return -1;
else if( strncmp(argv[i], maxdisp_opt, strlen(maxdisp_opt)) == 0 )
if( sscanf( argv[i] + strlen(maxdisp_opt), &%d&, &numberOfDisparities ) != 1 ||
numberOfDisparities & 1 || numberOfDisparities % 16 != 0 )
printf(&Command-line parameter error: The max disparity (--maxdisparity=&...&) must be a positive integer divisible by 16\n&);
print_help();
return -1;
else if( strncmp(argv[i], blocksize_opt, strlen(blocksize_opt)) == 0 )
if( sscanf( argv[i] + strlen(blocksize_opt), &%d&, &SADWindowSize ) != 1 ||
SADWindowSize & 1 || SADWindowSize % 2 != 1 )
printf(&Command-line parameter error: The block size (--blocksize=&...&) must be a positive odd number\n&);
return -1;
else if( strncmp(argv[i], scale_opt, strlen(scale_opt)) == 0 )
if( sscanf( argv[i] + strlen(scale_opt), &%f&, &scale ) != 1 || scale & 0 )
printf(&Command-line parameter error: The scale factor (--scale=&...&) must be a positive floating-point number\n&);
return -1;
else if( strcmp(argv[i], nodisplay_opt) == 0 )
no_display =
else if( strcmp(argv[i], &-i& ) == 0 )
intrinsic_filename = argv[++i];
else if( strcmp(argv[i], &-e& ) == 0 )
extrinsic_filename = argv[++i];
else if( strcmp(argv[i], &-o& ) == 0 )
disparity_filename = argv[++i];
else if( strcmp(argv[i], &-p& ) == 0 )
point_cloud_filename = argv[++i];
printf(&Command-line parameter error: unknown option %s\n&, argv[i]);
return -1;
if( !img1_filename || !img2_filename )
printf(&Command-line parameter error: both left and right images must be specified\n&);
return -1;
if( (intrinsic_filename != 0) ^ (extrinsic_filename != 0) )
printf(&Command-line parameter error: either both intrinsic and extrinsic parameters must be specified, or none of them (when the stereo pair is already rectified)\n&);
return -1;
if( extrinsic_filename == 0 && point_cloud_filename )
printf(&Command-line parameter error: extrinsic and intrinsic parameters must be specified to compute the point cloud\n&);
return -1;
int color_mode = alg == STEREO_BM ? 0 : -1;
Mat img1 = imread(img1_filename, color_mode);
Mat img2 = imread(img2_filename, color_mode);
if( scale != 1.f )
Mat temp1, temp2;
int method = scale & 1 ? INTER_AREA : INTER_CUBIC;
resize(img1, temp1, Size(), scale, scale, method);
img1 = temp1;
resize(img2, temp2, Size(), scale, scale, method);
img2 = temp2;
Size img_size = img1.size();
Rect roi1, roi2;
if( intrinsic_filename )
// reading intrinsic parameters
FileStorage fs(intrinsic_filename, CV_STORAGE_READ);
if(!fs.isOpened())
printf(&Failed to open file %s\n&, intrinsic_filename);
return -1;
Mat M1, D1, M2, D2;
fs[&M1&] && M1;
fs[&D1&] && D1;
fs[&M2&] && M2;
fs[&D2&] && D2;
fs.open(extrinsic_filename, CV_STORAGE_READ);
if(!fs.isOpened())
printf(&Failed to open file %s\n&, extrinsic_filename);
return -1;
Mat R, T, R1, P1, R2, P2;
fs[&R&] && R;
fs[&T&] && T;
stereoRectify( M1, D1, M2, D2, img_size, R, T, R1, R2, P1, P2, Q, CALIB_ZERO_DISPARITY, -1, img_size, &roi1, &roi2 );
Mat map11, map12, map21, map22;
initUndistortRectifyMap(M1, D1, R1, P1, img_size, CV_16SC2, map11, map12);
initUndistortRectifyMap(M2, D2, R2, P2, img_size, CV_16SC2, map21, map22);
Mat img1r, img2r;
remap(img1, img1r, map11, map12, INTER_LINEAR);
remap(img2, img2r, map21, map22, INTER_LINEAR);
img1 = img1r;
img2 = img2r;
numberOfDisparities = numberOfDisparities & 0 ? numberOfDisparities : ((img_size.width/8) + 15) & -16;
bm.state-&roi1 = roi1;
bm.state-&roi2 = roi2;
bm.state-&preFilterCap = 31;
bm.state-&SADWindowSize = SADWindowSize & 0 ? SADWindowSize : 9;
bm.state-&minDisparity = 0;
bm.state-&numberOfDisparities = numberOfD
bm.state-&textureThreshold = 10;
bm.state-&uniquenessRatio = 15;
bm.state-&speckleWindowSize = 100;
bm.state-&speckleRange = 32;
bm.state-&disp12MaxDiff = 1;
sgbm.preFilterCap = 63;
sgbm.SADWindowSize = SADWindowSize & 0 ? SADWindowSize : 3;
int cn = img1.channels();
sgbm.P1 = 8*cn*sgbm.SADWindowSize*sgbm.SADWindowS
sgbm.P2 = 32*cn*sgbm.SADWindowSize*sgbm.SADWindowS
sgbm.minDisparity = 0;
sgbm.numberOfDisparities = numberOfD
sgbm.uniquenessRatio = 10;
sgbm.speckleWindowSize = bm.state-&speckleWindowS
sgbm.speckleRange = bm.state-&speckleR
sgbm.disp12MaxDiff = 1;
sgbm.fullDP = alg == STEREO_HH;
var.levels = 3;
// ignored with USE_AUTO_PARAMS
var.pyrScale = 0.5;
// ignored with USE_AUTO_PARAMS
var.nIt = 25;
var.minDisp = -numberOfD
var.maxDisp = 0;
var.poly_n = 3;
var.poly_sigma = 0.0;
var.fi = 15.0f;
var.lambda = 0.03f;
var.penalization = var.PENALIZATION_TICHONOV;
// ignored with USE_AUTO_PARAMS
var.cycle = var.CYCLE_V;
// ignored with USE_AUTO_PARAMS
var.flags = var.USE_SMART_ID | var.USE_AUTO_PARAMS | var.USE_INITIAL_DISPARITY | var.USE_MEDIAN_FILTERING ;
Mat disp, disp8;
//Mat img1p, img2p,
//copyMakeBorder(img1, img1p, 0, 0, numberOfDisparities, 0, IPL_BORDER_REPLICATE);
//copyMakeBorder(img2, img2p, 0, 0, numberOfDisparities, 0, IPL_BORDER_REPLICATE);
int64 t = getTickCount();
if( alg == STEREO_BM )
bm(img1, img2, disp);
else if( alg == STEREO_VAR ) {
var(img1, img2, disp);
else if( alg == STEREO_SGBM || alg == STEREO_HH )
sgbm(img1, img2, disp);
t = getTickCount() -
printf(&Time elapsed: %fms\n&, t*1000/getTickFrequency());
//disp = dispp.colRange(numberOfDisparities, img1p.cols);
if( alg != STEREO_VAR )
disp.convertTo(disp8, CV_8U, 255/(numberOfDisparities*16.));
disp.convertTo(disp8, CV_8U);
if( !no_display )
namedWindow(&left&, 1);
imshow(&left&, img1);
namedWindow(&right&, 1);
imshow(&right&, img2);
namedWindow(&disparity&, 0);
imshow(&disparity&, disp8);
printf(&press any key to continue...&);
fflush(stdout);
waitKey();
printf(&\n&);
if(disparity_filename)
imwrite(disparity_filename, disp8);
if(point_cloud_filename)
printf(&storing the point cloud...&);
fflush(stdout);
reprojectImageTo3D(disp, xyz, Q, true);
saveXYZ(point_cloud_filename, xyz);
printf(&\n&);
&调试参数:
view_l.png view_r.png --algorithm=bm --blocksize=5 --max-disparity=256& --scale=1.0 --no-display -o disparity.bmp
立体匹配效果:
根据大牛的代码增加一个函数:实现视差数据保存成txt又matlab显示
void saveDisp(const char* filename, const Mat& mat)
FILE* fp = fopen(filename, &wt&);
fprintf(fp, &%02d\n&, mat.rows);
fprintf(fp, &%02d\n&, mat.cols);
for(int y = 0; y & mat. y++)
for(int x = 0; x & mat. x++)
int disp = (int)mat.at&float&(y, x); // 这里视差矩阵是CV_16S 格式的,故用 short 类型读取
fprintf(fp, &%d\n&, disp);
// 若视差矩阵是 CV_32F 格式,则用 float 类型读取
//fprintf(fp, &\n&);
fclose(fp);
matlab代码:
function img = txt2img(filename)
data = importdata(filename);
r = data(1);
c = data(2);
disp = data(3:end); % 视差
vmin = min(disp);
vmax = max(disp);
disp = reshape(disp, [c,r])'; % 将列向量形式的 disp 重构为 矩阵形式
OpenCV 是行扫描存储图像,Matlab 是列扫描存储图像
故对 disp 的重新排列是首先变成 c 行 r 列的矩阵,然后再转置回 r 行 c 列
img = uint8( 255 * ( disp - vmin ) / ( vmax - vmin ) );
mesh(disp);
set(gca,'YDir','reverse');
% 通过 mesh 方式绘图时,需倒置 Y 轴方向
% 使坐标轴显示范围与数据范围相贴合,去除空白显示区
实现效果:
下面是大牛博客的内容,我粘贴过来啦:
有关立体匹配的介绍和常见匹配算法的比较,推荐大家看看
的讲义 ,190页的ppt,讲解得非常形象详尽。
1. opencv2.1和opencv2.0在做stereo vision方面有什么区别了?
2.1版增强了Stereo Vision方面的功能:
(1) 新增了 SGBM 立体匹配算法(源自Heiko Hirschmuller的《》),可以获得比 BM 算法物体轮廓更清晰的视差图(但低纹理区域容易出现横/斜纹路,在
GCstate-&fullDP 选项使能时可消减这种异常纹路,但对应区域视差变为0,且运行速度会有所下降),速度比 BM 稍慢, 352*288的帧处理速度大约是 5 帧/秒;
(2) 视差效果:BM & SGBM & GC;处理速度:BM & SGBM & GC ;
(3) BM 算法比2.0版性能有所提升,其状态参数新增了对左右视图感兴趣区域 ROI 的支持(roi1 和 roi2,由stereoRectify函数产生);
(4) BM 算法和 GC 算法的核心代码改动不大,主要是面向多线程运算方面的(由 OpenMP 转向 Intel TBB);
(5) cvFindStereoCorrespondenceBM 函数的disparity参数的数据格式新增了 CV_32F 的支持,这种格式的数据给出实际视差,而 2.0 版只支持 CV_16S,需要除以 16.0 才能得到实际的视差数值。
2. 用于立体匹配的图像可以是彩色的吗?
在OpenCV2.1中,BM和GC算法只能对8位灰度图像计算视差,SGBM算法则可以处理24位(8bits*3)彩色图像。所以在读入图像时,应该根据采用的算法来处理图像:
int color_mode = alg == STEREO_SGBM ? 1 : 0;
//////////////////////////////////////////////////////////////////////////
// 载入图像
cvGrabFrame( lfCam );
cvGrabFrame( riCam );
frame1 = cvRetrieveFrame( lfCam );
frame2 = cvRetrieveFrame( riCam );
if(frame1.empty())
resize(frame1, img1, img_size, 0, 0);
resize(frame2, img2, img_size, 0, 0);
// 选择彩色或灰度格式作为双目匹配的处理图像
if (!color_mode && cn&1)
cvtColor(img1, img1gray, CV_BGR2GRAY);
cvtColor(img2, img2gray, CV_BGR2GRAY);
img1p = img1
img2p = img2
img1p = img1;
img2p = img2;
3. 怎样获取与原图像有效像素区域相同的视差图?
在OpenCV2.0及以前的版本中,所获取的视差图总是在左侧和右侧有明显的黑色区域,这些区域没有有效的视差数据。视差图有效像素区域与视差窗口(ndisp,一般取正值且能被16整除)和最小视差值(mindisp,一般取0或负值)相关,视差窗口越大,视差图左侧的黑色区域越大,最小视差值越小,视差图右侧的黑色区域越大。其原因是为了保证参考图像(一般是左视图)的像素点能在目标图像(右视图)中按照设定的视差匹配窗口匹配对应点,OpenCV
只从参考图像的第 (ndisp - 1 + mindisp) 列开始向右计算视差,第 0 列到第 (ndisp - 1 + mindisp) 列的区域视差统一设置为 (mindisp - 1) *16;视差计算到第 width + mindisp 列时停止,余下的右侧区域视差值也统一设置为 (mindisp - 1) *16。&&
00177 static const int DISPARITY_SHIFT = 4;
int ndisp = state-&numberOfD
int mindisp = state-&minD
int lofs = MAX(ndisp - 1 + mindisp, 0);
int rofs = -MIN(ndisp - 1 + mindisp, 0);
int width = left-&cols, height = left-&
int width1 = width - rofs - ndisp + 1;
short FILTERED = (short)((mindisp - 1) && DISPARITY_SHIFT);
// initialize the left and right borders of the disparity map
for( y = 0; y & y++ )
for( x = 0; x & x++ )
dptr[y*dstep + x] = FILTERED;
for( x = lofs + width1; x & x++ )
dptr[y*dstep + x] = FILTERED;
for( x = 0; x & width1; x++, dptr++ )
这样的设置很明显是不符合实际应用的需求的,它相当于把摄像头的视场范围缩窄了。因此,OpenCV2.1 做了明显的改进,不再要求左右视图和视差图的大小(size)一致,允许对视差图进行左右边界延拓,这样,虽然计算视差时还是按上面的代码思路来处理左右边界,但是视差图的边界得到延拓后,有效视差的范围就能够与对应视图完全对应。具体的实现代码范例如下:
//////////////////////////////////////////////////////////////////////////
// 对左右视图的左边进行边界延拓,以获取与原始视图相同大小的有效视差区域
copyMakeBorder(img1r, img1b, 0, 0, m_nMaxDisp, 0, IPL_BORDER_REPLICATE);
copyMakeBorder(img2r, img2b, 0, 0, m_nMaxDisp, 0, IPL_BORDER_REPLICATE);
//////////////////////////////////////////////////////////////////////////
// 计算视差
if( alg == STEREO_BM )
bm(img1b, img2b, dispb);
// 截取与原始画面对应的视差区域(舍去加宽的部分)
displf = dispb.colRange(m_nMaxDisp, img1b.cols);
else if(alg == STEREO_SGBM)
sgbm(img1b, img2b, dispb);
displf = dispb.colRange(m_nMaxDisp, img1b.cols);
4. cvFindStereoCorrespondenceBM的输出结果好像不是以像素点为单位的视差?
“:在OpenCV2.0中,BM函数得出的结果是以16位符号数的形式的存储的,出于精度需要,所有的视差在输出时都扩大了16倍(2^4)。其具体代码表示如下:
dptr[y*dstep] = (short)(((ndisp - mind - 1 + mindisp)*256 + (d != 0 ? (p-n)*128/d : 0) + 15) && 4);
可以看到,原始视差在左移8位(256)并且加上一个修正值之后又右移了4位,最终的结果就是左移4位。
因此,在实际求距离时,cvReprojectTo3D出来的X/W,Y/W,Z/W都要乘以16 (也就是W除以16),才能得到正确的三维坐标信息。”
在OpenCV2.1中,BM算法可以用 CV_16S 或者 CV_32F 的方式输出视差数据,使用32位float格式可以得到真实的视差值,而CV_16S 格式得到的视差矩阵则需要 除以16 才能得到正确的视差。另外,OpenCV2.1另外两种立体匹配算法
SGBM 和 GC 只支持 CV_16S 格式的 disparity 矩阵。
5. 如何设置BM、SGBM和GC算法的状态参数?
(1)StereoBMState
// 预处理滤波参数
preFilterType:预处理滤波器的类型,主要是用于降低亮度失真(photometric distortions)、消除噪声和增强纹理等, 有两种可选类型:CV_STEREO_BM_NORMALIZED_RESPONSE(归一化响应) 或者
CV_STEREO_BM_XSOBEL(水平方向Sobel算子,默认类型), 该参数为 int 型; preFilterSize:预处理滤波器窗口大小,容许范围是[5,255],一般应该在 5x5..21x21 之间,参数必须为奇数值, int 型
preFilterCap:预处理滤波器的截断值,预处理的输出值仅保留[-preFilterCap, preFilterCap]范围内的值,参数范围:1 - 31(文档中是31,但代码中是 63), int
// SAD 参数
SADWindowSize:SAD窗口大小,容许范围是[5,255],一般应该在 5x5 至 21x21 之间,参数必须是奇数,int 型
minDisparity:最小视差,默认值为 0, 可以是负值,int 型 numberOfDisparities:视差窗口,即最大视差值与最小视差值之差, 窗口大小必须是 16 的整数倍,int 型
// 后处理参数
textureThreshold:低纹理区域的判断阈值。如果当前SAD窗口内所有邻居像素点的x导数绝对值之和小于指定阈值,则该窗口对应的像素点的视差值为 0(That is, if the sum of absolute values of x-derivatives computed over SADWindowSize by SADWindowSize pixel neighborhood is smaller than the parameter, no disparity
is computed at the pixel),该参数不能为负值,int 型 uniquenessRatio:视差唯一性百分比, 视差窗口范围内最低代价是次低代价的(1 + uniquenessRatio/100)倍时,最低代价对应的视差值才是该像素点的视差,否则该像素点的视差为 0 (the minimum margin in percents between the best (minimum) cost function value and the second best value to accept the computed disparity,
that is, accept the computed disparity d^ only if SAD(d) &= SAD(d^) x (1 + uniquenessRatio/100.) for any d != d*+/-1 within the search range ),该参数不能为负值,一般5-15左右的值比较合适,int 型
speckleWindowSize:检查视差连通区域变化度的窗口大小, 值为 0 时取消 speckle 检查,int 型
speckleRange:视差变化阈值,当窗口内视差变化大于阈值时,该窗口内的视差清零,int 型
// OpenCV2.1 新增的状态参数
roi1, roi2:左右视图的有效像素区域,一般由双目校正阶段的 cvStereoRectify 函数传递,也可以自行设定。一旦在状态参数中设定了 roi1 和 roi2,OpenCV 会通过cvGetValidDisparityROI 函数计算出视差图的有效区域,在有效区域外的视差值将被清零。
disp12MaxDiff:左视差图(直接计算得出)和右视差图(通过cvValidateDisparity计算得出)之间的最大容许差异。超过该阈值的视差值将被清零。该参数默认为 -1,即不执行左右视差检查。int 型。注意在程序调试阶段最好保持该值为 -1,以便查看不同视差窗口生成的视差效果。具体请参见《》一文中的讨论。
在上述参数中,对视差生成效果影响较大的主要参数是 SADWindowSize、numberOfDisparities 和 uniquenessRatio 三个,一般只需对这三个参数进行调整,其余参数按默认设置即可。
在OpenCV2.1中,BM算法有C和C++ 两种实现模块。
(2)StereoSGBMState
SGBM算法的状态参数大部分与BM算法的一致,下面只解释不同的部分:
SADWindowSize:SAD窗口大小,容许范围是[1,11],一般应该在 3x3 至 11x11 之间,参数必须是奇数,int 型
P1, P2:控制视差变化平滑性的参数。P1、P2的值越大,视差越平滑。P1是相邻像素点视差增/减 1 时的惩罚系数;P2是相邻像素点视差变化值大于1时的惩罚系数。P2必须大于P1。OpenCV2.1提供的例程
stereo_match.cpp 给出了 P1 和 P2 比较合适的数值。 fullDP:布尔值,当设置为 TRUE 时,运行双通道动态编程算法(full-scale 2-pass dynamic programming algorithm),会占用O(W*H*numDisparities)个字节,对于高分辨率图像将占用较大的内存空间。一般设置为 FALSE。
注意OpenCV2.1的SGBM算法是用C++ 语言编写的,没有C实现模块。与H. Hirschmuller提出的原算法相比,主要有如下变化:
算法默认运行单通道DP算法,只用了5个方向,而fullDP使能时则使用8个方向(可能需要占用大量内存)。 算法在计算匹配代价函数时,采用块匹配方法而非像素匹配(不过SADWindowSize=1时就等于像素匹配了)。 匹配代价的计算采用BT算法(&& by S. Birchfield and C. Tomasi),并没有实现基于互熵信息的匹配代价计算。
增加了一些BM算法中的预处理和后处理程序。
(3)StereoGCState
GC算法的状态参数只有两个:numberOfDisparities 和 maxIters ,并且只能通过 cvCreateStereoGCState 在创建算法状态结构体时一次性确定,不能在循环中更新状态信息。GC算法并不是一种实时算法,但可以得到物体轮廓清晰准确的视差图,适用于静态环境物体的深度重构。
注意GC算法只能在C语言模式下运行,并且不能对视差图进行预先的边界延拓,左右视图和左右视差矩阵的大小必须一致。
6. 如何实现视差图的伪彩色显示?
首先要将16位符号整形的视差矩阵转换为8位无符号整形矩阵,然后按照一定的变换关系进行伪彩色处理。我的实现代码如下:&
// 转换为 CV_8U 格式,彩色显示
dispLfcv = displf, dispRicv = dispri, disp8cv = disp8;
if (alg == STEREO_GC)
cvNormalize( &dispLfcv, &disp8cv, 0, 256, CV_MINMAX );
displf.convertTo(disp8, CV_8U, 255/(m_nMaxDisp*16.));
F_Gray2Color(&disp8cv, vdispRGB);
灰度图转伪彩色图的代码,主要功能是使灰度图中 亮度越高的像素点,在伪彩色图中对应的点越趋向于 红色;亮度越低,则对应的伪彩色越趋向于 蓝色;总体上按照灰度值高低,由红渐变至蓝,中间色为绿色。其对应关系如下图所示:
void F_Gray2Color(CvMat* gray_mat, CvMat* color_mat)
if(color_mat)
cvZero(color_mat);
int stype = CV_MAT_TYPE(gray_mat-&type), dtype = CV_MAT_TYPE(color_mat-&type);
int rows = gray_mat-&rows, cols = gray_mat-&
// 判断输入的灰度图和输出的伪彩色图是否大小相同、格式是否符合要求
if (CV_ARE_SIZES_EQ(gray_mat, color_mat) && stype == CV_8UC1 && dtype == CV_8UC3)
CvMat* red = cvCreateMat(gray_mat-&rows, gray_mat-&cols, CV_8U);
CvMat* green = cvCreateMat(gray_mat-&rows, gray_mat-&cols, CV_8U);
CvMat* blue = cvCreateMat(gray_mat-&rows, gray_mat-&cols, CV_8U);
CvMat* mask = cvCreateMat(gray_mat-&rows, gray_mat-&cols, CV_8U);
// 计算各彩色通道的像素值
cvSubRS(gray_mat, cvScalar(255), blue); // blue(I) = 255 - gray(I)
cvCopy(gray_mat, red);
// red(I) = gray(I)
cvCopy(gray_mat, green);
// green(I) = gray(I),if gray(I) & 128
cvCmpS(green, 128, mask, CV_CMP_GE ); // green(I) = 255 - gray(I), if gray(I) &= 128
cvSubRS(green, cvScalar(255), green, mask);
cvConvertScale(green, green, 2.0, 0.0);
// 合成伪彩色图
cvMerge(blue, green, red, NULL, color_mat);
cvReleaseMat( &red );
cvReleaseMat( &green );
cvReleaseMat( &blue );
cvReleaseMat( &mask );
7. 如何将视差数据保存为 txt 数据文件以便在 Matlab 中读取分析?
由于OpenCV本身只支持 xml、yml 的数据文件读写功能,并且其xml文件与构建网页数据所用的xml文件格式不一致,在Matlab中无法读取。我们可以通过以下方式将视差数据保存为txt文件,再导入到Matlab中。&
void saveDisp(const char* filename, const Mat& mat)
FILE* fp = fopen(filename, &wt&);
fprintf(fp, &%02d/n&, mat.rows);
fprintf(fp, &%02d/n&, mat.cols);
for(int y = 0; y & mat. y++)
for(int x = 0; x & mat. x++)
short disp = mat.at&short&(y, x); // 这里视差矩阵是CV_16S 格式的,故用 short 类型读取
fprintf(fp, &%d/n&, disp); // 若视差矩阵是 CV_32F 格式,则用 float 类型读取
fclose(fp);
相应的Matlab代码为:
function img = txt2img(filename)
data = importdata(filename);
r = data(1);
c = data(2);
disp = data(3:end); % 视差
vmin = min(disp);
vmax = max(disp);
disp = reshape(disp, [c,r])'; % 将列向量形式的 disp 重构为 矩阵形式
OpenCV 是行扫描存储图像,Matlab 是列扫描存储图像
故对 disp 的重新排列是首先变成 c 行 r 列的矩阵,然后再转置回 r 行 c 列
img = uint8( 255 * ( disp - vmin ) / ( vmax - vmin ) );
mesh(disp);
set(gca,'YDir','reverse');
% 通过 mesh 方式绘图时,需倒置 Y 轴方向
% 使坐标轴显示范围与数据范围相贴合,去除空白显示区
版权声明:本文为博主原创文章,未经博主允许不得转载。
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场}

我要回帖

更多关于 matlab画动态图 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信