前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >双线性插值算法详解并用matlab实现「建议收藏」

双线性插值算法详解并用matlab实现「建议收藏」

作者头像
全栈程序员站长
发布2022-06-30 19:59:31
1.7K0
发布2022-06-30 19:59:31
举报

大家好,又见面了,我是你们的朋友全栈君。

参考: 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 主程序代码

代码语言:javascript
复制
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 核心代码

代码语言:javascript
复制
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 用于显示的代码

代码语言:javascript
复制
function img_show(original,new_img) [height,width,channel] = size(original);
figure;imshow(original);
axis on
title(['原图像(大小: ',num2str(height),'*',num2str(width),'*',num2str(channel),')']);
[new_height,new_width,~] =size(new_img); 
figure;imshow(new_img);
axis on
title(['缩放后的图像(大小: ',num2str(new_height),'*',num2str(new_width),'*',num2str(channel)',')']); end

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/132017.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 双线性插值算法
    • 介绍
      • 伪代码
      • 2 matlab代码
        • 2.1 主程序代码
          • 2.2 核心代码
            • 2.3 用于显示的代码
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档