def perspective_mapping(arrF, arrH, u_ul, u_ur, u_ll, u_lr, debug=False):
M, N = arrH.shape
u, v = np.meshgrid(np.arange(N), np.arange(M))
matX = np.stack((u, v)).astype(float)
u1, v1 = u_ul
u2, v2 = u_ur
u3, v3 = u_ll
u4, v4 = u_lr
x1, y1 = 0, 0
x2, y2 = arrF.shape[1], 0
x3, y3 = 0, arrF.shape[0]
x4, y4 = arrF.shape[1], arrF.shape[0]
A = [[u1, v1, 1, 0, 0, 0, -u1*x1, -v1*x1],
[u2, v2, 1, 0, 0, 0, -u2*x2, -v2*x2],
[u3, v3, 1, 0, 0, 0, -u3*x3, -v3*x3],
[u4, v4, 1, 0, 0, 0, -u4*x4, -v4*x4],
[0, 0, 0, u1, v1, 1, -u1*y1, -v1*y1],
[0, 0, 0, u2, v2, 1, -u2*y2, -v2*y2],
[0, 0, 0, u3, v3, 1, -u3*y3, -v3*y3],
[0, 0, 0, u4, v4, 1, -u4*y4, -v4*y4]]
A = np.array(A)
b = np.array([x1, x2, x3, x4, y1, y2, y3, y4]).T
X, _, _, _ = np.linalg.lstsq(A, b, rcond=None)
a,b,c,d,e,f,g,h = X
X_ = (a*matX[0] + b*matX[1] + c) / (g*matX[0] + h*matX[1] + 1)
Y_ = (d*matX[0] + e*matX[1] + f) / (g*matX[0] + h*matX[1] + 1)
matX = np.stack((Y_, X_))
arrG = img.map_coordinates(arrF, matX, cval=-1) # matX MUST be float
arrG = arrG.reshape(matX.shape[1],matX.shape[2])
mask = arrG != -1
#mask = np.bitwise_and(arrG != -1, arrG<230)
if debug:
plt.imshow(arrG, cmap="gray"); plt.title("Transformed Image"); plt.show()
plt.imshow(mask, cmap="gray"); plt.title("Mask")
newArr = arrH.copy()
newArr[mask] = arrG[mask]
return newArr
def perspective_mapping_transparent(arrF, arrH, u_ul, u_ur, u_ll, u_lr, debug=False):
M, N = arrH.shape
u, v = np.meshgrid(np.arange(N), np.arange(M))
matX = np.stack((u, v)).astype(float)
u1, v1 = u_ul
u2, v2 = u_ur
u3, v3 = u_ll
u4, v4 = u_lr
x1, y1 = 0, 0
x2, y2 = arrF.shape[1], 0
x3, y3 = 0, arrF.shape[0]
x4, y4 = arrF.shape[1], arrF.shape[0]
A = [[u1, v1, 1, 0, 0, 0, -u1*x1, -v1*x1],
[u2, v2, 1, 0, 0, 0, -u2*x2, -v2*x2],
[u3, v3, 1, 0, 0, 0, -u3*x3, -v3*x3],
[u4, v4, 1, 0, 0, 0, -u4*x4, -v4*x4],
[0, 0, 0, u1, v1, 1, -u1*y1, -v1*y1],
[0, 0, 0, u2, v2, 1, -u2*y2, -v2*y2],
[0, 0, 0, u3, v3, 1, -u3*y3, -v3*y3],
[0, 0, 0, u4, v4, 1, -u4*y4, -v4*y4]]
A = np.array(A)
b = np.array([x1, x2, x3, x4, y1, y2, y3, y4]).T
X, _, _, _ = np.linalg.lstsq(A, b, rcond=None)
a,b,c,d,e,f,g,h = X
X_ = (a*matX[0] + b*matX[1] + c) / (g*matX[0] + h*matX[1] + 1)
Y_ = (d*matX[0] + e*matX[1] + f) / (g*matX[0] + h*matX[1] + 1)
matX = np.stack((Y_, X_))
arrG = img.map_coordinates(arrF, matX, cval=-1) # matX MUST be float
arrG = arrG.reshape(matX.shape[1],matX.shape[2])
#mask = arrG != -1
mask = np.bitwise_and(arrG != -1, arrG<230)
if debug:
plt.imshow(arrG, cmap="gray"); plt.title("Transformed Image"); plt.show()
plt.imshow(mask, cmap="gray"); plt.title("Mask")
newArr = arrH.copy()
newArr[mask] = arrG[mask]
return newArr
arrF_ = imageRead('Data/asterix.png')
arrH_ = imageRead('Data/isle.jpg')
out = perspective_mapping_transparent(arrF_, arrH_, (215, 56), (365, 10), (218, 258), (364, 296))
out2 = perspective_mapping(arrF_, arrH_, (215, 56), (365, 10), (218, 258), (364, 296))
fig, axs = plt.subplots(1, 2, figsize=(10,10))
axs[0].imshow(out / 255, cmap="gray")
axs[1].imshow(out2 / 255, cmap="gray")
plt.show()