python实现2D图像插值算法

图像插值算法有很多一般采用的是最邻近插值和双线性插值。

最邻近插值

最邻近插值顾名思义就是取图像最近点的值作为新的插入值,话不多说直接上代码

def nearest_interpolation(src_img, tar_size):
    H = src_img.shape[0]   #原始图像的高
    W = src_img.shape[1]   #原始图像的宽
    channel= src_img.shape[2]

    tar_H = H * tar_size[0]  #插值后的高
    tar_W = W * tar_size[1]  #插值后的宽

    tar_img = np.zeros([tar_H, tar_W, channel], dtype=np.uint8)  #先生成插值后图像的大小,以0填充,注意一定是np.uint8

    for h in range(tar_H - 1):
        for w in range(tar_W - 1):

            src_h = round(h / tar_size[0])       #得到对应原始图像的高和宽并取整
            src_w = round(w/ tar_size[1])

            tar_img[h, w] = src_img[src_h, src_w]  #赋值

    return tar_img

双线性插值

网上有很多介绍双线性插值原理,在这就不阐述了,简单一个原理就是根据周围四个点利用公式f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)计算新的插入值。

def bilinear_interpolation(org_img, tar_size):
    org_h, org_w, channel= org_img.shape   #得到原图图像的长和宽

    dst_img = np.zeros((org_h * tar_size[0], org_w * tar_size[1], channel),dtype = np.uint8)   #生成插值后图像的大小
    dst_h, dst_w , channel= dst_img.shape  #得到插值后图像的长和宽

    scale_h = org_h / dst_h  #计算插值后的倍数
    scale_w = org_w / dst_w

    for i in range(dst_h):
        for j in range(dst_w):

            src_x = i * scale_h  #计算目标像素在原图像中的位置
            src_y = j * scale_w

            src_x_int = int(math.floor(src_x))  #取整
            src_y_int = int(math.floor(src_y))

            u = src_x - src_x_int
            v = src_y - src_y_int

            #判断是否超出边界
            if src_x_int + 1 == org_h or src_y_int + 1 == org_w:
                dst_img[i, j, :] = org_img[src_x_int, src_y_int, :]
                continue

            #根据公式求插值后的图像
            dst_img[i, j, :] =(1-u)*(1-v)*org_img[src_x_int,src_y_int, :] + \
                           (1-u)*v*org_img[src_x_int,src_y_int+1, :] + \
                           u*(1-v)*org_img[src_x_int+1,src_y_int, :] +\
                           u*v*org_img[src_x_int+1,src_y_int+1, :]
    return dst_img

全部代码如下:

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

#最近邻插值就是简单的选择x和y的整数部分的坐标像素点赋值给新图像
def nearest_interpolation(src_img, tar_size):
    H = src_img.shape[0]   #原始图像的高
    W = src_img.shape[1]   #原始图像的宽
    channel= src_img.shape[2]

    tar_H = H * tar_size[0]  #插值后的高
    tar_W = W * tar_size[1]  #插值后的宽

    tar_img = np.zeros([tar_H, tar_W, channel], dtype=np.uint8)  #先生成插值后图像的大小,以0填充,注意一定是np.uint8

    for h in range(tar_H - 1):
        for w in range(tar_W - 1):

            src_h = round(h / tar_size[0])       #得到对应原始图像的高和宽并取整
            src_w = round(w/ tar_size[1])

            tar_img[h, w] = src_img[src_h, src_w]  #赋值

    return tar_img


##双线性插值,根据公式f(i+u,j+v) = (1-u)(1-v)f(i,j) + (1-u)vf(i,j+1) + u(1-v)f(i+1,j) + uvf(i+1,j+1)计算即可
def bilinear_interpolation(org_img, dst_shape):
    org_h, org_w, channel= org_img.shape   #得到原图图像的长和宽

    dst_img = np.zeros((org_h * dst_shape[0], org_w *dst_shape[1], channel),dtype = np.uint8)   #生成插值后图像的大小
    dst_h, dst_w , channel= dst_img.shape  #得到插值后图像的长和宽

    scale_h = org_h / dst_h  #计算插值后的倍数
    scale_w = org_w / dst_w

    for i in range(dst_h):
        for j in range(dst_w):

            src_x = i * scale_h  #计算目标像素在原图像中的位置
            src_y = j * scale_w

            src_x_int = int(math.floor(src_x))  #取整
            src_y_int = int(math.floor(src_y))

            u = src_x - src_x_int
            v = src_y - src_y_int

            #判断是否查出边界
            if src_x_int + 1 == org_h or src_y_int + 1 == org_w:
                dst_img[i, j, :] = org_img[src_x_int, src_y_int, :]
                continue

            #根据公式求插值后的图像
            dst_img[i, j, :] =(1-u)*(1-v)*org_img[src_x_int,src_y_int, :] + \
                           (1-u)*v*org_img[src_x_int,src_y_int+1, :] + \
                           u*(1-v)*org_img[src_x_int+1,src_y_int, :] +\
                           u*v*org_img[src_x_int+1,src_y_int+1, :]
    return dst_img

image = Image.open('img.jpg')  #读取图像

imgData = np.array(image)   #将图像转化为数组

tar_size = (2, 3)           #插值后图像的大小
# tar_img = nearest_interpolation(imgData, tar_size)  ##邻近插值插值
tar_img = bilinear_interpolation(imgData, tar_size)   ##双线性插值

plt.figure("Image")
plt.imshow(image)
plt.axis('on')
plt.title('image')
plt.show()

plt.figure('tar_img')
plt.imshow(tar_img)
plt.axis('on')
plt.title('tar_img')
plt.show()


后续将会跟新3d图像的插值算法

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

花生米生花@

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值