news 2026/9/16 23:51:22

自适应中值滤波原理详解与Matlab去噪仿真实现

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
自适应中值滤波原理详解与Matlab去噪仿真实现

简介:面向图像处理初学者、课程设计学生以及需要快速复现去噪算法的研究人员,这份资源提供了基于MATLAB的自适应中值滤波图像去噪完整仿真方案,可有效应对椒盐噪声污染,并在去噪同时保留更多边缘细节,是理解自适应滤波机制的良好起点。压缩包共3个文件,包含核心算法脚本(.m)、演示操作录像(.avi)与测试图像(.jpg),整体仅2.14MB,轻量便携。脚本实现主控制逻辑与可视化输出,录像逐步展示从环境配置到运行出图的完整过程,测试图则方便直接验证算法效果。运行前需将MATLAB当前文件夹切换至工程路径,建议使用2021a或更高版本,配套视频可辅助新手避开常见环境问题。已有712人学习下载,适合课程设计、论文实验或算法对比等场景。借助包内完整的源码、测试图与操作演示,可深入理解自适应窗口尺寸随噪声密度动态变化的思想,并灵活修改参数对比去噪效果。

1. 自适应中值滤波为什么比普通中值滤波更值得仿真

在图像去噪这个老话题里,中值滤波一直是最容易上手、最不挑硬件的一类方法。但真把一张叠加了高密度椒盐噪声的图丢给固定窗口的中值滤波,结果往往不是去噪,而是把图像弄成一块块模糊的色斑。原因不复杂:噪声密度高时,固定窗口里的中值本身可能就是被污染像素,排序取中值失去了意义。更麻烦的是,中值滤波对边缘和细纹理的处理是“一视同仁”的——它分不清某像素是噪声还是本来就在细节区域。

自适应中值滤波(Adaptive Median Filter,AMF)解决的就是这个矛盾:窗口大小和是否滤波都由局部统计特性决定。能确认是脉冲噪声的,才动这个像素;确认是边缘细节的,主动放行。这个“先在噪声检测上做文章、再决定滤波强度”的思路,在图像去噪这个方向上,几乎是所有现代去噪算法(从加权中值到非局部均值)的雏形。用 Matlab 做这个算法的仿真,核心不是调一个medfilt2,而是自己把窗口扩展、噪声检测、双阈值判断这些逻辑一步步写出来。

这篇帖子会从算法判定逻辑讲到 Matlab 代码实现,再对比不同参数下的去噪效果,最后聊怎么把仿真过程做成能放进 PPT 或演示视频的动态展示。适合做图像处理课程实验、毕设仿真,以及刚开始接触自适应滤波但不想只看公式的工程师。

2. 自适应中值滤波的两级判定逻辑:从噪声检测到窗口扩展

2.1 标准中值滤波的失效边界

先明确中值滤波到底在算什么。对图像中的某个像素点 ((x,y)),取一个大小为 (W \times W) 的邻域窗口,窗口内所有像素按灰度排序,取中间值作为当前像素的新灰度。Matlab 里一行g = medfilt2(f, [3 3])就能跑,但这一行隐藏了两个默认行为:窗口大小固定,且对窗口内的每个像素都做替换。

固定窗口的隐患在噪声密度上来之后非常明显。假设椒盐噪声密度是 0.3,一个 3×3 窗口内平均会有约 2.7 个噪声点。排序后的中值落在真实像素上的概率尚可,但如果噪声密度到 0.5,3×3 窗口里一半左右是噪声,排序取到的中值大概率本身就是噪声或受噪声影响的灰度,滤波后图像会残留大量黑白点。更隐蔽的情况是边缘像素:一个干净的边缘像素和一个被噪声污染的非边缘像素,在固定窗口中各占 9 个灰度值,排序后的输出几乎总会压平边缘,造成细节丢失,而这种丢失在视觉上表现得比噪声本身更难接受。

自适应策略的核心,就是不把每个像素都交给同一个窗口。它对每个像素做先判断、后处理,判断不通过时自动扩大窗口,直到满足条件或到达窗口上限。这套机制业界通常称为“双级判定”,英文资料里常写为 two-level decision,它也是后面代码实现的骨架。

2.2 第一级判定:区分噪声点和信号点

先看窗口内部的灰度分布。设当前窗口为 (S_{xy}),窗口半径为 (r),(z_{min})、(z_{max})、(z_{med}) 分别是窗口内灰度的最小值、最大值和中值。第一级判定规则如下:

  • 若 (z_{min} < z_{med} < z_{max}),说明中值本身不是极值,即中值不是被椒盐噪声污染的亮度值。这种情况下,窗口中心像素的原始灰度 (z_{xy}) 如果满足 (z_{min} < z_{xy} < z_{max}),那就认为它是正常信号,直接保留原始灰度,不做滤波。
  • 若 (z_{xy}) 本身落在极值上(即等于 (z_{min}) 或 (z_{max})),判定为疑似噪声,进入第二级判定。

第一级判定的意义很多人会看漏:它真正在做的是“保护非噪声极值”。图像中天然存在接近全黑或全白的像素(如夜晚的路灯、白墙上的黑点),这些像素的灰度在邻域中可能恰好是极小值或极大值。如果只按单一阈值判断,这类像素会被误伤。所以第一级先看中值是否可靠,再看中心像素是否真的是极值,双条件同时满足才认为是噪声候选。

2.3 第二级判定:中值本身也是极值时怎么办

当第一级判定发现 (z_{med}) 等于 (z_{min}) 或 (z_{max}),说明当前窗口内噪声密度高,排序后的中值已经不可靠。此时的做法不是直接滤波,而是扩大窗口半径,从 (r+1) 重新执行第一级判定。具体流程:

  1. 从最小窗口半径 (r_{min})(通常 1,即 3×3 窗口)开始。
  2. 执行第一级判定,若不通过,则 (r \leftarrow r+1),重新计算窗口灰度统计。
  3. 若 (r) 已经达到最大窗口半径 (r_{max})(常取 3 或 4,即 7×7 或 9×9 窗口),仍然不满足第一级条件,说明局部区域噪声非常密集。此时不再无限扩大,直接输出当前窗口的中值 (z_{med}) 作为替代值。

这个“扩窗上限”的设计是自适应中值滤波的关键参数。(r_{max}) 设小了,高密度噪声区域救不回来;设大了,虽然能覆盖更宽的空间,但窗口跨越物体边界的概率增加,容易把两个不同区域的灰度混在一起取中值,产生伪纹理。

第二级判定的另一条重要规则是:当中心像素被判定为噪声、但窗口扩展后的中值仍落在极值上时,也有资料主张用“相邻窗口中值”或“最近有效像素”来替代,但这属于变体做法。课程和常见的毕业设计仿真里,标准 AMF 多采用“扩窗后输出中值”的方式,实现简单、效果可预期。

2.4 AMF 与传统中值滤波的对比表

维度传统中值滤波自适应中值滤波
窗口大小固定动态调整,从 3×3 自动扩至上限
是否检测噪声不做区分,全图统一处理两级判定,只处理疑似噪声点
边缘保护差,边缘像素易被排序后的中值改写较好,极值判定的目的是先识别再处理
高密度噪声(>0.5)残留大量斑点能通过扩窗提高恢复能力,但也受 (r_{max}) 限制
Matlab 内置函数medfilt2无内置,需手动实现
适用场景中低密度高斯/椒盐噪声做预处理高密度椒盐噪声、对细节有要求的去噪任务

AMF 的代价是计算量显著上升:每个像素都要做窗口统计和条件判断,噪声密度越高,窗口扩张越频繁,排序次数也就越多。实际落地时通常先用快速排序算法(如sort的底层实现)来减少排序开销,后面代码实现里会用这个思路。

3. Matlab 实现:从零手写自适应中值滤波函数

3.1 灰度图预处理与噪声类型选择

写滤波函数前,先把测试图准备好。Matlab 里最常用的实验图是自带的camerman.tif,也可以用imread读入自己的图像。关键是第一步要把图像转成double类型,否则灰度的加减比较在uint8下会发生溢出问题。

clear; clc; close all; % 读取灰度图,转为 double,归一化到 [0,1] I = imread('cameraman.tif'); if size(I, 3) == 3 I = rgb2gray(I); end I = im2double(I); % 关键:后续所有操作都在 double 下做 % 加入椒盐噪声,密度 0.3 In = imnoise(I, 'salt & pepper', 0.3);

参数说明:imnoise的第三个参数是噪声密度,取值范围 0 到 1,表示总像素中多少比例会被替换为 0 或 255(归一化后为 0 或 1)。密度 0.3 意味着三成像素被污染,这个密度对普通 3×3 中值滤波已经有明显压力,但自适应滤波大多能恢复得不错。im2double把灰度从 0-255 的整数区间映射到 0-1 的浮点区间,窗口内排序和比较都更稳。注意:因为imnoise用的是随机数生成器,每次运行输出的噪声位置不同,如果需要可复现结果,建议先执行一次rng(0)固定随机种子。

3.2 自写 min 和 max 的朴素自适应窗口版本

下面是一个原理最直观的实现,每个像素独立处理,代码量短,逻辑和上面讲的两级判定一一对应。

function out = adaptive_median_filter(I, r_min, r_max) % 输入 I 为 double 灰度图,值域 [0,1] % r_min 最小窗口半径,通常为 1(3×3) % r_max 最大窗口半径,建议 3 或 4 [M, N] = size(I); % 边界填充:用边缘镜像,避免窗口越界 pad = r_max; I_pad = padarray(I, [pad pad], 'symmetric'); out = zeros(M, N); for i = pad+1 : M+pad for j = pad+1 : N+pad for r = r_min : r_max % 当前窗口半径下的局部块 block = I_pad(i-r:i+r, j-r:j+r); zmin = min(block(:)); zmax = max(block(:)); zmed = median(block(:)); zxy = I_pad(i, j); % 第一级判定:中值是否为极值 if zmin < zmed && zmed < zmax % 第二级判定:当前像素是否是疑似噪声 if zmin < zxy && zxy < zmax out(i-pad, j-pad) = zxy; % 是信号,直接保留 else out(i-pad, j-pad) = zmed; % 是噪声,输出中值 end break; else % 中值不可靠,若已到最大半径,只能用当前中值兜底 if r == r_max out(i-pad, j-pad) = zmed; end end end end end end

逻辑说明:外层r循环从最小半径到最大半径递增,内层对每个半径做窗口统计。break语句保证一旦满足第一级判定条件就不再扩大窗口。这里容易踩坑的是padarray'symmetric'选项——它把边缘像素做镜像填充,比补零好得多。如果补零,图像四周边界会出现一圈由 0 引发的伪边缘,滤波后视觉上会有一圈黑框。还有一点:zmin < zmed && zmed < zmax是严格小于,不能取<=。在后文 3.3 会解释为什么<=会让平坦区域的像素完全走错误分支。

3.3 优化版:一维排序、复用统计量、避免窗口全量排序

朴素版本的问题是慢。对 256×256 图像,在密度 0.5 噪声下,每个像素可能要重复计算多个窗口的median。如果实验图是 1024×1024,朴素版本跑一次要几十秒,根本不适合做参数扫描。优化思路分三层:

  1. 利用sort一次得到排序后的整行数据,同时提取zminzmaxzmed,避免minmaxmedian三次扫描。
  2. 外层扩窗时,上一轮窗口包含在下一轮窗口内。可以维护窗口内灰度的直方图,扩窗时只增量更新边界新增像素,而不是重新对整块排序。
  3. 窗口半径递增时,复用上一轮的排序结果,理论上扩窗代价从 O(W^2 log W) 降到 O(W),但在 Matlab 里向量化的收益往往比手动维护数据结构的收益更明显,所以折中做法是保留全窗口排序,只是用sort(block(:))一次性取值。
function out = adaptive_median_filter_fast(I, r_min, r_max) % 优化版:利用 sort 一次取三值,减少重复扫描 [M, N] = size(I); % 对中心像素做扩展时,先预留输出矩阵 out = zeros(M, N); pad = r_max; I_pad = padarray(I, [pad pad], 'symmetric'); for i = pad+1 : M+pad for j = pad+1 : N+pad for r = r_min : r_max block = I_pad(i-r:i+r, j-r:j+r); sorted = sort(block(:)); % 升序 zmin = sorted(1); zmax = sorted(end); zmed = sorted(ceil(length(sorted)/2)); zxy = I_pad(i, j); if zmin < zmed && zmed < zmax if zmin < zxy && zxy < zmax out(i-pad, j-pad) = zxy; else out(i-pad, j-pad) = zmed; end break; else if r == r_max out(i-pad, j-pad) = zmed; end end end end end end

核心改动是sorted = sort(block(:))这一行:block(:)将二维窗口拉成一维列向量,sort升序排列后,最小值是第一个元素,最大值是最后一个,中位数是正中间那个。注意在元素个数为偶数时中值定义有两种,这里统一用ceil,效果偏差在图像上肉眼基本看不出来。

3.4 与传统 medfilt2 的对比脚本

实现完滤波器,立刻就能做对比实验。下面脚本同时跑出三种结果:普通 3×3 中值、自适应中值(r_min=1, r_max=3)、自适应中值(r_min=1, r_max=4),并计算 PSNR 和 SSIM。

% 直接调用上面写的函数 I_med3 = medfilt2(In, [3 3]); % 传统中值滤波 I_amf3 = adaptive_median_filter_fast(In, 1, 3); % 自适应,最大 7×7 I_amf4 = adaptive_median_filter_fast(In, 1, 4); % 自适应,最大 9×9 % 计算峰值信噪比 PSNR psnr_med3 = psnr(I_med3, I); psnr_amf3 = psnr(I_amf3, I); psnr_amf4 = psnr(I_amf4, I); % 计算结构相似性 SSIM ssim_med3 = ssim(I_med3, I); ssim_amf3 = ssim(I_amf3, I); ssim_amf4 = ssim(I_amf4, I); fprintf('PSNR: medfilt2=%.2f dB, AMF(r_max=3)=%.2f dB, AMF(r_max=4)=%.2f dB\n', ... psnr_med3, psnr_amf3, psnr_amf4); fprintf('SSIM: medfilt2=%.4f, AMF(r_max=3)=%.4f, AMF(r_max=4)=%.4f\n', ... ssim_med3, ssim_amf3, ssim_amf4);

说明:psnrssim都是 Matlab 图像处理工具箱(Image Processing Toolbox)里的函数。psnr输入两张图必须是同尺寸同类型,这里都是 double 且在 0-1 范围,所以不需要额外转换。SSIM 是一个 0 到 1 之间的值,比 PSNR 更能反映结构相似性。对于椒盐噪声去噪,通常 AMF 的 PSNR 会高于普通中值滤波 3-8 dB,具体数值受噪声密度和图像内容影响。

3.5 参数调试:r_max 选择与边界处理

r_max窗口最大尺寸适应噪声密度计算耗时(256×256)主要风险
13×3≤0.2高密度噪声下残留大量椒盐点
25×5≤0.4中等窗口跨边缘时,细节区出现轻度糊化
37×7≤0.6宽窗口下平坦区域可能出现块状伪纹理
49×9≤0.7很慢边缘过冲明显,细线结构丢失

边界处理上,padarray'symmetric'已经规避了大部分越界问题,但要留意r_max大于图像最小边长的一半时,pad会大于实际图像尺寸,这时镜像范围也会出现异常。正常实验图都在 256×256 以上,r_max=4 完全安全。

提示:如果输入图像不是方形,padarraypad参数是一个二维向量[pad_row, pad_col],行和列方向的扩展尺寸可以不一样。上面代码统一用了pad = r_max,对非方形图像误差也不大,但严谨的做法是行方向用r_max、列方向也用r_max,保持一致。

4. 仿真实验:噪声密度变化与去噪效果对比分析

4.1 噪声密度从 0.1 到 0.7 的梯度测试

单张图固定密度的对比只能说明一种情况下的表现。要系统地评价自适应中值滤波,得让噪声密度在一个区间内变化,观察三个指标:PSNR、SSIM、主观视觉残留。下面脚本完成这个任务:

rng(0); % 固定随机种子 density_list = 0.1:0.1:0.7; psnr_med = zeros(length(density_list), 1); psnr_amf = zeros(length(density_list), 1); for k = 1:length(density_list) d = density_list(k); In = imnoise(I, 'salt & pepper', d); I_med = medfilt2(In, [3 3]); I_amf = adaptive_median_filter_fast(In, 1, 3); psnr_med(k) = psnr(I_med, I); psnr_amf(k) = psnr(I_amf, I); end % 打印表格数据 T = table(density_list', psnr_med, psnr_amf, ... 'VariableNames', {'NoiseDensity', 'MedianPSNR', 'AMF_PSNR'}); disp(T);

rng(0)让每次循环生成的噪声位置一致,这样对比的是两种算法在同一种噪声分布下的差异,而不是随机误差。这一步在写论文或报告时尤其重要——可复现性是仿真实验的基本要求。

当噪声密度达到 0.7 时,3×3 固定窗口中几乎每个窗口都有 5 个左右的噪声像素,排序中值大概率落在噪声灰度上,medfilt2的结果会呈现明显的水渍状色斑,而 AMF 因为可以扩到 7×7 或 9×9,取到有效信号的概率就高一些。但注意,r_max=3 时 0.7 的密度已经逼近理论上限,如果密度继续升高,效果会快速下降。

4.2 边缘像素在滤波前后的灰度剖面

中值滤波最被诟病的点是边缘过度平滑,而自适应版本在边缘处通常选择保留原始值。为了可视化这一点,取图中一行像素,画出原始图像、噪声图像、普通中值滤波、自适应滤波四种情况下的灰度剖面曲线。

row = 100; % 取第 100 行观察 figure; subplot(2,1,1); plot(I(row, :), 'k-', 'LineWidth', 1.2); hold on; plot(In(row, :), 'b.', 'MarkerSize', 4); legend('原始', '带噪'); title('第100行灰度剖面:原始与噪声'); ylim([0 1]); subplot(2,1,2); plot(I_med3(row, :), 'r--', 'LineWidth', 1.2); hold on; plot(I_amf3(row, :), 'g-', 'LineWidth', 1.2); legend('medfilt2', 'AMF'); title('第100行灰度剖面:滤波结果对比'); ylim([0 1]);

剖面图能非常直观地说明问题:在明显的灰度阶跃(物体边缘)处,medfilt2会把跳变沿拉平成一个斜坡,而 AMF 的曲线会在阶跃附近保留更陡的过渡。对比原始图像曲线,能看出 AMF 在平坦区域有明显去噪能力,同时在边缘处更接近原始曲线。这个可视化手法常出现在课程报告和论文的结果分析部分,也是答辩时评委爱看的内容。

4.3 局部区域放大对比:细节保留程度

全局 PSNR 无法反映局部细节保留情况,尤其是细线、纹理这类高频信息。建议用imcrop截取图像中一块包含细节的区域,放大后对比。

rect = [80 60 60 60]; % 裁剪区域 [x, y, width, height] I_crop_orig = imcrop(I, rect); I_crop_noise = imcrop(In, rect); I_crop_med = imcrop(I_med3, rect); I_crop_amf = imcrop(I_amf3, rect); % 拼接成 2×2 montage 显示 figure; subplot(2,2,1); imshow(I_crop_orig); title('原始'); subplot(2,2,2); imshow(I_crop_noise); title('带噪'); subplot(2,2,3); imshow(I_crop_med); title('medfilt2'); subplot(2,2,4); imshow(I_crop_amf); title('AMF');

放大区域的视觉差异通常比全图更明显。medfilt2输出中能看到的细线断裂、屋顶纹理变模糊,在 AMF 中会清晰不少。如果看不出来,可以尝试截取 cameraman 图中的三脚架区域,那个位置的密集细线是检验中值滤波类算法的最佳试金石。注意imcrop的坐标原点在图像左上角,宽度高度按像素计算,数据归一化不影响裁剪结果。

4.4 运行时间统计

性能这块在论文里是硬指标。用tic/toc记录运行时间,注意多次运行取平均值排除抖动。

funcs = {@() medfilt2(In, [3 3]), ... @() adaptive_median_filter_fast(In, 1, 3), ... @() adaptive_median_filter_fast(In, 1, 4)}; labels = {'medfilt2-3x3', 'AMF-rmax3', 'AMF-rmax4'}; for k = 1:length(funcs) t = zeros(1, 5); for trial = 1:5 f = funcs{k}; tic; f(); t(trial) = toc; end fprintf('%s 平均耗时: %.4f s\n', labels{k}, mean(t)); end

medfilt2底层是高效的 C 实现,自适应版本因为是纯 Matlab 循环,速度上被拉开差距是预期内的事。对 256×256 图像,medfilt2耗时 0.01s 量级,而 AMF 的纯循环实现通常要 2s 左右。如果仿真图是 1024×1024,纯循环版本可能要到 30 秒以上。实际项目中要提速,可以考虑把最内层循环用mex重构,或者用parfor并行化——后面第 5 章会讲一个不需要离开 Matlab 环境的加速思路。

5. 把仿真做成操作演示视频:录屏与动图两种路线

5.1 用 Matlab 自带的 VideoWriter 录制滤波过程

标题里提到“含代码操作演示视频”,说明这个项目的交付物不只是算法本身,还包含可演示的视频材料。Matlab 官方推荐的做法是用VideoWriter把多帧图像写成一个 AVI 或 MP4 文件。最常见的演示视频思路是:先展示原始图 → 展示加噪图 → 窗口逐渐扩大的动画 → 滤波结果图。下面给出一个录制窗口动画的代码。

% 生成演示视频:窗口逐帧扩大的滤波过程 v = VideoWriter('AMF_demo.avi', 'Motion JPEG AVI'); v.FrameRate = 5; % 每秒 5 帧,视觉上刚好能看清变化 open(v); % 先写 15 帧原始图,停顿感靠多帧重复实现 for f = 1:15 imshow(In); title('带噪声图像'); frame = getframe(gcf); writeVideo(v, frame); end % 窗口从 1 扩到 3,每级窗口显示 10 帧 for r = 1:3 I_tmp = adaptive_median_filter_fast(In, 1, r); for f = 1:10 imshow(I_tmp); title(sprintf('自适应中值滤波 (r = %d)', r)); frame = getframe(gcf); writeVideo(v, frame); end end close(v);

参数说明:VideoWriter第一个参数是输出文件名,扩展名决定封装格式。.aviMotion JPEG AVI是兼容性最好的组合,生成的视频体积较大但任何播放器都能打开。.mp4需要系统里有对应的编码器(Windows 上通常能用,Linux 上可能需要确认是否安装了 H.264 编码支持)。getframe(gcf)捕获当前 figure 窗口的内容,注意 gcf 窗口大小会直接影响视频分辨率,建议在录制前用set(gcf, 'Position', [100 100 640 480])固定窗口尺寸,避免不同帧分辨率抖动。

视频里的“代码操作演示”部分,如果不需要展示实时代码输入,可以用live script(.mlx 文件)逐段运行代码块,用系统录屏软件(Windows 的 Xbox Game Bar 或 OBS)录屏,这比 Matlab 内部录制的画面更丰富。

5.2 用 write 命令把关键中间结果输出为 GIF

视频适合汇报答辩,GIF 则更适合放进课程报告或博客附图中。Matlab 里把多帧图像写进 GIF 的方式是用imwrite'WriteMode', 'append'选项。

% 输出一组 GIF 动画:原始 -> 加噪 -> 滤波结果 frames = {I, In, I_amf3}; filename = 'amf_steps.gif'; for k = 1:length(frames) [A, map] = gray2ind(frames{k}, 256); if k == 1 imwrite(A, map, filename, 'gif', 'LoopCount', Inf, 'DelayTime', 1); else imwrite(A, map, filename, 'gif', 'WriteMode', 'append', 'DelayTime', 1); end end

gray2ind把 double 灰度图转成带 colormap 的索引图像,这是 GIF 格式要求的。DelayTime单位是秒,1 表示每帧停留 1 秒,如果想让加噪过程更快,改成 0.5 即可。LoopCount, Inf表示无限循环播放。这套写法在写博客、做实验报告时很实用,生成的 GIF 可以直接插入 Markdown 或者 Word,不需要任何视频剪辑软件。

5.3 演示视频中如何展示代码与参数

录屏演示的场景下,很多同学会直接把脚本从头到尾运行一遍,视频里全是代码滚动,观看者根本抓不住重点。更好的顺序是:

  1. 先用一句中文注释交代实验目的,例如% 比较固定中值与自适应中值在噪声密度0.5下的去噪效果
  2. 运行加噪代码,图窗弹出,停顿 2 秒让观众看到噪声图。
  3. 运行medfilt2结果,再运行 AMF 结果,两张图并排对比。
  4. 命令行再打印一组 PSNR 数值。
  5. 最后运行VideoWriter片段,把之前录的视频文件播一遍。

配合录屏软件,Matlab 编辑器里的代码高亮和命令行输出都能被记录下来,效果比直接导出 PDF 脚本要生动得多。如果环境支持,还可以在.mlx活页脚本里把代码、输出图和文字说明放在同一个文档流中,每段代码块执行后立即在右侧显示生成的图窗。这样录屏时就只滚动活页脚本,不需要反复切换窗口,观感上更接近现代 Notebook 风格。

5.4 验证演示视频正确性的自查清单

做完视频不要直接交差,花两分钟检查这几个点:窗口尺寸是否真的在变化(看 title 中的 r 值或者画面中噪声残留的变化)、不同算法对比时用是否是同一张噪声图(由于rng没有固定,两次imnoise产生的噪声位置可能不同,对比会失真)、视频文件是否能被主流播放器解码。最容易翻车的其实是最后一个——Matlab 在 Linux 下生成的某些编码格式 Windows 播放器不支持,保险起见统一用 Motion JPEG AVI。

注意:演示视频中的结果图应当与正文中的 PSNR 数值来源于同一组固定随机种子的运行结果。如果录视频时重新执行了脚本而没有设置rng,噪声分布就可能与论文表格中的数据对不上,这种不一致在答辩时大概率会被追问。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 23:50:16

单目相机标定原理与OpenCV实现:从张正友法到工程落地

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/16 23:47:40

16GB板载大模型:从量化到内存优化的完整实战

1. 一块16GB开发板&#xff0c;面对17.66GB的模型&#xff0c;第一个动作是什么我刚拿到任务时&#xff0c;对方把两张图发给我&#xff1a;一张是模型文件大小&#xff0c;17.66GB&#xff1b;一张是开发板参数&#xff0c;16GB内存。我的第一反应是“这怕不是要用内存卡当硬盘…

作者头像 李华
网站建设 2026/9/16 23:47:03

AVFoundation实战:从自定义相机到直播推流的完整指南

第一次在项目里接到“做一个能拍短视频的功能”这个需求时&#xff0c;我第一反应是直接拖一个UIImagePickerController上去。说实话&#xff0c;那会儿20分钟就能拍照、录视频&#xff0c;看起来效率很高。但产品需求一旦变成“录到12秒自动停、拍摄界面要自定义UI、直播要实时…

作者头像 李华
网站建设 2026/9/16 23:46:02

麒麟V10 ARM平台部署达梦数据库DM8实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/16 23:45:59

NAS、SAN、ISCSI到底啥区别?从文件级到块级存储的选型指南

打开购物网站搜“NAS”&#xff0c;能看到几百块的玩客云&#xff0c;也能看到上万块的群晖企业级&#xff1b;搜“SAN”&#xff0c;出来的基本是机柜、光纤线和一个让人不敢追问的价格&#xff1b;再搜“ISCSI”&#xff0c;大多文章写得太硬核&#xff0c;读三行就劝退。很多…

作者头像 李华
网站建设 2026/9/16 23:44:57

WinCC V7.5 SP1安装与服务器授权选型实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华