数字图像处理学习笔记(七)——用Pycharm及MATLAB实现三种图像内插法(最近邻内插法、双线性内插法、双三次内插法)

数字图像处理(Digital Image Processing)是通过计算机对图像进行去除噪声、增强、复原、分割、提取特征等处理的方法和技术。本专栏将以学习笔记形式对数字图像处理的重点基础知识进行总结整理,欢迎大家一起学习交流!
专栏链接:数字图像学习笔记

★由于之前学习笔记(四)有对于图像三种插值的理论讲解,这里就不再赘余;
可参照此文阅读学习图像的三种内插法

一、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
    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。

二、MATLAB实现过程

①最近邻插值

代码部分

% 最近邻插值

% 输入图像文件及放大率

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

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

运行结果截图

在这里插入图片描述

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

欢迎留言,一起学习交流~~~

感谢阅读

END

发布了24 篇原创文章 · 获赞 178 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/IT_charge/article/details/105522317