画像を回転するには アフィン変換という手法を用います。かすかな記憶では 大学の教養課程の線形代数の講義で習ったような・・・『アフィン変換』で検索すると 山のようにヒットしてきます。
OpenCv for Android では 次の手順で行います。
1)変換前の3角形の座標と 変換後の3角形の座標を与え アフィン変換行列を求める。
public static Mat getAffineTransform(Mat src, Mat dst)
Mat src: 変換前の3角形の座標を示すマトリックス
Mat dst: 変換後の3角形の座標を示すマトリックス
2)実際に画像の回転を行う
static void warpAffine(Mat src, Mat dst, Mat M, Size dsize)
static void warpAffine(Mat src, Mat dst, Mat M, Size dsize, int flags)
static void warpAffine(Mat src, Mat dst, Mat M, Size dsize, int flags, int borderMode)
static void warpAffine(Mat src, Mat dst, Mat M, Size dsize, int flags, int borderMode,
Scalar borderValue)
Mat src: 変換前画像
Mat dst: 変換後画像
Mat M : 1)で求めたアフィン変換行列
Size dsize: アフィン変換対象とするサイズ(幅・高さ)
int flags: 補完手法 (画像サイズの変更参照)
int borderMode: ピクセル外挿手法
Scalar borderValue: 定数境界モードで利用されるピクセル値.デフォルトでは 0
borderMode・borderValue ついては よくわかりません。深入りしないで、いつものようにまずは実験。
しかし ここからが 茨の道 !!!
というのも c++版とか Ver2.2.xでは getAffineTransformの引数はListであるのに対し Ver2.3.1では Matになっている。 ここで大きな誤りをしでかしてしまった。三角形の座標のペアを与えるには違いはないのですが 直感的に A(x,y)と思ったのが大きな間違い、Mat(3,2,CvType)とすべきところ Mat(2,3,CvType) とやらかしてしまったため 予期せぬエラーの嵐!!!
コーディング |
//変換先画像を 画像が切れないよう 縦横回転した状態で作成 Mat dstMat = new Mat(srcMat.cols(),srcMat.rows(),srcMat.type()); //変換前後の3角形を定義 Mat src_mat = new Mat(3,2,CvType.CV_32F); Mat dst_mat = new Mat(3,2,CvType.CV_32F); //変換する座標値を設定 // ( 0, 0) (0,240) // ( 0,240) ⇒ (240,240) // (240,240) (240, 0) float srcTri[] = new float[]{ 0, 0, 0,240,240,240}; float dstTri[] = new float[]{ 0,240,240,240,240, 0}; src_mat.put(0, 0, srcTri); dst_mat.put(0, 0, dstTri); // アフィン変換行列を求める Mat rot_mat = Imgproc.getAffineTransform(src_mat, dst_mat); // アフィン変換 Imgproc.warpAffine(srcMat, dstMat, rot_mat,dstMat.size());
src_mat およびdst_matのCv_TypeはCV_32F以外はエラーになります。
処理結果 |
上段:元画像 下段:左回り90度回転した画像
おまけ |
座標軸を変え
float srcTri[] = new float[]{200,200,250,200,200,100};
float dstTri[] = new float[]{300, 70,300, 50,200,100}; とすると
座標値にマイナスを指定しても変換できます。
by Android2.2 with OpenCv 2.3.1 for Android |