python中提高重心坐标计算的效率
背景:我试图将一张脸歪曲到另一个不同的形状。
为了将一幅图像转换为另一幅图像,我使用了面部标志的delaunay三角剖分,并将一幅肖像的三角形翘曲为第二幅肖像的相应三角形。 我使用重心坐标系将三角形内的一个点映射到另一个三角形上相应的变形位置。
我的第一种方法是用逆乘法方法求解系统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
这是我的建议,用你的伪代码表示。 请注意,向三角形上的向量化循环也不应该太难。
# 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
# 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)
barytransform = np.linalg.inv([[ax,bx,cx], [ay,by,cy], [1,1,1]])
grid = np.mgrid[xleft:xright, ytop:ybottom].reshape(2,-1)
grid = np.vstack((grid, np.ones((1, grid.shape[1]))))
barycoords = np.dot(barytransform, grid)
barycoords = barycoords[:,np.all(barycoords>=0, axis=0)]
链接地址: http://www.djcxy.com/p/27473.html
上一篇: Increasing efficiency of barycentric coordinate calculation in python