Конечно, в коде могут быть некоторые ошибки, потому что выходные изображения выглядят не так, как должны (а могут и не быть).Но вы никогда не получите именно то, что вы хотите, используя перспективные преобразования из-за их математической природы.А именно потому, что они нелинейные.Вы можете сделать так, чтобы углы прямоугольника совпадали, но между углами изображение масштабируется неравномерно, и вы не можете сделать эти неоднородности одинаковыми по обе стороны от разделительной линии.
Но выможет использовать аффинные преобразования, которые масштабируют изображение равномерно.И это гарантирует, что если две точки на линии совпадают, все остальные точки также совпадают.Единственная проблема здесь в том, что аффинное преобразование определяется с помощью треугольника, поэтому вам нужно будет разделить ваши четырехугольники на треугольники.Например, в следующем коде каждый четырехугольник разбит на 4 треугольника с использованием центра четырехугольника в качестве дополнительной вершины.
import numpy as np
import matplotlib.pyplot as plt
import cv2
# generate a test image
im = np.full((400,600), 255, 'u1')
h, w = im.shape
for i in range(1, w//20):
im = cv2.line(im, (i*20, 0), (i*20, h), i*8)
for i in range(1, h//20):
im = cv2.line(im, (0, i*20), (w, i*20), i*10)
plt.figure(figsize=(w/30, h/30))
plt.imshow(im, 'gray')
plt.show()
# Number of grid cells
nx, ny = 3, 2
p0 = np.meshgrid(np.linspace(0, w-1, nx+1, dtype='f'), np.linspace(0, h-1, ny+1, dtype='f'))
print(np.vstack(p0))
p1 = [v.copy() for v in p0]
# Move the central points
p1[0][1,1] -= 30; p1[1][1,1] -= 40
p1[0][1,2] += 20; p1[1][1,2] += 10
print(np.vstack(p1))
# Set perspective = True to see what happens if we use perspective transform
perspective = False
im1 = np.zeros_like(im)
for i in range(nx):
for j in range(ny):
x0, y0 = p0[0][j,i], p0[1][j,i]
c0 = np.stack((p0[0][j:(j+2),i:(i+2)].ravel() - x0, p0[1][j:(j+2),i:(i+2)].ravel() - y0))
c1 = np.stack((p1[0][j:(j+2),i:(i+2)].ravel(), p1[1][j:(j+2),i:(i+2)].ravel()))
if perspective:
ic0 = np.round(c0).astype('i')
ic1 = np.round(c1).astype('i')
M = cv2.getPerspectiveTransform(c0.T, c1.T)
imw = cv2.warpPerspective(im[ic0[1,0]:ic0[1,3], ic0[0,0]:ic0[0,3]], M, (w, h))
im1 |= cv2.fillConvexPoly(np.zeros_like(im), ic1[:,[0,1,3,2]].T, 255) & imw
else:
c0 = np.append(c0, np.mean(c0, axis=1, keepdims=True), 1)
c1 = np.append(c1, np.mean(c1, axis=1, keepdims=True), 1)
ic0 = np.round(c0).astype('i')
ic1 = np.round(c1).astype('i')
for ind in ([0,1,4], [1,3,4], [3,2,4], [2,0,4]):
M = cv2.getAffineTransform(c0[:,ind].T, c1[:,ind].T)
imw = cv2.warpAffine(im[ic0[1,0]:ic0[1,3], ic0[0,0]:ic0[0,3]], M, (w, h))
im1 |= cv2.fillConvexPoly(np.zeros_like(im), ic1[:,ind].T, 255) & imw
plt.figure(figsize=(w/30, h/30))
plt.imshow(im1, 'gray')
plt.show()