4

Flash ムービー クリップの変換マトリックスからスキュー値を取得しようとしています。変換行列は次のように表されます。

a b tx
c d ty
0 0 1

どのような変換が実行され、どちらが最初に来るかについての情報はありません。フラッシュでは、ムービー クリップを回転または傾斜させることしかできないことは知っています (間違っていたら訂正してください)。ムービー クリップの scaleX プロパティと scaleY プロパティからスケール値を取得できます。翻訳はそれほど重要ではないと思います。tx と ty をゼロとみなすことができます。

私の質問には2つの部分があります。傾斜または回転が適用されたかどうかを判断するにはどうすればよいですか? また、それぞれの値を取得するにはどうすればよいですか?

4

4 に答える 4

2

2D 回転行列は

cos(theta) -sin(theta)
sin(theta)  cos(theta)

スケーリングやせん断が適用されていない場合

   a = d
and
   c = -b
and the angle of rotation is
   theta = asin(c) = acos(a)

スケーリングが適用されていて、スケーリング係数 sx と sy を復元できる場合は、元の変換行列で最初の行を sx で、2 番目の行を sy で割り、上記のように回転角度を復元します。

そこのどこかにせん断(スキュー)が適用されている場合、私は以前のコメント者と同じです。非常に限られた場合(一度に1つの既知の方向のみに既知の順序でせん断するなど)を除いて、それは不可能かもしれません)。

于 2012-09-21T23:24:47.627 に答える
2

極分解を行う必要があります。このウィキペディアの記事では、そのしくみについて説明してい ます。

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になります。ウィキペディアの記事で、行列の平方根を計算する必要があることに気付くでしょう。これを行う唯一の方法は、固有値を計算し、次にそれらの平方根を計算し、対角行列を回転させて元の座標系に戻すことです。複雑ですが、アフィン変換がある場合に回転を計算する唯一の方法です。私の場合、私は回転だけを気にしていたので、私のコードはあなたにスキューを与えません.

于 2014-12-23T05:03:07.597 に答える
0

まず、傾斜と回転の両方を行うことができますが、最初に順序を選択する必要があります。歪行列についてはこちらで説明しています。歪行列を変換に追加するには、新しい行列を作成して実行しますyourTransformMatrix.concat(skewMatrix);

「回転角度」、「skew_X 角度」、「skew_Y 角度」、「translation_X」、「translation_Y」に関して変換の値を取得できるかどうかは、現時点ではわかりません。これは一般に非線形方程式系であり、特定のマトリックスのソリューションがあります。

于 2012-09-18T07:11:35.480 に答える