1. 项目概述:从零到一掌握MATLAB图像绘制核心
如果你刚开始接触MATLAB,或者已经用它处理数据很久了,但每次画图还是得去翻旧代码、查文档,那这篇笔记就是为你准备的。MATLAB的绘图功能强大到令人发指,但它的函数命名和参数体系对新手来说,确实有点“散装”的感觉。plot、scatter、contour、mesh、surf……这些函数各自为战,参数又多又杂,不系统梳理一遍,很难形成肌肉记忆。我当年也是从一堆混乱的脚本里爬出来的,深知那种“想画个带误差棒的散点图却不知道用errorbar”的无力感。
这篇笔记的核心,就是帮你把MATLAB里二维和三维图像的基本画法,像拼乐高一样,拆解成最基础的模块,然后告诉你如何组合它们。我们不止讲“怎么画”,更会深入“为什么这么画”以及“怎么画得又快又好”。无论是科研论文里的精美插图,还是工程报告中的趋势分析图,其底层逻辑都离不开这些基本操作。掌握了它们,你就拥有了用数据“说话”的能力。无论你是学生、工程师还是科研人员,只要需要用图形化方式展示数据,这里的内容都将是你工具箱里最趁手的家伙之一。
2. 二维图像绘制:从基础线条到专业图表
二维绘图是数据可视化的基石,MATLAB在这方面提供了从简单到复杂的全套工具。理解二维绘图的逻辑,是迈向高级可视化的第一步。
2.1 核心绘图函数plot的深度解析
plot函数是MATLAB二维绘图的“瑞士军刀”,看似简单,实则内涵丰富。它的基本语法是plot(X, Y, LineSpec),但这里的门道很多。
基础线条绘制与属性定制最基本的用法就是给定X和Y向量。例如,画一个正弦波:
x = linspace(0, 2*pi, 100); % 生成0到2π之间的100个点 y = sin(x); plot(x, y);这行代码会打开一个图形窗口,画出一条蓝色的正弦曲线。但默认的蓝色实线可能并不符合你的需求。这时就需要用到LineSpec(线条规范)和属性名-值对参数。LineSpec是一个字符串,可以同时指定线条颜色、标记符号和线型。它的格式是‘颜色标记线型’,顺序任意,但通常按这个顺序写更清晰。例如:
‘r--’表示红色虚线。‘b*:’表示蓝色星号标记,点线连接。‘go-’表示绿色圆圈标记,实线连接。
而属性名-值对提供了更精细的控制。在plot调用后,你可以用set函数,或者更常见的,直接在plot函数里指定:
plot(x, y, ‘LineWidth‘, 2, ‘Color‘, [0.5, 0.2, 0.8], ‘Marker‘, ‘s‘, ‘MarkerSize‘, 10, ‘MarkerFaceColor‘, ‘y‘);这里,‘LineWidth‘, 2将线宽设为2磅;‘Color‘, [0.5, 0.2, 0.8]用RGB数组指定了一个自定义的紫色;‘Marker‘, ‘s‘使用方块标记;‘MarkerSize‘, 10设置标记大小;‘MarkerFaceColor‘, ‘y‘将标记内部填充为黄色。
注意:
LineSpec字符串和属性名-值对可以混用,但如果在LineSpec中指定了颜色(如‘r‘),又在属性中指定了‘Color‘,那么属性名-值对的设置会覆盖LineSpec。为了避免混淆,我个人的习惯是,简单设置用LineSpec,复杂精细的设置全部用属性名-值对,这样代码意图更清晰。
多组数据与子图绘制在一张图上绘制多条曲线非常简单,有几种方法:
- 多次调用
hold on和plot。 - 将多组X,Y对放入一个
plot调用:plot(x1, y1, x2, y2, ...)。 - 使用矩阵Y:如果X是向量,Y是矩阵,
plot(X, Y)会以X为横坐标,分别绘制Y的每一列。
子图功能subplot是组织多个相关图形的利器。subplot(m, n, p)将当前图形窗口划分为m行n列的网格,并激活第p个位置(按行优先计数)作为当前绘图区。
subplot(2, 2, 1); % 激活2x2网格的第1个位置(左上角) plot(x, sin(x)); title(‘Sine Wave‘); subplot(2, 2, 2); % 激活第2个位置(右上角) plot(x, cos(x)); title(‘Cosine Wave‘);合理使用子图可以让你的报告或论文图表更加紧凑和专业。
2.2 高级二维图表:散点、条形与误差
除了基本的线图,针对不同类型的数据,MATLAB提供了更专业的绘图函数。
散点图与气泡图scatter函数用于绘制散点图,它能直观展示两个变量之间的关系,尤其适合不连续或没有顺序的数据。
x = randn(100, 1); y = x + randn(100, 1)*0.5; scatter(x, y, ‘filled‘);scatter的第三个参数可以是一个标量或向量,用于指定每个点的大小。如果是一个向量,就能实现气泡图的效果,用点的大小表示第三个变量的值。
sizes = abs(randn(100, 1)) * 100; % 随机生成大小 scatter(x, y, sizes, ‘filled‘); colormap(‘jet‘); % 可以配合颜色映射,用颜色表示第四个维度这里,sizes向量控制了每个散点的面积(以磅^2为单位)。‘filled‘参数让标记点内部被填充。
条形图与直方图对于分类数据或显示离散分布,条形图是首选。bar函数绘制垂直条形图,barh绘制水平条形图。
categories = {‘A‘, ‘B‘, ‘C‘, ‘D‘}; values = [23, 45, 12, 67]; bar(categorical(categories), values); % 使用categorical确保x轴标签正确 xlabel(‘Category‘); ylabel(‘Value‘); title(‘Simple Bar Chart‘);histogram函数则用于可视化数据的分布。与老旧的hist函数相比,histogram是面向对象的,功能更强大,能自动计算合适的箱(bin)数量,并给出概率密度估计。
data = randn(1000, 1); histogram(data, ‘Normalization‘, ‘pdf‘); % 绘制概率密度直方图 hold on; % 可以叠加理论上的概率密度函数曲线进行对比 x_fit = linspace(min(data), max(data), 100); y_fit = normpdf(x_fit, mean(data), std(data)); plot(x_fit, y_fit, ‘r-‘, ‘LineWidth‘, 2);‘Normalization‘, ‘pdf‘参数将纵轴归一化为概率密度,使得直方图总面积积分为1,便于与概率密度函数对比。
误差棒与双Y轴在科学绘图中,表示数据的不确定性至关重要。errorbar函数可以轻松添加误差棒。
x = 1:5; y = [10, 15, 12, 18, 16]; err = [1, 1.5, 0.8, 2, 1.2]; errorbar(x, y, err, ‘o‘, ‘CapSize‘, 10); % ‘CapSize‘控制误差棒顶端横杠的长度有时需要在一个图中对比两个量纲不同的变量,这就需要双Y轴。yyaxis函数让这变得简单:
x = linspace(0, 10); y1 = sin(x); y2 = 100*cos(x); yyaxis left; % 激活左侧Y轴 plot(x, y1, ‘b-‘); ylabel(‘Sine‘); yyaxis right; % 激活右侧Y轴 plot(x, y2, ‘r--‘); ylabel(‘100*Cosine‘); xlabel(‘X‘);两个Y轴可以独立设置颜色、标签和范围,完美解决量纲不统一的可视化问题。
3. 三维图像绘制:从曲面到空间分布
当数据具有两个自变量时,三维可视化能提供更深刻的洞察。MATLAB的三维绘图函数同样丰富,核心在于理解网格数据meshgrid的构建。
3.1 三维曲线与网格曲面
三维空间曲线使用plot3函数可以绘制三维空间中的参数曲线,其逻辑与plot完全一致,只是多了一个Z坐标。
t = linspace(0, 10*pi, 1000); x = sin(t); y = cos(t); z = t; plot3(x, y, z, ‘b-‘, ‘LineWidth‘, 1.5); grid on; % 显示网格 xlabel(‘X‘); ylabel(‘Y‘); zlabel(‘Z‘); title(‘3D Helix (Spiral)‘); view(30, 30); % 设置视角(方位角,仰角)view函数是三维绘图的灵魂,它控制观察者的视角。view(az, el)中,az是方位角(在xy平面内从负y轴顺时针旋转的角度),el是仰角(从xy平面向上旋转的角度)。多尝试不同的角度,能找到展示数据特征的最佳视角。
网格曲面图:mesh与surf这是三维绘图的重点。要绘制曲面z = f(x, y),首先需要创建定义域(x, y)的网格。meshgrid函数就是干这个的。
[X, Y] = meshgrid(-2:0.1:2, -2:0.1:2); % 生成网格点 Z = X .* exp(-X.^2 - Y.^2); % 计算每个网格点上的函数值,注意是点乘 .*现在X,Y,Z都是矩阵。mesh(X, Y, Z)会绘制一个线框网格图,曲面是空心的。
figure; subplot(1,2,1); mesh(X, Y, Z); title(‘Mesh Plot‘); colormap(‘jet‘); % 颜色映射根据Z值变化 colorbar; % 显示颜色条surf(X, Y, Z)则会绘制一个表面图,网格被面片填充。
subplot(1,2,2); surf(X, Y, Z); title(‘Surface Plot‘); shading interp; % 使用插值着色,使颜色过渡平滑 light; lighting gouraud; % 添加光照并使用高洛德着色,增强立体感shading命令控制着色方式:flat每个网格面片一个颜色,faceted(默认)带黑色网格线,interp在顶点间插值颜色,最平滑。添加light光源和lighting gouraud光照模型,能极大提升图像的质感和立体感,让曲面特征一目了然。
3.2 等高线图与三维散点
二维与三维等高线等高线图contour和contourf用于展示二维标量场的分布,在物理、地理、工程领域应用极广。
figure; contourf(X, Y, Z, 20, ‘LineWidth‘, 0.5); % 绘制填充等高线,20条等高线 colormap(‘hot‘); colorbar; xlabel(‘X‘); ylabel(‘Y‘); title(‘Filled Contour Plot‘);contourf生成填充颜色的等高线图。第一个数字参数20指定了等高线的数量(也可以直接传入一个向量指定具体的等高线值)。contour3则可以绘制三维空间中的等高线。
figure; contour3(X, Y, Z, 20, ‘LineWidth‘, 1.5); grid on;对于需要精确标注等高线数值的情况,可以在绘制后使用clabel函数:
[C, h] = contour(X, Y, Z); clabel(C, h, ‘FontSize‘, 10); % 将标签添加到等高线h上三维散点图与向量场scatter3是scatter在三维的自然延伸,用于绘制三维空间中的离散点。
x = randn(100,1); y = randn(100,1); z = randn(100,1); c = sqrt(x.^2 + y.^2 + z.^2); % 用颜色表示点到原点的距离 scatter3(x, y, z, 50, c, ‘filled‘); % 点大小50,颜色映射到c colormap(‘parula‘); colorbar; xlabel(‘X‘); ylabel(‘Y‘); zlabel(‘Z‘);quiver3函数用于绘制三维向量场,比如流体速度场、电磁场等。
[X, Y, Z] = meshgrid(-1:0.2:1, -1:0.2:1, -1:0.2:1); U = -Y; % X方向分量 V = X; % Y方向分量 W = zeros(size(Z)); % Z方向分量为0,形成一个在XY平面旋转的场 quiver3(X, Y, Z, U, V, W); axis equal; % 保持坐标轴比例一致 xlabel(‘X‘); ylabel(‘Y‘); zlabel(‘Z‘); title(‘3D Vector Field (Rotation in XY plane)‘);quiver3的前三个参数是向量的起点坐标,后三个参数是向量的分量(U, V, W)。通过调整‘AutoScale‘和‘AutoScaleFactor‘参数可以控制箭头的大小。
4. 图形修饰与输出:让图表会说话
一张专业的图表,除了准确表达数据,还需要精心的修饰和高质量的输出。这是区分“能画图”和“会画图”的关键。
4.1 坐标轴、标签与图例的精细控制
坐标轴属性大全默认的坐标轴范围可能不适合你的数据。使用axis或xlim/ylim/zlim进行控制。
axis([xmin xmax ymin ymax]): 设置二维图的XY范围。axis([xmin xmax ymin ymax zmin zmax]): 设置三维图的XYZ范围。axis equal: 使坐标轴刻度等长,确保圆形看起来是圆,而不是椭圆。axis tight: 将坐标轴范围设置为恰好等于数据范围。box on/off: 控制是否显示坐标轴边框。grid on/off: 控制是否显示网格线。grid minor可以打开更细的次网格。
坐标轴刻度也可以自定义:
xticks([0, pi/2, pi, 3*pi/2, 2*pi]); xticklabels({‘0‘, ‘\pi/2‘, ‘\pi‘, ‘3\pi/2‘, ‘2\pi‘}); % 使用LaTeX语法这能将横坐标的数值刻度替换为更美观的π符号。
标签、标题与图例xlabel,ylabel,zlabel,title函数用于添加文本。它们支持LaTeX语法,可以插入数学公式和特殊符号。
xlabel(‘Time (s)‘, ‘FontSize‘, 12, ‘FontWeight‘, ‘bold‘); ylabel(‘Amplitude‘, ‘FontSize‘, 12); title(‘Signal: $y = e^{-t} \cdot \sin(2\pi f t)$‘, ‘Interpreter‘, ‘latex‘, ‘FontSize‘, 14);注意,要使用LaTeX,必须在title或text函数中设置‘Interpreter‘, ‘latex‘。
图例legend是区分多条曲线的关键。最佳实践是在plot时就用‘DisplayName‘参数指定图例条目。
plot(x, sin(x), ‘b-‘, ‘DisplayName‘, ‘Sine‘, ‘LineWidth‘, 2); hold on; plot(x, cos(x), ‘r--‘, ‘DisplayName‘, ‘Cosine‘, ‘LineWidth‘, 2); legend(‘Location‘, ‘best‘, ‘FontSize‘, 10); % ‘best‘让MATLAB自动选择最佳位置这样调用legend时就不需要再输入字符串数组,避免了顺序错乱的问题。‘Location‘参数可以指定图例位置,如‘northwest‘(左上)、‘southeast‘(右下)等。
4.2 颜色映射、光照与视角
颜色映射的艺术颜色映射colormap决定了数据如何映射到颜色。MATLAB内置了许多色彩方案:
jet: 彩虹色,对比强烈,但已被批评在科学可视化中可能误导(因为亮度变化不均匀)。parula: MATLAB默认的新色彩映射,感知均匀,更适合科学用途。hot: 黑-红-黄-白,常用于表示热度或强度。gray: 灰度,用于黑白打印或强调亮度。cool,summer,winter等: 季节性色彩。
你可以使用colormap(jet(256))来指定一个256级的jet色彩映射。colorbar函数会添加一个颜色条,直观显示颜色与数据值的对应关系。
光照与材质对于三维表面图,光照能极大增强立体感和真实感。
surf(peaks); % peaks是一个测试用的曲面函数 shading interp; light(‘Position‘, [1, -1, 1], ‘Style‘, ‘infinite‘); % 添加一个位于(1,-1,1)方向的无限远光源 lighting gouraud; % 使用Gouraud着色(平滑着色) material shiny; % 设置材质属性为‘shiny‘,高光明显material命令可以快速设置一组预定义的材质属性(shiny,dull,metal)。你也可以用‘SpecularStrength‘,‘DiffuseStrength‘,‘AmbientStrength‘等属性进行微调,控制镜面反射、漫反射和环境光的强度。
视角与交互view函数控制观察角度。除了view(az, el),还可以用view([x, y, z])指定一个从原点指向[x,y,z]的视角。 更强大的是交互式工具。在图形窗口的工具栏中,有旋转、平移、缩放、数据游标等工具。特别是旋转工具,对于理解复杂三维结构至关重要。你也可以在代码中设置rotate3d on来默认启用旋转模式。
4.3 图形导出与发布级质量
画好的图最终要插入文档或演示文稿中。低质量的截图会毁掉所有努力。
导出设置与命令图形窗口的“文件”->“另存为”菜单可以保存,但为了可重复性和一致性,最好使用命令。saveas函数最通用:
saveas(gcf, ‘my_plot.png‘); % gcf获取当前图形窗口句柄但saveas对分辨率和尺寸的控制有限。专业做法是使用print函数:
set(gcf, ‘Position‘, [100, 100, 800, 600]); % 设置图形窗口大小(像素) set(gcf, ‘PaperPositionMode‘, ‘auto‘); % 重要!使打印尺寸与屏幕显示一致 print(‘-dpng‘, ‘-r300‘, ‘high_res_plot.png‘); % 保存为300 DPI的PNG-dpng指定格式(还可选-depsc矢量图,-dpdf等)。-r300设置分辨率为300 DPI(点每英寸),对于大多数印刷和屏幕显示足够了。对于论文,推荐使用矢量格式如EPS或PDF,它们无限缩放不失真。
print(‘-depsc2‘, ‘-tiff‘, ‘vector_plot.eps‘); % 保存为彩色EPS,兼容性较好常见问题与避坑指南
- 图形窗口闪烁或覆盖: 在脚本中连续画多个图时,默认会覆盖上一个。使用
figure命令创建新窗口,或用figure(1),figure(2)指定窗口编号。在循环中绘图时,使用drawnow或drawnow limitrate可以强制刷新图形,实现动画效果或实时更新。 - 中文显示乱码: 旧版本MATLAB默认字体可能不支持中文。可以在绘图前设置默认字体:
或者,在具体的set(0, ‘DefaultAxesFontName‘, ‘SimHei‘); % 设置坐标轴默认字体为黑体 set(0, ‘DefaultTextFontName‘, ‘SimHei‘); % 设置文本默认字体xlabel,title中指定字体:title(‘标题‘, ‘FontName‘, ‘Microsoft YaHei‘)。 - 保存的图片周围有大量白边: 这是因为图形窗口的
‘InvertHardcopy‘属性和纸张尺寸设置。在print前设置:set(gcf, ‘InvertHardcopy‘, ‘off‘); % 保持屏幕显示的颜色 set(gcf, ‘PaperUnits‘, ‘inches‘); set(gcf, ‘PaperPosition‘, [0 0 6 4]); % 设置纸张位置和大小(6x4英寸) - 三维图形旋转后保存的视角不对:
print保存的是当前图形窗口的视图。确保在print命令前没有改变窗口焦点或视角。可以在保存前用view固定一个视角。 - 线条或字体在导出后变粗/模糊: 对于矢量图(EPS/PDF),有时线条会显得过粗。可以在导出前设置线条和字体属性为“按屏幕显示”:
set(gcf, ‘Renderer‘, ‘painters‘); % 使用Painters渲染器,对矢量图支持更好 set(gca, ‘FontSize‘, 10); % 明确设置坐标轴字体大小 set(findobj(gcf, ‘Type‘, ‘line‘), ‘LineWidth‘, 1); % 设置所有线宽为1
我个人最常用的工作流是:先在脚本中调整好图形所有细节(大小、颜色、标签、视角),然后使用print函数以高分辨率PNG(用于PPT)和PDF(用于论文)两种格式保存。对于包含大量子图的复杂图表,可以考虑使用exportgraphics函数(R2020a以上),它提供了更简单的接口和更好的默认设置,例如exportgraphics(gcf, ‘plot.pdf‘, ‘ContentType‘, ‘vector‘, ‘Resolution‘, 300)。