数字图像处理(Digital Image Processing)是通过计算机对图像进行去除噪声、增强、复原、分割、提取特征等处理的方法和技术。本专栏将以学习笔记形式对数字图像处理的重点基础知识进行总结整理,欢迎大家一起学习交流! 专栏链接:数字图像学习笔记
★由于之前学习笔记(四)有对于图像三种插值的理论讲解,这里就不再赘余;
可参照此文阅读学习☞图像的三种内插法
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
img=np.pad(img,((0,1),(0,1),(0,0)),'constant')
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
#img=np.pad(img,((1,3),(1,3),(0,0)),'constant')
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')
运行结果截图
原图earth.jpg
最近邻插值 NNEarth.jpg
双线性内插法 BiLinearEarth.jpg
双三次内插法 BiCubicEarth.jpg
三种方法的细节表现图
由此可见,插值效果从左到右依次增强
但随之而来的是计算量的增加(也就是说越来越耗时)
注:3是原图,4是最近邻插值,2是双线性内插法,1是双三次内插法;
实现时间分别是4min、5min、12min。
①最近邻插值
代码部分
% 最近邻插值
% 输入图像文件及放大率
% 输出根据放大率变化后的新图像
function nearest_neighbor = nearest_neighbor(filename,R)
% 初始化,读入图像,图像数据为m*n*color
img = imread('E:\earth.GIF');
% 变化后图像
[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
img = imread('H:\earth.JPG');
% 变化后图像
[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
% read original image I
I = imread('G:\earth.GIF');
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
运行结果截图
注:为便于比较,以上所有图片均放置统一大小。
感谢阅读