我正在尝试从Flash电影片段中获取转换矩阵的偏移值。该转换矩阵由以下代码表示:
a b tx
c d ty
0 0 1
我不知道进行了什么类型的变换以及哪个先执行。我知道在flash中,你只能旋转OR倾斜电影剪辑(如果我错了,请纠正我)。我可以从电影剪辑的scaleX和scaleY属性中获取比例值。我相信平移并不重要,我只需要将tx和ty等于零。
所以我的问题有两个部分。如何确定是否应用了倾斜或旋转,以及如何获取相应的值?
a b tx
c d ty
0 0 1
我不知道进行了什么类型的变换以及哪个先执行。我知道在flash中,你只能旋转OR倾斜电影剪辑(如果我错了,请纠正我)。我可以从电影剪辑的scaleX和scaleY属性中获取比例值。我相信平移并不重要,我只需要将tx和ty等于零。
所以我的问题有两个部分。如何确定是否应用了倾斜或旋转,以及如何获取相应的值?
cos(theta) -sin(theta)
sin(theta) cos(theta)
如果您没有应用缩放或剪切,
a = d
and
c = -b
and the angle of rotation is
theta = asin(c) = acos(a)
这个术语叫做矩阵分解。以下是一个包括 Frédéric Wang 描述的斜切解决方案。
当变换按照这个顺序应用时有效:斜切、缩放、旋转、平移。
function decompose_2d_matrix(mat) {
var a = mat[0];
var b = mat[1];
var c = mat[2];
var d = mat[3];
var e = mat[4];
var f = mat[5];
var delta = a * d - b * c;
let result = {
translation: [e, f],
rotation: 0,
scale: [0, 0],
skew: [0, 0],
};
// Apply the QR-like decomposition.
if (a != 0 || b != 0) {
var r = Math.sqrt(a * a + b * b);
result.rotation = b > 0 ? Math.acos(a / r) : -Math.acos(a / r);
result.scale = [r, delta / r];
result.skew = [Math.atan((a * c + b * d) / (r * r)), 0];
} else if (c != 0 || d != 0) {
var s = Math.sqrt(c * c + d * d);
result.rotation =
Math.PI / 2 - (d > 0 ? Math.acos(-c / s) : -Math.acos(c / s));
result.scale = [delta / s, s];
result.skew = [0, Math.atan((a * c + b * d) / (s * s))];
} else {
// a = b = c = d = 0
}
return result;
}
const double PI = 3.141592653;
cv::Mat rotationOutput = cv::Mat::zeros(warp00.size(),CV_64F);
cv::Mat_<double>::iterator rotIter = rotationOutput.begin<double>();
cv::Mat_<double>::iterator warp00Iter = warp00.begin<double>();
cv::Mat_<double>::iterator warp01Iter = warp01.begin<double>();
cv::Mat_<double>::iterator warp10Iter = warp10.begin<double>();
cv::Mat_<double>::iterator warp11Iter = warp11.begin<double>();
for(; warp00Iter != warp00.end<double>(); ++warp00Iter, ++warp01Iter, ++warp10Iter,
++warp11Iter, ++rotIter){
cv::Matx22d fMatrix(*warp00Iter,*warp01Iter, *warp10Iter, *warp11Iter);
cv::Matx22d cMatrix;
cv::Matx22d cMatSqrt(0.,0.,0.,0.);
cv::mulTransposed(fMatrix, cMatrix, true);
cv::Matx21d eigenVals;
cv::Matx22d eigenVecs;
if((cMatrix(0,0) !=0.) && (cMatrix(1,1) !=0.)){
if(cv::eigen(cMatrix,true,eigenVals,eigenVecs)){
cMatSqrt = eigenVecs.t()*
cv::Matx22d(sqrt(eigenVals(0,0)),0.,0.,sqrt(eigenVals(1,0)))*eigenVecs;
}
}
cv::Matx22d rMat = fMatrix*cMatSqrt.inv();
*rotIter = atan(rMat(1,0)/rMat(0,0));
}
warp00、warp01、warp10和warp11包含仿射变换的前4个参数(平移参数warp02和warp12不需要)。在您的情况下,它将是a、b、c、d。 在维基百科文章中,您会注意到需要计算矩阵的平方根。唯一的方法是计算特征值,然后计算它们的平方根,并将对角矩阵旋转回原来的坐标系。 虽然有些复杂,但这是计算仿射变换旋转的唯一方法。 在我的情况下,我只关心旋转,所以我的代码不会给你提供倾斜。
首先,您可以同时进行倾斜和旋转,但必须先选择顺序。一个倾斜矩阵在这里有解释,要将倾斜矩阵添加到变换中,您需要创建一个新矩阵并执行yourTransformMatrix.concat(skewMatrix);
目前我无法确定是否可以以“旋转角度”、“倾斜_X角度”、“倾斜_Y角度”、“平移_X”、“平移_Y”的形式检索变换的值,这通常是一个非线性方程系统,可能没有特定矩阵的解。