我的透视变换系数函数(Python)出了什么问题?

时间:2014-04-02 13:20:38

标签: python numpy matrix-inverse perspectivecamera

原始问题

所以我一直在阅读很多关于如何在纯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

0 个答案:

没有答案