原始问题
所以我一直在阅读很多关于如何在纯Python中对图像进行透视变换但我无法使其工作。
变换本身非常简单,它只是一个小方程式,但是我在使用从图像中的某些锚点创建系数的函数时遇到了问题。我已经得到了一个可以在基于numpy的优秀答案from another post的帮助下完成而没有错误的工作代码,但我的问题是我试图在纯Python中执行此操作。系数变得非常低,并且在我生成的图像上没有任何东西弹出。
一个问题可能是移植numpy函数,如dotmatrix,multiplication和inverse matrix,我试图在纯Python函数中做。 (当我手动输入每个系数时,我确实获得了透视变换图像,因此我知道渲染部分的系数应该正常工作)。因此,非常感谢任何有关如何计算出如何计算系数可能出错的帮助:)
更新
好的,快速更新,事实证明numpy代码现在突然起作用并产生看起来像透视图像(最初来自我之前链接的帖子),所以这至少是一个好兆头。这是我使用的确切numpy代码,因此是纯Python中要复制的步骤模板。
import numpy
matrix = []
print pa,pb
for p1, p2 in zip(pa, pb):
matrix.append([p1[0], p1[1], 1, 0, 0, 0, -p2[0]*p1[0], -p2[0]*p1[1]])
matrix.append([0, 0, 0, p1[0], p1[1], 1, -p2[1]*p1[0], -p2[1]*p1[1]])
A = numpy.matrix(matrix, dtype=numpy.float)
B = numpy.array(pb).reshape(8)
print "ab",A,B
res = numpy.dot(numpy.linalg.inv(A.T * A) * A.T, B)
print "res",numpy.array(res).reshape(8)
这是纯Python版本,目前尝试重现这些步骤但失败了:
def tilt(self, oldplane, newplane):
"""
perspective transform.
oldplane is a list of four old xy coordinate pairs
that will move to the four points in the newplane
"""
#first find the transform coefficients, thanks to https://stackoverflow.com/questions/14177744/how-does-perspective-transformation-work-in-pil
pb,pa = oldplane,newplane
grid = []
for p1,p2 in zip(pa, pb):
grid.append([p1[0], p1[1], 1, 0, 0, 0, -p2[0]*p1[0], -p2[0]*p1[1]])
grid.append([0, 0, 0, p1[0], p1[1], 1, -p2[1]*p1[0], -p2[1]*p1[1]])
def transpose(listoflists):
return [list(each) for each in zip(*listoflists)]
def flatten(listoflists):
return [xory for xy in listoflists for xory in xy]
def sumproduct(listA,multis):
"aka, dot multiplication"
outgrid = []
for y,(row,multi) in enumerate(zip(listA,multis)):
rowsum = 0
for x,nr in enumerate(row):
rowsum += nr*multi
outgrid.append(rowsum)
return outgrid
def gridmultiply(grid1,grid2):
"aka, matrix*matrix"
outgrid = []
for y in xrange(len(grid1)):
newrow = []
for x in xrange(len(grid2)):
value = grid1[y][x] * grid2[y][x]
newrow.append(value)
outgrid.append(newrow)
return outgrid
def gridinverse(grid):
outgrid = []
pos_deriv = 1
neg_deriv = 1
for y in xrange(len(grid)):
horizline = []
for x in xrange(len(grid[0])):
invx=len(grid[0])-1-x
invy=len(grid)-1-y
nr = grid[y][x]
pos_deriv += pos_deriv*nr
invnr = grid[invy][invx]*-1
horizline.append(invnr)
neg_deriv += neg_deriv*invnr
outgrid.append(horizline)
derivative = 1/float(pos_deriv-neg_deriv)
print "deriv",derivative
outgrid = gridmultiply(outgrid,[[derivative for _ in xrange(len(outgrid[0]))] for _ in xrange(len(outgrid))])
return outgrid
A = grid
B = flatten(pb)
res = sumproduct(gridinverse(gridmultiply(gridmultiply(transpose(A),A),transpose(A))), B)
transcoeff = res
print transcoeff
#then calculate new coords, thanks to http://math.stackexchange.com/questions/413860/is-perspective-transform-affine-if-it-is-why-its-impossible-to-perspective-a"
k = 1
a,b,c,d,e,f,g,h = transcoeff
outimg = Image().new(self.width,self.height)
for y in xrange(len(self.imagegrid)):
for x in xrange(len(self.imagegrid[0])):
color = self.get(x,y)
newx = int(round((a*x+b*y+c)/float(g*x+h*y+k)))
newy = int(round((d*x+e*y+f)/float(g*x+h*y+k)))
try:
outimg.put(newx,newy,color)
#print x,y,newx,newy
except IndexError:
#out of bounds
pass
return outimg