大家好,又见面了,我是你们的朋友全栈君。
参考:
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);
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
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/132017.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...