float a = mat[0], d = mat[ 1], /* ignore */ g = mat[ 3]; float b = mat[4], e = mat[ 5], /* 3rd col*/ h = mat[ 7]; /* ignore 3rd row */ float c = mat[12], f = mat[13];
float A = e - f * h; float B = c * h - b; float C = b * f - c * e; float D = f * g - d; float E = a - c * g; float F = c * d - a * f; float G = d * h - e * g; float H = b * g - a * h; float I = a * e - b * d;
// Probably unnecessary since 'I' is also scaled by the determinant, // and 'I' scales the homogeneous coordinate, which, in turn, // scales the X,Y coordinates. // Determinant = a * (e - f * h) + b * (f * g - d) + c * (d * h - e * g); float idet = 1.0f / (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; }void ConverterRegion::computeSquareToQuad(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float *mat) { float dx1 = x1 - x2, dy1 = y1 - y2; float dx2 = x3 - x2, dy2 = y3 - y2; float sx = x0 - x1 + x2 - x3; float sy = y0 - y1 + y2 - y3; float g = (sx * dy2 - dx2 * sy) / (dx1 * dy2 - dx2 * dy1); float h = (dx1 * sy - sx * dy1) / (dx1 * dy2 - dx2 * dy1); float a = x1 - x0 + g * x1; float b = x3 - x0 + h * x3; float c = x0; float d = y1 - y0 + g * y1; float e = y3 - y0 + h * y3; float f = y0;
float dx1 = x1 - x2, dy1 = y1 - y2;
float dx2 = x3 - x2, dy2 = y3 - y2;
float sx = x0 - x1 + x2 - x3;
float sy = y0 - y1 + y2 - y3;
float g = (sx * dy2 - dx2 * sy) / (dx1 * dy2 - dx2 * dy1);
float h = (dx1 * sy - sx * dy1) / (dx1 * dy2 - dx2 * dy1);
float a = x1 - x0 + g * x1;
float b = x3 - x0 + h * x3;
float c = x0;
float d = y1 - y0 + g * y1;
float e = y3 - y0 + h * y3;
float f = y0;
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;
最后得到的mat[16]为一个4X4的矩阵
我想知道这段代码是依据什么原理将四个点转换为矩阵的
变换公式形如:[x y z 1] M = [x' y' z' 1];
M = [m00, m01, m02, m03; m10, m11, m12, m13; m20, m21, m22, m23; m30, m31, m32, m33];
其中的3*3的矩阵[m00, m01, m02; m10, m11, m12; m30, m31, m32];将产生比例、对称、错切、旋转等基本变换;
其中的1*3矩阵[m30, m31, m32]将产生平移变换;
其中的3*1矩阵[m03, m13, m23]T 将产生透视变换;
最后[m33]将产生全比例变换效果。返回来看楼主代码中定义的变换矩阵: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;3*3矩阵为[a, d, 0; b , e, 0; 0, 0, 1];注意到第3行为[0,0,1]、且第3列为[0,0,1],即这个变化描述的是一个2维旋转变换。
1*3矩阵为[c, f, 0],这表示在二维上存在平移变换。
3*1矩阵为[g, h, 0],这表示在二维上存在透视变换。
最后全比例变换参数为1,这说明没有发生全比例变换。从二维上坐标点映射的角度看,将一个四边形映射到另一个四边形,其变换不外乎旋转、平移、透视变换。而从mat矩阵中也正说明了这一点。
即为什么要通过以下这段代码得到mat矩阵
float dx1 = x1 - x2, dy1 = y1 - y2;
float dx2 = x3 - x2, dy2 = y3 - y2;
float sx = x0 - x1 + x2 - x3;
float sy = y0 - y1 + y2 - y3;
float g = (sx * dy2 - dx2 * sy) / (dx1 * dy2 - dx2 * dy1);
float h = (dx1 * sy - sx * dy1) / (dx1 * dy2 - dx2 * dy1);
float a = x1 - x0 + g * x1;
float b = x3 - x0 + h * x3;
float c = x0;
float d = y1 - y0 + g * y1;
float e = y3 - y0 + h * y3;
float f = y0;
void ConverterRegion::setIdentity(float* fpointSrcX,float* fpointSrcY,CPoint* fpointDes)
{
setSource(fpointSrcX[0],fpointSrcY[0],fpointSrcX[1],fpointSrcY[1],
fpointSrcX[2],fpointSrcY[2],fpointSrcX[3],fpointSrcY[3]);
setDestination((float)fpointDes[0].x,(float)fpointDes[0].y,(float)fpointDes[1].x,(float)fpointDes[1].y,
(float)fpointDes[2].x,(float)fpointDes[2].y,(float)fpointDes[3].x,(float)fpointDes[3].y);
computeWarp();
}void ConverterRegion::setSource(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
{
srcX[0] = x0;
srcY[0] = y0;
srcX[1] = x1;
srcY[1] = y1;
srcX[2] = x2;
srcY[2] = y2;
srcX[3] = x3;
srcY[3] = y3;
}void ConverterRegion::setDestination(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3)
{
dstX[0] = x0;
dstY[0] = y0;
dstX[1] = x1;
dstY[1] = y1;
dstX[2] = x2;
dstY[2] = y2;
dstX[3] = x3;
dstY[3] = y3;
}void ConverterRegion::warp(float fSrcX,float fSrcY,CPoint& pointDes)
{
float fDesx = (float) pointDes.x;
float fDesy = (float) pointDes.y; warp(warpMat, fSrcX,fSrcY,fDesx,fDesy); pointDes.x = (int)fDesx;
if ( fabs(pointDes.x - fDesx) >= 0.5 )
pointDes.x++; pointDes.y = (int)fDesy;
if ( fabs(pointDes.y - fDesy) >= 0.5 )
pointDes.y++;
}void ConverterRegion::warp(float fSrcX,float fSrcY,float &fDesx,float &fDesy)
{
warp(warpMat, fSrcX,fSrcY,fDesx,fDesy);
}void ConverterRegion::warp(float *mat, float srcX, float srcY, float &dstX, float &dstY)
{
float z = 0;
result[0] = (float)(srcX * mat[0] + srcY*mat[4] + z*mat[8] + 1*mat[12]);
result[1] = (float)(srcX * mat[1] + srcY*mat[5] + z*mat[9] + 1*mat[13]);
result[2] = (float)(srcX * mat[2] + srcY*mat[6] + z*mat[10] + 1*mat[14]);
result[3] = (float)(srcX * mat[3] + srcY*mat[7] + z*mat[11] + 1*mat[15]);
dstX = result[0]/result[3];
dstY = result[1]/result[3];
}
void ConverterRegion::multMats(float *srcMat, float *dstMat, float *resMat)
{
// DSTDO/CBB: could be faster, but not called often enough to matter
for (int r = 0; r < 4; r++) {
int ri = r * 4;
for (int c = 0; c < 4; c++) {
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]);
}
}
}void ConverterRegion::computeQuadToSquare(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float *mat)
{
computeSquareToQuad(x0,y0,x1,y1,x2,y2,x3,y3, mat);
// invert through adjoint
float a = mat[0], d = mat[ 1], /* ignore */ g = mat[ 3];
float b = mat[4], e = mat[ 5], /* 3rd col*/ h = mat[ 7];
/* ignore 3rd row */
float c = mat[12], f = mat[13];
float A = e - f * h;
float B = c * h - b;
float C = b * f - c * e;
float D = f * g - d;
float E = a - c * g;
float F = c * d - a * f;
float G = d * h - e * g;
float H = b * g - a * h;
float I = a * e - b * d;
// Probably unnecessary since 'I' is also scaled by the determinant,
// and 'I' scales the homogeneous coordinate, which, in turn,
// scales the X,Y coordinates.
// Determinant = a * (e - f * h) + b * (f * g - d) + c * (d * h - e * g);
float idet = 1.0f / (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;
}void ConverterRegion::computeSquareToQuad(float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float *mat)
{ float dx1 = x1 - x2, dy1 = y1 - y2;
float dx2 = x3 - x2, dy2 = y3 - y2;
float sx = x0 - x1 + x2 - x3;
float sy = y0 - y1 + y2 - y3;
float g = (sx * dy2 - dx2 * sy) / (dx1 * dy2 - dx2 * dy1);
float h = (dx1 * sy - sx * dy1) / (dx1 * dy2 - dx2 * dy1);
float a = x1 - x0 + g * x1;
float b = x3 - x0 + h * x3;
float c = x0;
float d = y1 - y0 + g * y1;
float e = y3 - y0 + h * y3;
float f = y0;
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;
}void ConverterRegion::computeWarp()
{
computeQuadToSquare( srcX[0],srcY[0],
srcX[1],srcY[1],
srcX[2],srcY[2],
srcX[3],srcY[3],
srcMat);
computeSquareToQuad( dstX[0], dstY[0],
dstX[1], dstY[1],
dstX[2], dstY[2],
dstX[3], dstY[3],
dstMat);
multMats(srcMat, dstMat, warpMat);
}
http://blog.csdn.net/beyond071/archive/2010/08/25/5837723.aspx