简介:数字图像处理方向的本科毕业设计论文,面向电子信息工程、计算机等专业需要完成图像处理课题的学生与指导教师,聚焦数字电视中的关键环节——数字图像缩放技术。文档完整保留了任务书、摘要、目录与各章节的论文结构,围绕最近邻域插值、双线性插值、双三次插值等经典算法讲解原理与适用场景,并用 MATLAB 编程实现与实验,对多种算法的性能与运算量作出对比分析,同时交代了数字图像的采集、存储、处理、分析流程及常见文件格式等基础内容。压缩包共 1 个 doc 文件,约 2.05MB,章节编号规范、论述连贯,可作为选题参考、写作框架与算法实验的对照材料。目前已有 915 人学习下载,适合需要借鉴论文结构、梳理插值算法脉络或补充 MATLAB 仿真实现思路的读者。
1. 从一段 720P 素材要投到 1080P 屏说起:这个选题到底要交什么
一段 1280×720 的素材,直接铺到一块 1920×1080 的固定像素屏上,中间那道坎就是数字图像缩放。数字图像处理里最容易被低估的毕设题目之一,就是这个:它不像目标检测那样能靠调一个现成模型糊过去,也不像图像增强那样肉眼看着好看就行——放大一倍的图,边缘是硬是糊、是出现锯齿还是出现振铃,全部可以从像素值里量出来。这道题要交的东西很明确:把最近邻、双线性、双三次这三种经典插值算法用 MATLAB 亲手写出来,再挑四五种改进算法落地,最后用同一组测试图、同一套指标把性能和运算量摆平对比。适合电子信息工程、通信、计算机方向做毕业设计或课程设计的同学,也适合想把图像几何变换这一块补扎实的从业者。
2. 需求与技术路线:为什么用 MATLAB 把插值算法拆成可对比的实验
2.1 分辨率谱系决定了缩放这件事绕不开
数字电视的信号源和显示终端从来不是一一对应的。节目源可能是 1080i 的隔行信号,终端可能是一块固有分辨率只有 1366×768 的液晶屏,中间还可能经过机顶盒的一次变换。所谓固有分辨率,指的是显示设备不依赖行倍频、行内插这类手段本身能达到的像素排列规模,对等离子、液晶、数字光处理这类固定像素屏来说,它等于面板实际的像素结构。
常见的三档高清格式差异不小,做题目时把它们列清楚,第一章的理论铺垫就有了落点:
| 格式 | 可见扫描线 | 分辨率 | 扫描方式 | 场/帧率 | 行频 |
|---|---|---|---|---|---|
| 1080i | 1080 条(共 1125 条) | 1920×1080 | 隔行 | 60Hz | 33.75kHz |
| 720P | 720 条(共 750 条) | 1280×720 | 逐行 | 60Hz | 45kHz |
| 1080P | 1080 条(共 1125 条) | 1920×1080 | 逐行 | 60Hz | 专业格式 |
这三档都是 16:9 的宽高比,和传统 4:3 的模拟电视完全不同。有个反直觉的点值得在论文里点出来:对电视机处理能力(带宽)的要求是 1080i 反而低于 720P,因为隔行只传一半行,逐行要传满。这意味着同样一颗缩放芯片,处理 1080i 源和处理 720P 源的负载并不一样,运算量分析不能只看像素总数。
把这条链条讲透,缩放的合法性就成立了:任何终端收到非固有分辨率的信号,都必须做一次重采样。采样点不够就补,采样点多了就并,补和并的规则,就是插值算法。
2.2 技术路线为什么选 MATLAB 而不是 C 加图像库
这个题目用 MATLAB 做,不是图省事,是图「可比」。三个理由:
第一,MATLAB 里一幅灰度图就是一个 double 矩阵,img(i,j)直接就是像素值,插值公式写在纸上是什么样,代码里就是什么样。用 C 或 C++ 加第三方库,光是uint8指针、通道步长、内存对齐就要花掉两周,真正研究算法的时间被挤没了。
第二,MATLAB 自带imread、imshow、rgb2gray、imresize,读写显示和参考实现都是现成的。imresize尤其重要——它是后面自检的标尺,自己写的双三次和它的结果对不上,八成是自己错了。
第三,脚本天然可复现。一组测试图、一组缩放倍数、一张结果表,别人拿到你的.m文件跑一遍就能复现,这在答辩现场是硬通货。
代价也要写进去:MATLAB 是解释执行,绝对耗时不能代表算法在真实芯片上的性能,所以运算量分析要用「每像素乘法次数 × 像素总数」这种与语言无关的度量,再辅以相对耗时做交叉验证。这一点在论文的算法评价章节里必须交代清楚,否则评委一句「你这个 0.3 秒能说明什么」就问住了。
2.3 四层结构:理论、经典算法、改进算法、对比实验
整篇论文的骨架可以按交付物来切,每一章都有明确的产出,不是凑字数:
| 章节 | 交付物 | 答辩时的证据 |
|---|---|---|
| 绪论 | 格式谱系、研究意义 | 一张分辨率对照表 |
| 理论基础 | 插值数学定义、数字图像与 MATLAB 基础 | 采样量化公式、图像矩阵示意 |
| 传统算法 | 三种经典插值的推导与代码 | 三份可运行脚本 |
| 改进算法 | 四种主流方案的实现与评价 | 四份脚本 + 各自的适用场景结论 |
| 对比实验 | 性能与运算量数据 | 一张横向对比表 + 若干局部放大图 |
进度上,前三周啃插值数学和数字图像基础,第三到第六周把 MATLAB 环境和主流算法摸一遍,一半毕设时间用来写代码跑数据,最后三到四周成文和答辩。这个节奏里最容易失控的是「写代码跑数据」那一段,因为算法一多,脚本会互相污染,必须从一开始就定好统一的函数签名和测试集。
我一般会要求学生先写一个run_all.m主控脚本,所有算法都注册进去,一键跑完全部组合并输出表格。这样改一个算法不用手动重跑十次,也不会出现「这张图是用旧版代码跑的」这种答辩现场翻车。
3. 总体设计:一套能跑通三种经典插值的坐标映射引擎
3.1 把缩放拆成位置计算与灰度重建两步
所有插值缩放,本质都是两步:先算出目标图上每个像素对应源图的哪个位置,再根据这个位置周围的已知像素重建出灰度值。第一步叫坐标映射,第二步叫灰度重建。
映射方向必须选反向。正向映射是把源像素按缩放比例推到目标网格上,问题是缩放比例不是整数时,推过去的位置会落在非整数格点上,有的目标像素被推了两次,有的一个都没推到,出现空洞。反向映射反过来,遍历目标图的每个像素,问一句「你该从源图哪里取值」,每个目标像素都有且只有一个答案,不会漏也不会重。
function [xPos, yPos] = build_map(H, W, H2, W2) % 生成目标网格到源图像的反向映射坐标表 % H, W : 源图高、宽 % H2, W2 : 目标图高、宽 % 返回列向量 xPos (H2×1) 与行向量 yPos (1×W2) sx = H / H2; % 垂直方向缩放步长 sy = W / W2; % 水平方向缩放步长 xPos = ((1:H2)' - 0.5) * sx + 0.5; % 目标像素中心 -> 源坐标 yPos = ((1:W2) - 0.5) * sy + 0.5; end-0.5和+0.5这两处不是装饰。MATLAB 的索引从 1 开始,像素的「中心」在整数索引上,但几何上它占据的是[i-0.5, i+0.5]这个区间。目标像素的中心坐标是i,映射到源图后得到x,如果直接拿x和整数索引对齐,整幅图会整体偏移半个像素。半像素在放大两倍时肉眼看不出来,但在 PSNR 上会掉一两个 dB,而且做上下采样往返测试时误差会累积。
有了映射表,最近邻插值就是一行索引:
function out = scale_nn(img, H2, W2) [H, W] = size(img); [xPos, yPos] = build_map(H, W, H2, W2); xi = min(max(round(xPos), 1), H); % 取最近整数索引并钳位到边界内 yi = min(max(round(yPos), 1), W); out = img(xi, yi); % 向量化索引,一次取完整个目标图 endmin(max(..., 1), H)是边界钳位,防止源坐标落在图像外导致索引越界。这段代码体现的是 MATLAB 的向量化能力:img(xi, yi)里的xi是列向量、yi是行向量,MATLAB 会自动做外积式的索引展开,一次取出H2×W2个像素,比双重循环快一个数量级。后面讲运算量时,这种向量化写法不能拿来和循环写法的耗时直接比,这一点在第 5 章会单独说。
3.2 三种经典插值:核函数不同,代价和效果就不同
双线性插值取目标点周围 2×2 的四个已知像素,按距离做加权。距离越近权重越大,权重是两个方向线性函数的乘积。
function out = scale_bilinear(img, H2, W2) [H, W] = size(img); [xPos, yPos] = build_map(H, W, H2, W2); out = zeros(H2, W2); for i = 1:H2 x = xPos(i); x1 = min(max(floor(x), 1), H - 1); % 左上角邻域,留出 +1 的空间 dx = x - x1; % 垂直方向的小数偏移 for j = 1:W2 y = yPos(j); y1 = min(max(floor(y), 1), W - 1); dy = y - y1; % 水平方向的小数偏移 out(i,j) = (1-dx)*(1-dy)*img(x1, y1) ... + (1-dx)* dy *img(x1, y1+1) ... + dx *(1-dy)*img(x1+1, y1) ... + dx * dy *img(x1+1, y1+1); end end enddx、dy是目标点落在 2×2 邻域内的相对位置,取值在[0,1)。四个权重之和恒为 1,这是插值的一个基本约束:常数区域缩放后必须还是同一个常数,否则整幅图的亮度会随缩放倍数漂移。
双三次插值把邻域扩到 4×4,用三次卷积核加权。核函数最常见的是 Keys 提出的形式,参数a取 -0.5:
function w = cubic_kernel(t) % Keys 三次卷积核,a = -0.5 a = -0.5; t = abs(t); w = zeros(size(t)); i1 = t <= 1; i2 = t > 1 & t < 2; w(i1) = (a+2)*t(i1).^3 - (a+3)*t(i1).^2 + 1; w(i2) = a*t(i2).^3 - 5*a*t(i2).^2 + 8*a*t(i2) - 4*a; end这个核在|t| = 1和|t| = 2处连续,且一阶导数在|t| = 1处连续,插值出来的曲面不会出现双线性那种明显的三角形折痕。代价是 4×4 共 16 个邻域点,比双线性多四倍。
三种算法的差异可以直接列表对比,这张表是论文第三章的收口:
| 算法 | 邻域 | 每像素乘法次数 | 连续性 | 典型问题 |
|---|---|---|---|---|
| 最近邻 | 1×1 | 0(仅索引) | 阶跃 | 锯齿、马赛克 |
| 双线性 | 2×2 | 3(可分离后) | C0 | 边缘模糊、折痕 |
| 双三次 | 4×4 | 8(可分离后) | C1 | 强边缘处振铃 |
「每像素乘法次数」这一列等下要用到,它是运算量分析的源头,也是答辩时能直接写进 PPT 的数字。
3.3 可分离性:把二维核拆成两次一维运算
直接按 4×4 邻域做二维加权,每个目标像素要做 16 次乘加。但三次卷积核是可分离的——核函数在 x 和 y 方向上独立,二维权重等于两个一维权重的乘积。这意味着可以先在水平方向插值得到一张中间图,再在垂直方向插值,两次一维运算,每次 4 个点,乘法次数降到 8 次。
function out = scale_bicubic(img, H2, W2) [H, W] = size(img); [xPos, yPos] = build_map(H, W, H2, W2); % 第一步:水平方向插值,得到 H × W2 的中间图 tmp = zeros(H, W2); for j = 1:W2 y0 = floor(yPos(j)); for k = -1:2 yk = min(max(y0 + k, 1), W); % 4 个邻点索引,边界钳位 tmp(:, j) = tmp(:, j) + cubic_kernel(yPos(j) - yk) * img(:, yk); end end % 第二步:垂直方向对中间图做同样操作 out = zeros(H2, W2); for i = 1:H2 x0 = floor(xPos(i)); for k = -1:2 xk = min(max(x0 + k, 1), H); out(i, :) = out(i, :) + cubic_kernel(xPos(i) - xk) * tmp(xk, :); end end end这里有两个设计点。一是cubic_kernel传入的是「目标坐标减去邻点坐标」,所以邻点是y0-1到y0+2,跨越了目标点两侧各两个像素,这是因为三次核的支撑区间是|t| < 2。二是第一步的输出tmp保持了原图的行数,只改变列数,这样第二步只需要处理垂直方向,中间结果的内存是H × W2而不是H2 × W2,放大倍数大时能省不少内存。
运算量的推导可以写成公式:设目标图有N = H2×W2个像素,最近邻是O(N)次索引,双线性可分离后约4N次乘加,双三次可分离后约8N次乘加。不可分离时双三次是16N,差一倍。这个结论在论文里配一张运算量随分辨率变化的曲线图,比单纯列表更有说服力。
提示:边界钳位用
min(max(...))会引入边缘像素的重复采样,放大倍数大时图像最外一圈会出现轻微拉伸。如果对边角质量敏感,可以在映射前先给源图做padarray镜像填充,再把坐标整体平移,结果比钳位自然。
4. 改进算法模块:四种主流方案的落地要点
4.1 缩小方向的近邻加邻域平均
放大用最近邻会出锯齿,缩小用最近邻更糟。缩小两倍时,源图上 2×2 的四个像素里只有一个被保留,另外三个直接丢弃,高频信息全丢,画面会出现明显的摩尔纹和闪烁。
一个低成本改法是:先按最近邻确定目标像素落在源图的哪个块,再对这个块内的所有源像素取平均。放大时块退化为 1 个像素,结果和最近邻一致;缩小时块覆盖多个像素,平均起到低通滤波的作用。
function out = shrink_avg(img, H2, W2) [H, W] = size(img); out = zeros(H2, W2); for i = 1:H2 r1 = floor((i-1) * H / H2) + 1; % 该目标行覆盖的源行起点 r2 = min(H, floor(i * H / H2)); % 覆盖的源行终点 for j = 1:W2 c1 = floor((j-1) * W / W2) + 1; c2 = min(W, floor(j * W / W2)); block = img(r1:r2, c1:c2); % 取出覆盖块 out(i,j) = mean(block(:)); % 块内平均,等效于盒式低通 end end endr1、r2的算法要保证相邻目标像素的覆盖块不重叠也不留空:第i个目标像素覆盖[(i-1)H/H2, iH/H2),向下取整后边界天然衔接。min(H, ...)处理最后一个块可能超界的情况。
这个算法的评价要写清楚:缩小倍数接近 1 时,覆盖块退化,效果和最近邻几乎一样,优势体现不出来;缩小倍数大于 2 时改善明显,但块平均是各向同性的,斜边缘会被抹平。它不是万能的,胜在实现极简、运算量低,适合做论文里的对照组。
4.2 Ferguson 曲面插值与系数自适应插值
Ferguson 曲面本质是双三次 Hermite 曲面:除了四个角点的值,还用上了角点处沿两个方向的切线和混合偏导,共 16 个参数。一维方向上,四个基函数是这样的:
function v = hermite_basis(t) % Ferguson(双三次 Hermite)曲面的四个一维基函数 t2 = t.^2; t3 = t2 .* t; h00 = 2*t3 - 3*t2 + 1; % 起点值 h10 = t3 - 2*t2 + t; % 起点切线 h01 = -2*t3 + 3*t2; % 终点值 h11 = t3 - t2; % 终点切线 v = [h00, h10, h01, h11]; end一维插值就是p = h00*p0 + h10*m0 + h01*p1 + h11*m1,其中m0、m1是两端切线。切线在图像里没有现成值,要用相邻像素的中心差分估计,比如m0 = (p1 - p_{-1}) / 2。这个估计的准确性直接决定插值质量,噪声大的图上中心差分会把噪声放大,这也是 Ferguson 曲面在实际图像上不如理论漂亮的根本原因,论文里要老老实实写这一条。
系数自适应插值走的是另一条路:不换核函数,而是让双线性和双三次的结果按局部梯度加权混合。平坦区域用双线性,避免三次核在噪声上的过冲;强边缘区域加重双三次的比例,保住锐度。
% g 为 3×3 邻域的梯度幅值,gLow/gHigh 由全图梯度的分位数确定 alpha = min(1, max(0, (g - gLow) / (gHigh - gLow))); % 归一化到 [0,1] out = (1 - alpha) * bilinear_val + alpha * bicubic_val;gLow和gHigh不能用固定阈值。不同图像的梯度分布差很多,一张纹理丰富的图用固定阈值会几乎全被判成边缘,一张平滑的图又会全被判成平坦区。通常的做法是取全图梯度幅值的 30% 和 70% 分位数作为两个端点,这样alpha的取值在每张图上都能拉开层次。这一步做完,论文里可以放一张alpha的灰度图,直观展示算法判定的边缘区域,答辩时很好讲。
4.3 边缘定向插值与多帧融合
边缘定向插值针对的是「跨边缘插值导致模糊」这个痛点。双线性在斜边缘上,2×2 邻域里通常有两个像素在边缘一侧、两个在另一侧,四个一起加权,边缘就被拉平了。改法是先判断局部边缘走向,然后只沿边缘方向取点。
% 在待插值点的 3×3 邻域内比较两个对角方向的梯度 g1 = abs(img(i-1, j-1) - img(i+1, j+1)); % 主对角线方向 g2 = abs(img(i-1, j+1) - img(i+1, j-1)); % 副对角线方向 if g1 < g2 val = (img(i-1, j-1) + img(i+1, j+1)) / 2; % 梯度小说明沿此方向变化平缓 else val = (img(i-1, j+1) + img(i+1, j-1)) / 2; end梯度小,说明这两个点大概率在同一条等灰度线上,沿这条线插值不会跨越边缘。代价是方向判断只有两个候选,遇到接近水平的边缘就退化成普通插值。论文里可以把这个简化版和一般实现做个对比,说明为什么完整的方向检测要用八个方向甚至更多,而运算量会随之上升多少。
多帧融合是另一个思路,也是这几种改进里唯一不靠单帧插值的。同一场景的多帧图像之间存在亚像素级的位移,把这些位移估计出来对齐,再融合到一张高分辨率网格上,等效采样点就变多了。关键技术是位移估计和融合权重,融合可以用共轭梯度法迭代求解一个最小二乘问题,避免直接平均带来的模糊。
这部分在论文里我建议只写到方案和公式层面,给出一段迭代核心,不要强行凑出完整实验。原因很实在:多帧融合需要一组真实的亚像素位移图像,公开数据不好找,自己拍又很难保证位移精度,硬做出来的数据反而经不起问。
4.4 评价指标:PSNR、耗时和运算量三件套
算法写完了不算完,得能量出来。评价部分必须有统一口径,否则数据没有可比性。
峰值信噪比用均方误差反推,代码极短:
function p = psnr_calc(ref, test) % ref 为参考高分辨率图,test 为缩放重建图,均为 double 型 [0,1] mse = mean((ref(:) - test(:)).^2); if mse == 0 p = Inf; else p = 10 * log10(1 / mse); % 峰值取 1(归一化后) end end关键在参考图怎么来。正确做法是:拿一张高分辨率原图,先下采样得到低分辨率图,再用待测算法放大回原尺寸,和原图比。如果直接拿原图和「原图放大两倍」比,尺寸都对不上,指标没有意义。这一条是学生最容易搞错的地方,后面第 5 章还会提。
耗时用tic/toc,但必须跑多次取中位数,且第一次调用要丢弃,因为 MATLAB 的首次函数解析开销会污染数据。运算量则用与语言无关的度量:统计每个算法的每像素乘法次数,乘以目标图像素数,得到一个理论值,再和实测耗时做相关性验证。两条线对得上,说明分析是可信的;对不上,就要回去看是不是向量化程度差异太大导致的。
5. 避坑清单:MATLAB 图像缩放实验里最容易翻车的五处
5.1 uint8 和 double 混用,结果一片惨白
现象:缩放后的图像大面积变成纯白或纯黑,边缘出现硬截断。
原因:imread读进来的彩色图默认是uint8,取值范围 0 到 255。插值过程里做乘加,uint8会饱和到 255 而不是回绕,只要有一步结果超过 255 就被钉死。双三次核有负权重,中间结果可能为负,被截成 0,振铃变成了大块黑斑。
解决:进算法前统一转成double并归一化到[0,1],img = im2double(imread('x.png'));所有中间计算都在double下做;输出前再im2uint8转回去。整条链路上,只要有一个函数用了uint8运算,前面所有精度控制都白费。
5.2 少了半个像素的偏移
现象:算法跑通了,PSNR 却比预期低两三个 dB;把放大结果和原图叠加,发现整幅图朝左上偏了半个像素。
原因:映射公式里漏了像素中心的偏移。目标像素的几何中心在索引位置,但它覆盖的区间是[i-0.5, i+0.5],映射到源图时必须用中心坐标去算,算完再转成索引。少一个+0.5,整体就平移半格。
解决:反向映射统一写成(i - 0.5) * s + 0.5的形式,s是缩放步长。这个公式在放大、缩小、任意目标尺寸三种情况下都成立,写死在build_map一个函数里,全项目只此一处,不给自己犯错的机会。改完用一张全白图和一张棋盘图验证,棋盘的黑白格边界应该正好落在整数格点上。
5.3 自写双三次和 imresize 对不上
现象:自己写的双三次放大两倍,和imresize(img, 2, 'bicubic')的结果差一大截,视觉上自己写的更糊。
原因:imresize的'bicubic'默认开启了抗混叠(antialiasing),缩小的时候会先把核按缩放比例展宽,相当于内置了一层低通;另外它的核参数和边界处理方式和你写的也不完全一样。放大倍数接近 1 时,这个差异尤其明显。
解决:验证时不要直接和imresize逐像素比。正确的做法是拿一个纯数学的测试信号,比如一维斜坡序列或者二维的二次曲面,用解析解验证自己的核函数;再在放大倍数明显大于 1.5 的情况下和imresize做视觉对比,允许微小差异。要在论文里明确写出「本文实现与工具箱默认行为在抗混叠策略上不同」,把差异说清楚,比装作一致要安全得多。
5.4 计时和运算量统计失真
现象:向量化写法的算法耗时只有循环版的三分之一,但两者的运算量分析明明差不多;同一段代码跑两次,时间差出好几倍。
原因:MATLAB 有 JIT 加速,循环结构在第二次执行时会被优化,第一次调用的耗时偏高;tic/toc测量的包含函数调用和内存分配开销,向量化写法虽然乘法次数一样,但内存访问模式完全不同;后台还有别的进程在抢 CPU。
解决:每个算法单独跑一次预热丢掉,再连续跑 5 次取中位数;测试前clear掉变量避免缓存干扰;关掉不必要的图形窗口;计时只包住核心插值循环,不含读写和显示。更重要的是,论文里的运算量主指标用「每像素乘法次数」这个理论值,实测耗时只作为辅助佐证,两者的角色不能颠倒。
5.5 彩色图像三通道的处理顺序
现象:灰度图上效果不错,换成彩色图,色块边缘出现彩色镶边,尤其是红色和蓝色的高对比区域。
原因:一是把 RGB 直接转灰度处理再转回去,颜色信息全丢了;二是三个通道独立插值,但三个通道的边缘位置并不完全重合,插值后各通道的偏移量不同,合成时出现伪彩;三是 RGB 空间本身不适合做插值,三个分量高度相关,误差会被放大。
解决:如果题目只考察算法本身,测试集统一用灰度图,把结论限定在灰度域,这是最稳妥的做法。如果必须处理彩色,先转 YCbCr(MATLAB 里rgb2ycbcr),只对亮度通道用高阶插值,两个色度通道用双线性甚至最近邻,因为人眼对色度分辨率本来就不敏感。转回 RGB 之前记得把取值范围钳到[0,1],否则又会撞上 5.1 的问题。
注意:
rgb2ycbcr的输入必须是uint8或double且在合法范围内,传进去一个含负值的中间结果会直接报错或者输出错乱。转换前后各做一次范围检查,能省掉大量排查时间。
6. 验收与答辩:一张表跑完对比,三个问题答住评委
验收这件事,不能等到论文写完才想。我一般会在写代码的第一周就把最终的对比表格式定下来,所有实验都往这个表里填,缺哪一格补哪一格。表大概是这样的:
| 算法 | 放大 2 倍 PSNR(dB) | 缩小 2 倍 PSNR(dB) | 每像素乘法次数 | 实测耗时(ms) | 主观评价 |
|---|---|---|---|---|---|
| 最近邻 | 低,锯齿明显 | 低,摩尔纹 | 0 | 最短 | 边缘硬,块状 |
| 双线性 | 中等 | 中等 | 3 | 短 | 平滑但糊 |
| 双三次 | 较高 | 较高 | 8 | 中等 | 锐但有振铃 |
| 近邻+邻域平均 | 放大同最近邻 | 缩小提升明显 | 约 4 | 短 | 缩小时较自然 |
| Ferguson 曲面 | 高 | 高 | 16 | 长 | 噪声放大 |
| 边缘定向 | 边缘区域高 | — | 约 12 | 较长 | 斜边缘清晰 |
有了这张表,答辩时最常被问的三个问题就都有答案了。
第一个问题:「你这几种算法到底哪个最好?」标准答案是没有最好,只有适配。放大且要求实时,选双线性;放大且要求画质、后处理有余量,选双三次;缩小且运算受限,选近邻加邻域平均;图像噪声大,三次核的振铃会很难看,反而不如双线性。能把这个取舍讲清楚,比背一个排名有价值得多。
第二个问题:「你的数据和别人的能比吗?」答案取决于口径是否交代清楚。测试图来源、缩放倍数、参考图的获取方式、PSNR 的峰值取值、耗时是否含读写,这五项必须在论文里写死。任何一项含糊,数据就不可比。
第三个问题:「这个算法能上硬件吗?」这时候运算量分析就派上用场了。每像素 8 次乘法的双三次,1920×1080 一帧是约 1660 万次乘法,60 帧每秒就是 10 亿次,这个量级能不能接受,取决于目标平台的算力。把这条推算写进论文,比空谈「具有一定的工程价值」实在得多。
现场演示我建议准备一个demo.m,输入一张测试图、一个缩放倍数和一个算法名,直接输出三张图:原图、缩放结果、误差放大图。误差放大图就是把abs(ref - test)拉伸到可视范围,振铃和锯齿一眼就能看出来,比讲十句原理都直接。
从那以后我每带一个学生做这个题目,都强制要求他在提交前把run_all.m从头到尾跑一遍,中间不许手动干预,跑出来的表必须和论文里的数字一字不差。有一次一个学生的表格是手抄的,抄错了一位小数,答辩时被问到具体数值,当场对不上,后面的问题全乱了。这种错误不值得犯,也不难防。希望帮到你。
本文还有配套的精品资源,点击获取