想来周末无事,还是把双线性插值做一做吧。
上一篇:变换与插值里的最邻近插值法理解的有问题,虽然写的时候就感觉有些不对劲,但当时急于实现就没想那么多。今天才突然想明白了插值的意义,之后上网一查,果真如此。如此看来,今天也算是有收获喽!
理解的差距在于:上一篇的实现中,我认为插值就是在两个像素点之间插入更多的点,以使图像更平滑之类的。但事实上,插值不一定会使图像的像素点更多。插值的方法让我可以知道任何我想知道的位置的像素值(通过公式计算),通过这种方法,我可以得到由任何像素点得到的图像。
下面,来试试吧!
import numpy as np
import matplotlib.image as imgplt
import matplotlib.pyplot as plt
import math
data = imgplt.imread('graph_320,500,3.jpg')
length = data.shape[1]
wide = data.shape[0]
high = data.shape[-1]
def bil_int(data, length, wide, high, length_new, wide_new):
data_new = np.zeros((wide_new, length_new, high),dtype='int32')
for i in range(wide_new):
for j in range(length_new):
x_dis = j*(length-1)/(length_new-1)
y_dis = i*(wide-1)/(wide_new-1)
x = x_dis - math.floor(x_dis)
y = y_dis - math.floor(y_dis)
y0 = int(math.floor(x_dis))
y1 = int(math.ceil(x_dis))
x0 = int(math.floor(y_dis))
x1 = int(math.ceil(y_dis))
#if 0<x0<length and 0<x1<length and 0<y0<wide and 0<y1<wide:
data_new[i][j] = (data[x1][y0]-data[x0][y0])*x + \
(data[x0][y1]-data[x0][y0])*y + \
(data[x1][y1]+data[x0][y0]-data[x0][y1]-data[x1][y0])*x*y\
+data[x0][y0]
return data_new
data_new = bil_int(data,length,wide,high,2*length,wide)
plt.imshow(data_new)
plt.show()
这次作业收获还是不小滴,搞明白了几个上一篇文章没弄懂的问题。
写代码的过程中主要是这几个点出现了问题:
1.类似于C的溢出问题,data的索引一直出界。原因在于line15、16行新图像对应点的坐标没有计算准确。
2.行列与x、y的对应问题,x是对应列,y是对应行滴。
3.对于一个数组,不能直接在前面加int()让它的各个元素变成整数,否则会报如下错误:only size-1 arrays can be converted to Python scalars.报错不可怕,可怕的是导致这个错因的错误会五花八门(本人亲身试验,网上很多这样的错误,但解决方案五花八门。。。)
4.最后,第一个出来的图居然是一边白,一边黑的。吐血。想到上一篇博客碰到同样的状况,归一化试试,bingo!此时,也解决了昨天碰到的一个问题:如果数组里的元素是浮点类型,则它默认所要转化的图片是经过归一化的,大于1的全变成1,所以就出现一片白的情况。这可以通过在创建数组时就指定数组元素的类型来规避此种情况。若初始算的数组元素带有小数,会自动取整滴!
欢迎指出错误,
一起学习,共同进步!