有时用matlab快速验证算法时需要动态绘制曲线、显示数据并观察结果。这里举一个自己编写的例子,在一幅图像上显示一个半径逐渐变化的圆形和一个绕圆心扫描的线段。
主要包括4个部分内容:
1. 读取图像
2. 构建时统
3. 绘制曲线和文本
4. 动态更新绘图
使用matlab函数imread读取图像,并用imshow显示图像。后续绘制的曲线以此图为背景。需要说明的是,坐标系为原点位于左上角的图像坐标系,即图像的左上角坐标为(0,0)。x坐标水平向右增长,y坐标垂直向下增长。
clc; close all; % === read image === image = imread('f:\images\earth.jpg'); figure(1); imshow(image); hold on; [H,W] = size(image);%获取图像矩阵尺寸[行,列],对应图像坐标中的[y,x] W=W/3; % RGB彩色图像,每个像素占据3个字节宽度,因此除3才是像素数量
如果figure中有很多曲线需要同步更新时,有必要构建统一的时统。即定义一个时间刻度数组,如果有必要的话所有绘图函数的时间刻度都将统一从时间数组t中读取。
% === time series === t = 0:0.1:200; totalFrame = max(size(t));
下面在图像上绘制一个半径随时间逐渐变化的圆形。绘制一个半径为R,圆心坐标为(x,y)的圆,可以使用下面的函数:
function h = circle(R,x,y) % 角度alpha alpha = 0:pi/50:2*pi; % x,y坐标,W,H为图像尺寸,将圆心设置到图像中心 x = R*cos(alpha)+x; % x方向偏移量 y = R*sin(alpha)+y; % y方向偏移量 h = plot(x,y,'-'); % 返回圆形的句柄h axis equal让半径R逐渐变化,只需要不断改变半径R的值,也就是用一个数组来存储变化的R。
R0 = (280-40)/totalFrame; % R变化的步长,与时间t同步变化 R = 40:r0:280; % 半径从40~280为了让绘制出的图像能动态更新,需要给每个绘制出来的图像加一个图像句柄,也就是给每个曲线或文本去一个名字,可以通过名字来调用不同的曲线或文本。
hcircle=circle(R(1),W/2,H/2);hcircle 就是这个圆形的句柄。 (W/2,H/2) 为圆形的圆心坐标,位于图像中心。圆的半径为初始半径 R(1)=40 。
下面,绘制一条绕圆心旋转的直线AB。那么,A点与圆心O点重合,|AB|=R(t),即直线长度为圆的半径。
Matlab绘制直线段有很多方法,如果已知直线两个端点的坐标(x1,y1),(x2,y2)可以使用函数line([x1,x2],[y1,y2],'LineWidth',2,'Color','r');方便的绘制直线。如果要让直线运动起来,只需要动态计算两个端点的坐标即可。因为我们要绘制的直线一端A点在圆心O,坐标为(W/2,H/2)不变;另一端B在不断变化的圆周上做扫描运动,因此,需要不断计算直线另一端的坐标。而计算的方法正好就是在半径为R(t)的圆周上取点。
定义直线扫描的圆周角的变化数组theta:
theta0 = 40*pi/totalFrame; % 步长 theta = 0:theta0:40*pi;编写一个函数,可以计算一个半径为R,圆心坐标为(x,y)的圆,其圆周角为theta时的圆周上某店的坐标(xx,yy):
function [xx,yy] = circleLoc(R,x,y,alpha) %theta输入圆周角 %(x,y)圆心坐标 %R半径 %输出圆周上点的坐标(xx,yy) xx=round(R*cos(alpha)+x); yy=round(R*sin(alpha)+y); [xx,yy] = circleLoc(r(1),W/2,H/2,theta(1)); % 返回圆周上的圆心角为alpha的点坐标 hline = line([W/2,xx],[H/2,yy],'LineWidth',2,'Color','r');
有了B点坐标(xx,yy)就可以绘制直线AB了:
[xx,yy] = circleLoc(r(1),W/2,H/2,theta(1)); hline = line([W/2,xx],[H/2,yy],'LineWidth',2,'Color','r');
本节将在图像左上角添加时间t与扫描半径R的读数。使用text()函数添加文本:
htextTime = text(20, 35, ['时间 t = ',num2str(t(1))]); set( htextTime, 'FontSize', 12,'Color','w'); htextR = text(20,80, ['半径 R = ',num2str(r(1))]); set( htextR, 'FontSize', 12,'Color','w'); pause(); % 暂停,等待任意按键继续上面代码中给每个文本也加上了句柄,是为了更新是使用。matlab中使用[]来连接字符和数据组成的字符串。到这一步程序显示如下图所示。
动态更新绘图的基本思路是通过循环来动态更新曲线与文本。
for i=2:1:totalFrame delete(hr1,hline,htextTime,htextR); hcircle =circle(r(i),W/2,H/2); [x,y] = circleLoc(r(i),W/2,H/2,theta(i)); hline = line([W/2,x],[H/2,y],'LineWidth',2,'Color','r'); htextTime = text(20, 35, ['时间 t = ',num2str(t(i))]); set( htextTime, 'FontSize', 12,'Color','w'); htextR = text(20,80, ['半径 R = ',num2str(r(i))]); set( htextR, 'FontSize', 12,'Color','w'); pause(0.01);%暂停0.01s if(t(i)==10||t(i)==100||t(i)==200)%在这几个时刻自动暂停观察显示结果 pause(); end end运行结果如下图所示: