参考:
https://blog.csdn.net/huang1024rui/article/details/46545329
<https://blog.csdn.net/huang1024rui/article/details/46545329>
数字图像处理

双线性插值算法

介绍


双线性插值法又称为二次线性插值法。在传统的插值算法中,它的插值效果比nearest插值法要好的多,但是速度上也必然会慢很多,比bicubic(二次立方法)效果要差,
但速度上要优于bicubic。
它主要思想就是利用某像素点周围的4个像素来计算出浮点坐标像素值。

举个例子,假设我们现在需要获得坐标为(6.6,4)的像素值T,该坐标离(6,4)和(7,4)这2个像素点最近。设(6,4)像素值为T_64,(7,4)像素值为T_74,直观地表现在图上就是:

按照距离越近混合的比例越大的原则可以得到:

其中u,v分别表示浮点坐标距离(6,4)和(7,4)这2个像素点的距离。此时就使用了一次线性插值得到了(6.6,4)的像素值。

通过上面一个简短的例子,我们知道了如何使用2个邻点来计算出坐标分量有一个为小数的情况,那么如果我们坐标分量2个都为小数呢,该如何插值?双线性插值通过多次线性插值就解决了这样的问题。
如图:

上图的求解思路用语言表述就是:先用一次线性插值分别求出f1、f2的像素值,然后再对f1、f2利用一次线性插值得到f的像素值。这就是双线性插值的原理。
用公式来展示一下求解的过程:
先求出2个红点的像素值,然后根据这2个像素值做一次线性插值得到目标点f的像素值。




伪代码

输入:
Img:原始图像
zmf:为缩放因子
输出:
new_img:输出图像

step1:求出原图像Img的大小,记为height×width×channel,接着生成大小为(zmf×height)×(zmf×width)×channel的全0矩阵new_img;
step2 :把Img边界扩展一圈得到IT,大小为(height+2)×(width+2)×channel;
step3
:对于缩放后的新图new_img中某像素位置(zi,zj)映射回(zi/zmf,zj/zmf)原图Img中得到(x,y),由于(x,y)不一定为整数,故向下取整得到(i,j),其中x
= i+u,y = j+v,且u,v[0,1)为小数部分;
step4 :根据下式进行双线性插值计算f(zi,zj)的值,也就是其对应的像素值。

f(zi,zj)=f(x,y)=(1-u)×(1-v)×f(i,j)+(1-u)×v×f(i,j+1)+u×(1-v)×f(i+1,j)+u×v×f(i+1,j+1);
其中f(zi,zj)表示新图(zi,zj)处的像素值,f(x,y)表示新图(zi,zj)对应在原图中的位置(x,y)处的像素值;
step5:重复3-4,直至将矩阵new_img

2 matlab代码

2.1 主程序代码
clear; close all; clc; img = imread('image/my_gray_512.jpg'); [ori,img_new] =
imblizoom(img,0.5); % [ori,img_new] = imblizoom('image/my_gray_512.jpg',0.5);
img_show(ori,img_new);
2.2 核心代码
function [ original,new_img ] = imblizoom( original,zmf ) % % % % % % % % % %
% % % % % % % % % % % % % % % % % % % % % % % %
%-----------------双线性插值法缩放矩阵或图像--------------------- % Input: %
original:原始图像图像文件名或矩阵(整数值(0~255)) % zmf:缩放因子,即缩放的倍数 % Output: % original: 原始图像矩阵
% new_img: 缩放后的图像矩阵 % Usage: % [original,new_img] =
imblizoom('ImageFileName',zmf) % 对图像I进行zmf倍的缩放 % Or: % [original,new_img] =
imblizoom(I,zmf) % 对矩阵I进行zmf倍的缩放 % % % % % % % % % % % % % % % % % % % % % % %
% % % % % % % % % % % %% Step1 对数据进行预处理 if ~exist('original','var') || isempty
(original) error('输入图像 I未定义或为空!'); end if ~exist('zmf','var') || isempty(zmf) ||
numel(zmf) ~= 1 error('位移矢量 zmf未定义或为空或 zmf中的元素超过2!'); end if isstr(original)
[original,M] = imread(original); end if zmf <= 0 error('缩放倍数 zmf的值应该大于0!'); end
%% Step2 通过原始图像和缩放因子得到新图像的大小,并创建新图像 [height,width,channel] = size(original);
new_height =round(height*zmf); % 计算缩放后的图像高度,最近取整 new_width = round(width*zmf);
% 计算缩放后的图像宽度,最近取整 new_img = zeros(new_height,new_width,channel); % 创建新图像 %%
Step3 扩展原始矩阵I边缘 img_scale = zeros(height+2,width+2,channel); % 为了边界点考虑的
img_scale(2:height+1,2:width+1,:) = original; % %
======================================================== % 为4周各添加的一行或列做值的初始化 %
% ========================================================= % 为扩展而来的各边赋值
img_scale(1,2:width+1,:) = original(1,:,:); img_scale(height+2,2:width+1,:) =
original(height,:,:); img_scale(2:height+1,1,:) = original(:,1,:); img_scale(2
:height+1,width+2,:) = original(:,width,:); % 用原图的4个顶点为扩展而来的4个顶点赋值 img_scale(1,1
,:) = original(1,1,:); img_scale(1,width+2,:) = original(1,width,:);
img_scale(height+2,1,:) = original(height,1,:); img_scale(height+2,width+2,:) =
original(height,width,:);%%
============================================================ % Step4
由新图像的某个像素(zi,zj)映射到原始图像(ii,jj)处, 并在原始 % 图像的(ii,jj)位置利用其周围4个像素点进行插值得到(ii,jj)处的像素值
% % ==================================================================== for zj
=1:new_width % 对图像进行按列逐元素扫描 for zi = 1:new_height %
(zi,zj)表示在新图中的坐标,(ii,jj)表示在原图中的坐标 % 注意:(ii,jj)不一定是整数 ii = (zi-1)/zmf; jj = (zj-1
)/zmf;i = floor(ii); j = floor(jj); % 向下取整得到在原图中坐标的整数部分 u = ii - i; v = jj - j;
% 得到在原图中坐标的小数部分 i = i + 1; j = j + 1; new_img(zi,zj,:) = (1-u)*(1-v)*img_scale(i
,j,:) + u*(1-v)*img_scale(i,j+1,:)... + (1-u)*v*img_scale(i+1,j,:) +
u*v*img_scale(i+1,j+1,:); end end new_img = uint8(new_img); end
2.3 用于显示的代码
function img_show(original,new_img) [height,width,channel] = size(original);
figure;imshow(original); axison title(['原图像(大小: ',num2str(height),'*'
,num2str(width),'*',num2str(channel),')']); [new_height,new_width,~]
=size(new_img); figure;imshow(new_img); axison title(['缩放后的图像(大小: '
,num2str(new_height),'*',num2str(new_width),'*',num2str(channel)',')']); end

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:[email protected]
QQ群:637538335
关注微信