AI学习第二周之python图像插值放大与缩小
新手上路,刚开始开始学这个难免会出错,希望大佬们谅解。写博客的本意是记录自己的学习过程,如果能给诸位带来一些小小的帮助,那实在是再好不过了
本周的任务是进行图片的放大和缩小,放大使用的一些插值方法之前在数学建模中有些了解,缩小就是等距取样或者均值法,总的来说这一周的任务难度不大。
图像放大
放大图像就是在原图像取不到的点上进行插值,得到完整的放大图像,在这我使用了三种方法,分别是临近点插值,双线性插值和双立方插值。
临近点插值
临近点插值说白了就是离哪个近取哪个点的值,在新的大图中就是不同的台阶,运行相当迅速,但后果就是图形会有锯齿状痕迹。
from scipy import signal,misc
import matplotlib.pyplot as plt
from scipy import interpolate
import pylab as pl
import numpy as np
import cv2
img0 =cv2.imread('wife.jpg',0)
img1=cv2.imread('lena.jpg',1)
#img1=np.ones([10,10,1])
[h, w, c] = img1.shape
times = 2 # 放大倍数
#临近插值
def cha1():
img_new=np.zeros([times*h,times*w,c],np.float32)
for i in range(c):
for j in range(h):
for k in range(w):
img_new[int(times*j-times/2):int(times*j+times/2),int(times*k-times/2):int(times*k+times/2),i]=img1[j,k,i]
最后的结果如下图:
双线性插值
双线性插值可以这么理解,取未知点附近最近的四个点,对这四个点进行线性插值(就是连直线)。实现起来还可以,本来以为python自带有矩阵插值的函数,结果没有,自己写一个得了。
#双线性插值
def new_square(a,b,c,d,s):
#进行矩阵的线性插值,s为矩阵规格,abcd是离他最近的四个角的点
ans=np.zeros([s,s],np.float32)
temp1=np.linspace(a,c,s)#第一列的头元素
temp2=np.linspace(b,d,s)#最后一列的元素
for i in range(s):
ans[i,:]=np.linspace(temp1[i],temp2[i],s)
return(ans)
def cha2():
img_new = np.zeros([times * h, times * w, c], np.float32)
for i in range(c):
for j in range(h - 1):
for k in range(w - 1):
img_new[int(times * j):int(times * j + times), int(times * k):int(times * k + times), i] = new_square(img1[j, k, i], img1[j, k + 1, i], img1[j + 1, k, i], img1[j + 1, k + 1, i], times)
return (img_new)
运行起来速度还说的过去,效果也比第一个好一点。
双立方插值
双立方插值回会用到临近的十六个点,进行三次插值得到该点的值。
就类似于这样的,每一个点的值,都与他临近的十六个点有关。代码实现起来没有必要每一个点都去取上16点,在算半天。其实分析后可以发现每十六个点中间的方块里面用的是同样的十六个点,所以,每去一次16点,可以返回中间(放大倍数×放大倍数)大小的矩阵,这样可以加快不少速度。
#双立方插值
def three_bar(a1,a2,a3,a4,b1,b2,b3,b4,c1,c2,c3,c4,d1,d2,d3,d4,s):
#先4次插值
x0=np.array([-1*s,0,s,2*s])
y0=np.array([-2*s,-s,0,s])
xx0=[y0,y0,y0,y0]
x1=np.linspace(-s*2,s,3*s)
x2=np.linspace(-s,2*s,s*3)
y0=[]
y0.append([d1,c1,b1,a1])
y0.append([d2,c2,b2,a2])
y0.append([d3,c3,b3,a3])
y0.append([d4,c4,b4,a4])
t=[]
y=np.zeros([4,3*s],np.float32)
fin=np.zeros([s,3*s],np.float32)
fin_t=[]
for i in range(4):
t=interpolate.splrep(xx0[i],y0[i])
y[i]=interpolate.splev(x1,t)
#再进行全方位插值(语无伦次了)
for i in range(s):
fin_t.append(interpolate.splrep(x0,[y[0][2*s-i],y[1][2*s-i],y[2][2*s-i],y[3][2*s-i]]))
fin[i]=interpolate.splev(x2,fin_t[i])
return(fin[:,s:2*s])
def cha3():
for i in range(c):
for j in range(1, h - 2):
for k in range(1, w - 2):
img_new[int(times * j):int(times * j + times), int(times * k):int(times * k + times), i] = three_bar(
img1[j - 1, k - 1, i], img1[j - 1, k, i], img1[j - 1, k + 1, i], img1[j - 1, k + 2, i],
img1[j, k - 1, i], img1[j, k, i], img1[j, k + 1, i], img1[j, k + 2, i], img1[j + 1, k - 1, i],
img1[j + 1, k, i], img1[j + 1, k + 1, i], img1[j + 1, k + 2, i], img1[j + 2, k - 1, i],
img1[j + 2, k, i], img1[j + 2, k + 1, i], img1[j + 2, k + 2, i], times)
return (img_new)
说实话,这个的效果确实好,但是这个的速度真实感人,或者是我电脑不行。
对了,这个还有一个问题就是边缘处理,这个由于时间匆忙这周还没有解决,现在暂时是抹去边缘。
以上是图像放大的几个算法,我这个是放大两倍,可能效果不是很明显,诸位可以调大放大倍数,效果就很明显了。
图像缩小
这个其实很简单,就是等间距取样,直接上代码。
def small():
img_new = np.zeros([int(h / times), int(w / times), c], np.float32)
for i in range(c):
for j in range(int(h / times)):
for k in range(int(w / times)):
img_new[j, k, i] = img1[j * times, k * times, i]
return (img_new)
这个没什么可以说的。
总结
这周科内任务有点多,还有几个其他的ctf比赛,总的学习时间比较少,有一些可以深入研究的点也没有细细研究,只能算是完成任务把,不过挺期待下周的tenserflow的,下周见。