#MATLAB编写双线性插值用于缩放图像,程序均为自己编写,供学习使用。 #程序包含详细注释,本人在2020a版本均可运行。
先看坐标映射部分的关键代码:
% 计算目标图像坐标对应到原图的浮点位置 src_x = (col - 0.5) * (src_width/dst_width) + 0.5; src_y = (row - 0.5) * (src_height/dst_height) + 0.5;这里有个容易踩坑的点:坐标偏移量处理。减0.5是为了将像素坐标系转换为笛卡尔坐标系,避免放大时边缘像素被重复采样。这个操作直接影响后续插值的准确性,试过不加的话缩放后图像边缘会有明显锯齿。
取整数部分和小数部分的操作很关键:
x1 = floor(src_x); y1 = floor(src_y); x2 = x1 + 1; y2 = y1 + 1; dx = src_x - x1; dy = src_y - y1;这里dx和dy就是权重分配的比例系数。注意边界处理——当映射到原图边缘时x2或y2可能超出范围,需要做clamp操作:
x2 = min(x2, src_width); y2 = min(y2, src_height);这个min函数看起来简单,但实测发现漏掉的话缩放某些尺寸的图片时会直接报数组越界错误。调试时遇到过因为忽略边界处理导致程序随机崩溃,排查了半小时才定位到问题。
#MATLAB编写双线性插值用于缩放图像,程序均为自己编写,供学习使用。 #程序包含详细注释,本人在2020a版本均可运行。
核心插值计算部分:
% 四个角点的像素值,注意转换为double类型做运算 v11 = double(original_img(y1, x1, :)); v12 = double(original_img(y1, x2, :)); v21 = double(original_img(y2, x1, :)); v22 = double(original_img(y2, x2, :)); % 双线性插值公式 interp_val = (1-dx)*(1-dy)*v11 + dx*(1-dy)*v12 +... (1-dx)*dy*v21 + dx*dy*v22;这里的维度顺序要注意:MATLAB图像数据是行在前,所以访问原图时坐标是(y,x)。彩色图像需要单独处理每个颜色通道,但得益于MATLAB的矩阵运算特性,冒号操作符能直接处理三维数组。
完整函数封装示例:
function output_img = bilinear_interp(original_img, new_size) % 获取原始尺寸 [src_height, src_width, channels] = size(original_img); dst_height = new_size(1); dst_width = new_size(2); % 初始化输出图像 output_img = zeros(dst_height, dst_width, channels, 'uint8'); % 遍历目标图像每个像素 for row = 1:dst_height for col = 1:dst_width % 坐标映射(核心代码块) src_x = (col - 0.5) * (src_width/dst_width) + 0.5; src_y = (row - 0.5) * (src_height/dst_height) + 0.5; % 边界保护 x1 = max(1, floor(src_x)); y1 = max(1, floor(src_y)); x2 = min(x1+1, src_width); y2 = min(y1+1, src_height); % 权重计算 dx = src_x - x1; dy = src_y - y1; % 四邻域采样 v11 = double(original_img(y1, x1, :)); v12 = double(original_img(y1, x2, :)); v21 = double(original_img(y2, x1, :)); v22 = double(original_img(y2, x2, :)); % 混合计算 interp_val = (1-dx)*(1-dy)*v11 + dx*(1-dy)*v12 +... (1-dx)*dy*v21 + dx*dy*v22; % 写入结果 output_img(row, col, :) = uint8(round(interp_val)); end end end测试时发现几个有趣现象:缩小图像时双线性比最近邻明显更平滑,但放大到400%以上时还是能看出模糊。和imresize对比,边缘处理有些微差异,主要因为MATLAB内置函数可能有更复杂的边界处理机制。
运行示例:
img = imread('lena.jpg'); resized_img = bilinear_interp(img, [800 800]); imshow(resized_img);注意原图尺寸最好是整数倍变化,否则缩放比例非整数时需要更复杂的处理。实际测试时用512x512缩到768x768效果最佳,而缩到素数尺寸如701x709时也能正常工作,说明算法具有普适性。