Skip to content

Texture.draw_quads() breaks the perspective #2422

Open
@yunline

Description

@yunline

Original Image:

tnt_side

Expected Output Image :

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()):

image

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()

Metadata

Metadata

Assignees

No one assigned

    Labels

    _sdl2pygame._sdl2bugNot working as intended

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions