双线性插值法之放大收缩图像及其python实现

一维线性插值

假设我们已知坐标(x0,y0)与(x1,y1),要得到[x0,x1]区间内某一位置x在直线上的值。根据图中所示可得:
在这里插入图片描述
通过斜率比,可以得到下面的等式。
在这里插入图片描述
在这里插入图片描述

双线性插值

在这里插入图片描述
如图所示:所谓双线性插值,也就是连续使用三次一维线性插值,最终求得g(u0,v0)。
第一次:由g(u’,v’)和g(u’+1,v’)一维线性插值求g(u0,v’).
第二次:由g(u’,v’+1)和g(u’+1,v’+1)一维线性插值求g(u0,v’+1).
第三次:由g(u0,v’)和g(u0,v’+1)一维线性插值求g(u0,v0).
在这里插入图片描述

如何用双线性插值放大或收缩图像

我们只需要做两件事:

  • 计算新图像像素在原图像的对应位置
  • 通过位置,在原图像找到4个点来计算新图像对应位置的像素

f(x,y)表示输出图像,g(u,v)表示输入图像。图像放大或缩小的几何运算可定义为: f ( x , y ) = g ( u 0 , v 0 ) = g [ a ( x , y ) , b ( x , y ) ] f(x,y)=g(u_0,v_0)=g[a(x,y),b(x,y)] f(x,y)=g(u0,v0)=g[a(x,y),b(x,y)].如果令 u 0 = a ( x , y ) = x c , v 0 = b ( x , y ) = y d u_0=a(x,y)=\frac{x}{c},v_0=b(x,y)=\frac{y}{d} u0=a(x,y)=cx,v0=b(x,y)=dy.我们知道 u 0 , v 0 u_0,v_0 u0,v0的坐标其实就是原图x轴方向放大c倍,y轴方向放大d被。

举个例子,将一副200×200的图像 g ( u , v ) g(u,v) g(u,v)放大1.5倍,那么将得到300×300的新图像 f ( x , y ) f(x,y) f(x,y)。产生新图像的过程,实际就是为300×300的像素赋值的过程。
假如为 f ( 150 , 150 ) f(150,150) f(150,150)赋值:
f ( 150 , 150 ) = g ( 150 / 1.5 , 150 / 1.5 ) = g ( 100 , 100 ) ; f(150,150)=g(150/1.5,150/1.5)=g(100,100); f(150,150)=g(150/1.5,150/1.5)=g(100,100);
假如为f(100,100)赋值:
f ( 100 , 100 ) = g ( 100 / 1.5 , 100 / 1.5 ) = g ( 66.7 , 66.7 ) . f(100,100)=g(100/1.5,100/1.5)=g(66.7,66.7). f(100,100)=g(100/1.5,100/1.5)=g(66.7,66.7).

对于 g ( 100 , 100 ) g(100,100) g(100,100),坐标值为整数,可直接赋值。而对于 g ( 66.7 , 66.7 ) g(66.7,66.7) g(66.7,66.7),坐标值为小数,也即 ( u 0 , v 0 ) (u_0,v_0) u0v0不一定在坐标点上,这种情况就需要用到前言中所提到的双线性插值。 f ( 100 , 100 ) = g ( 66.7 , 66.7 ) = ( 0.3 ∗ 0.3 ) g ( 66 , 66 ) + ( 0.3 ∗ 0.7 ) g ( 66 , 67 ) + ( 0.3 ∗ 0.7 ) g ( 67 , 66 ) + ( 0.7 ∗ 0.7 ) g ( 67 , 67 ) f(100,100)=g(66.7,66.7)=(0.3*0.3)g(66,66)+(0.3*0.7)g(66,67)+(0.3*0.7)g(67,66)+(0.7*0.7)g(67,67) f(100,100)=g(66.7,66.7)=(0.30.3)g(66,66)+(0.30.7)g(66,67)+(0.30.7)g(67,66)+(0.70.7)g(67,67)

python实现

# --*-- encoding: utf-8 --*--
'''
Date: 2018.09.13
Content: python3 实现双线性插值图像缩放算法
'''

import numpy as np
import cv2
import math

def bi_linear(src, dst, target_size):
    pic = cv2.imread(src)       # 读取输入图像
    th, tw = target_size[0], target_size[1]
    emptyImage = np.zeros(target_size, np.uint8)
    for k in range(3):
        for i in range(th):
            for j in range(tw):
                # 首先找到在原图中对应的点的(X, Y)坐标
                corr_x = (i+0.5)/th*pic.shape[0]-0.5
                corr_y = (j+0.5)/tw*pic.shape[1]-0.5
                # if i*pic.shape[0]%th==0 and j*pic.shape[1]%tw==0:     # 对应的点正好是一个像素点,直接拷贝
                #   emptyImage[i, j, k] = pic[int(corr_x), int(corr_y), k]
                point1 = (math.floor(corr_x), math.floor(corr_y))   # 左上角的点
                point2 = (point1[0], point1[1]+1)
                point3 = (point1[0]+1, point1[1])
                point4 = (point1[0]+1, point1[1]+1)

                fr1 = (point2[1]-corr_y)*pic[point1[0], point1[1], k] + (corr_y-point1[1])*pic[point2[0], point2[1], k]
                fr2 = (point2[1]-corr_y)*pic[point3[0], point3[1], k] + (corr_y-point1[1])*pic[point4[0], point4[1], k]
                emptyImage[i, j, k] = (point3[0]-corr_x)*fr1 + (corr_x-point1[0])*fr2

    cv2.imwrite(dst, emptyImage)
    # 用 CV2 resize函数得到的缩放图像
    new_img = cv2.resize(pic, (200, 300))
    cv2.imwrite('pic/1_cv_img.png', new_img)

def main():
    src = 'pic/raw_1.jpg'
    dst = 'pic/new_1.png'
    target_size = (300, 200, 3)     # 变换后的图像大小

    bi_linear(src, dst, target_size)

if __name__ == '__main__':
    main()
  • 17
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值