#!/usr/bin/env python # # Ported from Johnny Lee's C# WiiWhiteboard project (Warper.cs file) # by Stephane Duchesneau # # # Create Perspective() object, # call setsrc() with the 4 corners of the quad as tuples, # call setdst() with the 4 corners of the rectangle as tuples, # # use warp(srcx,srcy) to get dstx and dsty # # class Perspective(): """Used to map pixels in a non-rectangular quad to a rectangular one""" srcmatrix = [0.0,0.0, 1.0,0.0, 0.0,1.0, 1.0,1.0] dstmatrix = [0.0,0.0, 1.0,0.0, 0.0,1.0, 1.0,1.0] dstdots = [(0.0,0.0),(1.0,0.0),(0.0,1.0),(1.0,1.0)] srcdots = [(0.0,0.0),(1.0,0.0),(0.0,1.0),(1.0,1.0)] def __init__(self): self.computeWarpMatrix() def setsrc(self,dot1,dot2,dot3,dot4): self.srcdots = [(float(dot[0]),float(dot[1])) for dot in [dot1,dot2,dot3,dot4]] self.computeWarpMatrix() def setdst(self,dot1,dot2,dot3,dot4): self.dstdots = [dot1,dot2,dot3,dot4] self.computeWarpMatrix() def computeWarpMatrix(self): self.srcmatrix = self.computeQuadToSquare(self.srcdots) self.dstmatrix = self.computeSquareToQuad(self.dstdots) self.warpmatrix = self.multMats(self.srcmatrix,self.dstmatrix) def computeSquareToQuad(self,inputdots): x0,y0 = inputdots[0] x1,y1 = inputdots[1] x2,y2 = inputdots[2] x3,y3 = inputdots[3] dx1 = x1 - x2 dy1 = y1 - y2 dx2 = x3 - x2 dy2 = y3 - y2 sx = x0 - x1 + x2 - x3 sy = y0 - y1 + y2 - y3 g = (sx * dy2 - dx2 * sy) / (dx1 * dy2 - dx2 * dy1) h = (dx1 * sy - sx * dy1) / (dx1 * dy2 - dx2 * dy1) a = x1 - x0 + g * x1 b = x3 - x0 + h * x3 c = x0 d = y1 - y0 + g * y1 e = y3 - y0 + h * y3 f = y0 mat = [0.0]*16 mat[ 0] = a mat[ 1] = d mat[ 2] = 0 mat[ 3] = g mat[ 4] = b mat[ 5] = e mat[ 6] = 0 mat[ 7] = h mat[ 8] = 0 mat[ 9] = 0 mat[10] = 1 mat[11] = 0 mat[12] = c mat[13] = f mat[14] = 0 mat[15] = 1 return mat def computeQuadToSquare(self,inputdots): x0,y0 = inputdots[0] x1,y1 = inputdots[1] x2,y2 = inputdots[2] x3,y3 = inputdots[3] mat = self.computeSquareToQuad(inputdots) a = mat[ 0] d = mat[ 1] g = mat[ 3] b = mat[ 4] e = mat[ 5] h = mat[ 7] c = mat[12] f = mat[13] A = e - f * h B = c * h - b C = b * f - c * e D = f * g - d E = a - c * g F = c * d - a * f G = d * h - e * g H = b * g - a * h I = a * e - b * d idet = 1.0 / (a * A + b * D + c * G) mat[ 0] = A * idet mat[ 1] = D * idet mat[ 2] = 0 mat[ 3] = G * idet mat[ 4] = B * idet mat[ 5] = E * idet mat[ 6] = 0 mat[ 7] = H * idet mat[ 8] = 0 mat[ 9] = 0 mat[10] = 1 mat[11] = 0 mat[12] = C * idet mat[13] = F * idet mat[14] = 0 mat[15] = I * idet return mat def multMats(self,srcMat,dstMat): resMat = [0]*16 for r in range(0,4): ri = r * 4 for c in range(0,4): resMat[ri + c] = (srcMat[ri ] * dstMat[c ] + srcMat[ri + 1] * dstMat[c + 4] + srcMat[ri + 2] * dstMat[c + 8] + srcMat[ri + 3] * dstMat[c + 12]) return resMat def warp(self, srcX, srcY): result = [0.0]*4 mat = self.warpmatrix z=0.0 result[0] = (srcX * mat[0] + srcY*mat[4] + z*mat[8] + 1*mat[12]) result[1] = (srcX * mat[1] + srcY*mat[5] + z*mat[9] + 1*mat[13]) result[2] = (srcX * mat[2] + srcY*mat[6] + z*mat[10] + 1*mat[14]) result[3] = (srcX * mat[3] + srcY*mat[7] + z*mat[11] + 1*mat[15]) dstX = result[0]/result[3] dstY = result[1]/result[3] return dstX,dstY