背景:我正在尝试将一个不同形状的面孔变形成另一个面孔。
为了将一幅图像变形成另一幅图像,我使用了面部标记的德劳内三角剖分,并将一个肖像的三角形变形为第二个肖像的相应三角形。我使用重心坐标系将三角形内的点映射到其在另一个三角形上对应的变形位置。
我的第一种方法是使用逆乘法解决系统Ax = b,其中A由三角形的三个角组成,b表示当前点,x表示该点的重心坐标(alpha、beta和gamma)。我每个三角形只找到一次矩阵A的逆矩阵,然后对于该三角形内的每个点,通过找到A^-1和点b的点积来计算重心坐标。我发现这非常慢(函数需要36秒才能完成)。
根据其他帖子的建议,我尝试使用最小二乘解来提高此过程的效率。然而,当我使用numpy的lsq方法时,时间增加到了154秒。我认为这是因为每次内部循环运行时都要对A矩阵进行因式分解,而之前我能够在两个循环开始之前仅找到一次逆矩阵。
我的问题是,如何提高这个函数的效率?有没有一种方法可以存储A的分解,以便每次为新点计算最小二乘解时,不会重复相同的工作?
该函数的伪代码:
# Iterate through each triangle (and get corresponding warp triangle)
for triangle in triangulation:
# Extract corners of the unwarped triangle
a = firstCornerUW
b = secondCornerUW
c = thirdCornerUW
# Extract corners of the warp triangle
a_prime = firstCornerW
b_prime = secondCornerW
c_prime = thirdCornerW
# This matrix will be the same for all points within the triangle
triMatrix = matrix of a, b, and c
# Bounding box of the triangle
xleft = min(ax, bx, cx)
xright = max(ax, bx, cx)
ytop = min(ay, by, cy)
ybottom = max(ay, by, cy)
for x in range(xleft, xright):
for y in range(ytop, ybottom):
# Store the current point as a matrix
p = np.array([[x], [y], [1]])
# Solve for least squares solution to get barycentric coordinates
barycoor = np.linalg.lstsq(triMatrix, p)
# Pull individual coordinates from the array
alpha = barycoor[0]
beta = barycoor[1]
gamma = barycoor[2]
# If any of these conditions are not met, the point is not inside the triangle
if alpha, beta, gamma > 0 and alpha + beta + gamma <= 1:
# Now calculate the warped point by multiplying by alpha, beta, and gamma
# Warp the point from image to warped image