★由于之前学习笔记（四）有对于图像三种插值的理论讲解，这里就不再赘余；

## 一、Pycharm实现过程

``````from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import math

def NN_interpolation(img,dstH,dstW):
scrH,scrW,_=img.shape
retimg=np.zeros((dstH,dstW,3),dtype=np.uint8)
for i in range(dstH):
for j in range(dstW):
scrx=round((i+1)*(scrH/dstH))
scry=round((j+1)*(scrW/dstW))
retimg[i,j]=img[scrx-1,scry-1]
return retimg

def BiLinear_interpolation(img,dstH,dstW):
scrH,scrW,_=img.shape
retimg=np.zeros((dstH,dstW,3),dtype=np.uint8)
for i in range(dstH):
for j in range(dstW):
scrx=(i+1)*(scrH/dstH)-1
scry=(j+1)*(scrW/dstW)-1
x=math.floor(scrx)
y=math.floor(scry)
u=scrx-x
v=scry-y
retimg[i,j]=(1-u)*(1-v)*img[x,y]+u*(1-v)*img[x+1,y]+(1-u)*v*img[x,y+1]+u*v*img[x+1,y+1]
return retimg

def BiBubic(x):
x=abs(x)
if x<=1:
return 1-2*(x**2)+(x**3)
elif x<2:
return 4-8*x+5*(x**2)-(x**3)
else:
return 0

def BiCubic_interpolation(img,dstH,dstW):
scrH,scrW,_=img.shape
retimg=np.zeros((dstH,dstW,3),dtype=np.uint8)
for i in range(dstH):
for j in range(dstW):
scrx=i*(scrH/dstH)
scry=j*(scrW/dstW)
x=math.floor(scrx)
y=math.floor(scry)
u=scrx-x
v=scry-y
tmp=0
for ii in range(-1,2):
for jj in range(-1,2):
if x+ii<0 or y+jj<0 or x+ii>=scrH or y+jj>=scrW:
continue
tmp+=img[x+ii,y+jj]*BiBubic(ii-u)*BiBubic(jj-v)
retimg[i,j]=np.clip(tmp,0,255)
return retimg

im_path='/home/jovyan/img/earth.jpg'
image=np.array(Image.open(im_path))

image1=NN_interpolation(image,image.shape[0]*2,image.shape[1]*2)
image1=Image.fromarray(image1.astype('uint8')).convert('RGB')
image1.save('/home/jovyan/img/NNEarth.jpg')

image2=BiLinear_interpolation(image,image.shape[0]*2,image.shape[1]*2)
image2=Image.fromarray(image2.astype('uint8')).convert('RGB')
image2.save('/home/jovyan/img/BiLinearEarth.jpg')

image3=BiCubic_interpolation(image,image.shape[0]*2,image.shape[1]*2)
image3=Image.fromarray(image3.astype('uint8')).convert('RGB')
image3.save('/home/jovyan/img/BiCubicEarth.jpg')
``````

：3是原图，4是最近邻插值，2是双线性内插法，1是双三次内插法；

## 二、MATLAB实现过程

①最近邻插值

``````% 最近邻插值

% 输入图像文件及放大率

% 输出根据放大率变化后的新图像

function nearest_neighbor = nearest_neighbor(filename,R)

% 初始化，读入图像，图像数据为m*n*color

% 变化后图像

[row,col,color] = size(img);    % 获得图像的行列数及色板数

row = round(row*0.8);     % 新图像行

col = round(col*0.8);     % 新图像列

% 新图像初始化

% 使用class获得原图像的数据类型，使得新图像数据类型与原图像保持一致

img_new = zeros(row,col,color,class(img));

% 对新图像的行、列、色板赋值

for i = 1:row

for j = 1:col

for n = 1:color

x = round(i/0.8);

y = round(j/0.8);

% 为了避免x和y等于0而报错，采取+1处理即可

if x == 0

x = x+1;

end

if y == 0

y = y+1;

end

img_new(i,j,n) = img(x,y,n);

end

end

end

% 显示原图像

figure;

imshow(img);

title("Original Image");

% 显示新图像

figure;

imshow(img_new);

title("New Image");
end
``````

②双线性插值

``````% 双线性插值

% 输入图像文件及放大率

% 输出根据放大率变化后的新图像

function bilinear_interpolation = bilinear_interpolation(filename,R)

% 初始化，读入图像，图像数据为m*n*color

% 变化后图像

[row,col,color] = size(img);    % 获得图像的行列数及色板数

row = round(row*0.8);     % 新图像行

col = round(col*0.8);     % 新图像列

% 新图像初始化

% 使用class获得原图像的数据类型，使得新图像数据类型与原图像保持一致

img_new = zeros(row,col,color,class(img));

% 对新图像的行、列、色板赋值

for i = 1:row

for j = 1:col

for n = 1:color

x = round(i/0.8);

y = round(j/0.8);

if x == 0

x = x+1;

end

if y ==0

y = y+1;

end

u = i/0.8-floor(i/0.8); %求取水平方向上的权重

v = j/0.8-floor(j/0.8); %求取垂直方向上的权重

% 此处需要对图像边缘进行例外处理

% 本例对图像右边缘及下边缘用最近邻插值计算

if i >= row-0.8 || j >= col-0.8

img_new(i,j,n) = img(x,y,n);

else

img_new(i,j,n) = u*v*img(x,y,n)+(1-u)*v*img(x+1,y,n)+u*(1-v)*img(x,y+1,n)+(1-u)*(1-v)*img(x+1,y+1,n);

end

end

end

end

% 显示原图像

figure;

imshow(img);

title("Original Image");

% 显示新图像

figure;

imshow(img_new);

title("New Image");
``````

③双三次插值

``````% Author: Dabao

% Time: 2020年4月15日09:12:59

tic; % calculate running time

I = double(I);

[oh,ow,od] = size(I);

zmf = 2; %缩放因子

% initial target image TI

th = round(oh*zmf);

tw = round(ow*zmf);

TI = zeros(th,tw,od); %预分配内存提高计算速度

% add original image with 2 rows and 2 cols

% expand the border to prevent calculation overflow

a = I(1,:,:); b = I(oh,:,:);

temp_I = [a;a;I;b;b];

c = temp_I(:,1,:); d = temp_I(:,ow,:);

FI = [c,c,temp_I,d,d];

% fill target image with new pixels

for w = 1:tw

j = floor(w/zmf)+2; v = rem(w,zmf)/zmf;

for h = 1:th

i = floor(h/zmf)+2;  u = rem(h,zmf)/zmf;

A = [s(u+1),s(u),s(u-1),s(u-2)];

C = [s(v+1);s(v);s(v-1);s(v-2)];

for d = 1:od   % image's 3 channels

B = FI(i-1:i+2,j-1:j+2,d);

TI(h,w,d) = A*B*C;

end

end

end

figure;

imshow(uint8(TI));

toc;

% 插值核函数

function w = s(wx)

wx = abs(wx);

if wx<1

w = 1 - 2*wx^2 + wx^3;

elseif wx>=1 && wx<2

w = 4 - 8*wx + 5*wx^2 - wx^3;

else

w = 0;

end

end
``````

：为便于比较，以上所有图片均放置统一大小。