Open
Description
Original Image:
Expected Output Image :
Code
import numpy as np
import pygame
np.set_printoptions(precision=3, suppress=True)
sf=pygame.display.set_mode((640,480))
IMG_SIZE = 512
img=pygame.image.load("tnt_side.png")
img=pygame.transform.scale(img, (IMG_SIZE,IMG_SIZE))
img=pygame.surfarray.pixels3d(img)
quad=np.array([[10,10],[200,140],[240,260],[100,400]])
uv=np.array([[0,0],[1,0],[1,1],[0,1]])*IMG_SIZE
# ref https://blog.csdn.net/REstrat/article/details/126987198
# 此处的src是原坐标数组,dst是目标坐标数组
def WarpPerspectiveMatrix(src, dst):
assert src.shape[0] == dst.shape[0] and src.shape[0] >= 4
nums = src.shape[0]
# 4组对应点,每组2行8列
# 总共8行8列的数组,对应公式(3)中最左边的矩阵
A = np.zeros((2 * nums, 8))
# 4组对应点,每组2行1列
# 总共8行1列,对应公式(3)中最右边的矩阵
B = np.zeros((2 * nums, 1))
# 矩阵赋值,0下标为x值,1下标为y值
for i in range(0, nums):
A_i = src[i,:]
B_i = dst[i,:]
A[2*i, :] = [A_i[0], A_i[1], 1, 0, 0, 0, -A_i[0]*B_i[0], -A_i[1]*B_i[0]]
B[2*i] = B_i[0]
A[2*i+1, :] = [0, 0 , 0, A_i[0], A_i[1], 1, -A_i[0]*B_i[1], -A_i[1]*B_i[1]]
B[2*i+1] = B_i[1]
# 转换为矩阵
A = np.mat(A)
# 求解未知数值,.I表示求逆
warpMatrix = A.I * B
# 矩阵后处理,主要是将a33的1值赋值回去
warpMatrix = np.array(warpMatrix).T[0]
warpMatrix = np.insert(warpMatrix, warpMatrix.shape[0], values=1.0, axis=0)
warpMatrix = warpMatrix.reshape((3, 3))
return warpMatrix
mat=WarpPerspectiveMatrix(quad,uv)
def map_point(point):
o=mat.dot((*point,1))
return round(o[0]/o[2]),round(o[1]/o[2])
arr=pygame.surfarray.pixels3d(sf)
xmin=min(quad[:,0])
xmax=max(quad[:,0])
ymin=min(quad[:,1])
ymax=max(quad[:,1])
for y in range(ymin,ymax+1):
for x in range(xmin,xmax+1):
p=map_point((x,y))
if -1<p[0]<IMG_SIZE and -1<p[1]<IMG_SIZE:
arr[x,y]=img[p]
#pygame.draw.polygon(sf,(255,255,255),quad,width=1)
pygame.display.update()
while 1:
pygame.event.get()
Output Image (using Texture.draw_quads()
):
Code
import pygame
from pygame._sdl2 import video
win = video.Window()
ren = video.Renderer(win)
img=pygame.image.load("tnt_side.png")
tex = video.Texture.from_surface(ren, img)
quad=[[10,10],[200,140],[240,260],[100,400]]
uv=[[0,0],[1,0],[1,1],[0,1]]
tex.draw_quad(*quad,*uv)
ren.present()
while 1:
pygame.event.get()