参考文章
(1条消息) 几种常用的插值和分段插值方法Matlab算法实现_树莓、的博客-CSDN博客_分段线性插值matlab
MATLAB 图像的插值算法2:最近邻插值_Effend的博客-CSDN博客_matlab最近邻插值
[数字图像处理](六)插值运算
前言
本文章介绍的几种算法都是用变化后的坐标(((n*R || m*R)R 为变化率(如1.5))) 来计算映射到原始图像的位置,有很多博客和wiki都介绍了这些算法的数学原理,这里就不做介绍了就是数学不好。
本文章就matlab代码,来解释算法的执行逻辑,以便于更好的理解算法的实际思想。
1____最近邻插值法
基本思想
下文会用到的标记
-
transim()变换后的图像
-
grayim()变换之前的图像
-
n,m——grayim的大小,c,l——transim的大小
-
R变换率——(n*R = c,m*R = l)
最近邻插值法,本质上就是变换后图像的坐标等比映射到原图像取值
$ transim(i,j) = grayim( round(i/R),round(j/R) ) $
实现代码
%% nearest_neighbor
clc;
clear all;
close all;
rgbim = imread('p2.png');
grayim = rgb2gray(rgbim);
[n,m] = size(grayim);
figure;
imshow(grayim);
%% 设置变换率
R = 2.8;
n = round(n*R);% 四舍五入
m = round(m*R);
%% 变换
transim = zeros(n,m,class(grayim));% class的作用的把transim的数据类型变成和grayim一直的数据类型
for i = 1:1:n
for j = 1:1:m
x = round(i/R) ;% 映射到原图像
y = round(j/R);
if x == 0 % 考虑到边界问题
x = x + 1;
end
if y == 0
y = y + 1;
end
%------------
transim(i,j) = grayim(x,y);
end
end
%% 输出图像
figure;
imshow(transim);
imwrite(transim,'transim.png');
2____双线性插值法
前言
我在学习了最近邻插值法之后,想学的是线性插值法,去了解了之后发现,这是一个处理一维图像的算法。在粗略的了解与思考之后发现其实也是可以做二维图像的,只不过说处理时只能参考横向偏移量,或者纵向偏移量,有一定的局限性。
所以在这里我就直接跳过线性插值法,直接来说说双线性插值法
基本思想
如果知道线性插值法是如何处理的,那么双线性插值法也就明白了。
同时双线性插值法也是最近邻插值法的优化,在最近邻插值法中,我们直接用等比缩放的映射值来充当变换图像的灰度值(详见上),这样就浪费了很多领域的信息,如果把领域的信息利用起来,是不是就可以在一定程度上提升画质呢(通过之前学习的各种优化来推到)?
双线性插值法就是这样的思路,利用到了映射之后的领域信息,以及映射的比率来确定横纵上的偏移量,我这有系统的说,肯定很多小伙伴是云里雾里,但是看了下面的描述,再来看这段文字,必定茅塞顿开。
-
理解偏移量 (u,v)
-
横向:(u = frac{i}{R} - floor(frac{i}{R}))
-
纵向:(v = frac{i}{R}-floor(frac{j}{R}))
如何理解这个偏移量呢?
我们假设 $ i = 7,j = 131, R = 0.5 $
那么(u = 3.5 - 3 = 0.5) 这个0.5就对应的是上图的u,从图像的意义来解释,这个值反应的是是这个映射坐标本质上是更靠近x还是x+1 (因为很有可能不同的i,在同一R的情况下,能得到相同的映射坐标x)那么在这个时候,有了u以及v这个偏移量,就能更好的反应出图像的映射关系,进而得到更真实的变化图像。
同理,你也可以试着来设定一些y值来理解一下在纵向上的偏移量。
-
-
如果得到最终图像
查看上图我们发现,我们运用的是3*3领域中的4个边角,从坐标的描述上我们就可以得到,下面的计算式子(如果看不懂的话,可以结合上面的图来分析)
(transim(i,j) = u*v*grayim(x,y) + (1-u)*v*grayim(x+1,y) + u*(1-v)*grayim(x,y+1)+(1-u)*(1-v)*grayim(x+1,y+1);)
实现代码
%% 双线性插值法
clc;
close all;
clear all;
rgbim = imread('p2.png');
grayim = rgb2gray(rgbim);
figure;
imshow(grayim);
R = 0.4; % 变换率
[n,m] = size(grayim);
ans = round(3/2)
n = round(n*R); % 变换后的宽
m = round(m*R); % 变换后的高
%% 变换
transim = zeros(n,m,class(grayim));
for i = 1:1:n
for j = 1:1:m
x = round(i/R); % 映射到原图像的位置
y = round(j/R); % 映射到原图像的位置
if x == 0
x = x+1; end
if y == 0
y = y +1; end
%-----------------求得偏移量
u = i/R - floor(i/R); % 水平
v = j/R - floor(j/R); % 垂直
% 对于在边缘位置的图像用最近邻插值法
if i >= n - R || j >= m - R;
transim(i,j) = grayim(x,y);
else transim(i,j) = u*v*grayim(x,y) + (1-u)*v*grayim(x+1,y) + u*(1-v)*grayim(x,y+1)+(1-u)*(1-v)*grayim(x+1,y+1);
end
end
end
%% 输出结果
figure;
imshow(transim);
imwrite(transim,'BI.png');