实现了平移、旋转、缩放,其中缩放和旋转时采用双线性映射。
废话不多说,直接上代码
import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
from math import *
def bilinear_interpolation(img,x,y):
# 图像像素点的双线性插值,用周围最近的四个像素进行插值
try:
l_x,l_y = floor(x),floor(y)
h_x,h_y = ceil(x),ceil(y)
x_rate,_ = modf(x)
y_rate,_ = modf(y)
p1 = (1-x_rate)*img[l_x,l_y]+x_rate*img[h_x,l_y]
p2 = (1-x_rate)*img[l_x,h_y]+x_rate*img[h_x,h_y]
p = (1-y_rate)*p1+y_rate*p2
return p
except:
return img[int(x),int(y)]
def translate(img,dx,dy):
dx,dy = int(dx),int(dy)
h,w = img.shape
new_h,new_w = h+abs(int(dx)),w+abs(int(dy))
r_img = np.zeros(shape=(new_h,new_w))
xs = 0 if dx<0 else dx
ys = 0 if dy<0 else dy
r_img[xs:xs+h,ys:ys+w] = img
return r_img
def rotate(img, angle):
# 后向映射+双线性插值
angle = angle/180*pi
r_mat = np.array([
[cos(angle),-sin(angle)],
[sin(angle),cos(angle)]
])
rt_mat = np.array([
[cos(angle),sin(angle)],
[-sin(angle),cos(angle)]
])
h,w = img.shape
max_min = np.array([
np.array([0,0]),
np.matmul(r_mat,np.array([0,w])),
np.matmul(r_mat,np.array([h,w])),
np.matmul(r_mat,np.array([h,0]))
])
x_l = int(max_min[:,0].min())
x_h = ceil(max_min[:,0].max())
y_l = int(max_min[:,1].min())
y_h = ceil(max_min[:,1].max())
r_img = np.zeros(shape=(x_h-x_l,y_h-y_l))
for i in range(x_h-x_l):
for j in range(y_h-y_l):
coord = np.array([i+x_l,j+y_l])
coord = np.matmul(rt_mat,coord)
x,y = coord[0],coord[1]
if 0<x<=h-1 and 0<y<=w-1:
# 能映射回才算
r_img[i,j] = bilinear_interpolation(img,x,y)
return r_img
def scale(img,rate):
# 缩放
h,w = img.shape
new_h,new_w = int(rate*h),int(rate*w)
r_img = np.zeros(shape=(new_h,new_w))
for i in range(new_h):
for j in range(new_w):
r_img[i][j] = bilinear_interpolation(img,i/rate,j/rate)
return r_img
img = Image.open('lena_512.tif')
img = img.convert('L')
img = np.array(img)
img = img/255.0
r_img = rotate_1(img,30)
plt.imsave('rotate_30.jpg',r_img,cmap='gray')
r_img = scale(img,1.5)
plt.imsave('scale_1.5.jpg',r_img,cmap='gray')
r_img = translate(img, 20,20)
plt.imsave('translate_20_20.jpg',r_img,cmap='gray')