2012年2月26日日曜日

画像を回転する その2 - OpenCV for Android


前回は第5引数以下を省略したImgproc.warpAffine()メソッドについて実験しました。
今回は第5引数以下についても、それぞれの定数でどんな変化が見られるかやってみましょう。

Imgproc.warpAffine(Mat src, Mat dst, Mat M, Size dsize,
int flags, int borderMode, Scalar borderValue)

Mat src         処理したい元画像のMat
Mat dst         変換後Mat
Mat M          2×3の変換行列
Size dsize       変換後Matのサイズ
int flags         補間手法
int borderMode     ピクセル外挿手法
Scalar borderValue  定数境界モードで利用されるピクセル値


flagsについてはImgprocに用意された以下の定数から選択します。
定数は画像サイズを変更すると同じで、サイズが変わる場合の補完手法というところでしょうか。
また、それと組み合わせて使うオプションフラグが1つあります。

INTER_NEAREST  最近傍補間
INTER_LINEAR   バイリニア補間(デフォルト)
INTER_AREA     ピクセル領域の関係を利用したリサンプリング
INTER_CUBIC    4x4の近傍領域を利用するバイキュービック補間
INTER_LANCZOS4 8x8の近傍領域を利用するLanczos法の補間

WARP_INVERSE_MAP M が逆変換であることを意味する
(上記と組み合わせて使うオプションフラグ)


borderModeについてはImgprocに用意された以下の定数から選択します。
この定数で、回転することで空白となる部分の扱いが決まります。

BORDER_REPLICATE    画像境界の値を複製してコピー
BORDER_CONSTANT   borderValueで指定したピクセル値
BORDER_REFLECT     画像境界で反射するようにコピー
BORDER_WRAP       画像自身を繰り返しコピー
BORDER_REFLECT_101   画像境界で反射するようにコピー
BORDER_REFLECT101    画像境界で反射するようにコピー
BORDER_DEFAULT     画像境界で反射するようにコピー
BORDER_TRANSPARENT 元画像を変更しない

「BORDER_REFLECT」、「BORDER_REFLECT_101」、「BORDER_REFLECT101」、「BORDER_DEFAULT」の差は分かりませんでした。


borderValueについてはborderModeで「BORDER_CONSTANT」を選択した際に利用するピクセル値を決めます。
デフォルトではゼロです。


flagsについてはおそらくサイズ変更の時と同じだと思いますので、オプションフラグだけ試します。

元画像。

「INTER_LINEAR」で変換。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR);

オプションフラグを立ててみます。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR | Imgproc.WARP_INVERSE_MAP);

なるほど。変換行列が逆に扱われて、変換結果も逆になるわけですね。


続いてborderModeについてやってみましょう。

画像境界の値がそのままコピーされます。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR,Imgproc.BORDER_REPLICATE);


指定したピクセル値で埋めます。
デフォルトではScalarがゼロで面白くないので、色をつけてみます。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR,Imgproc.BORDER_CONSTANT,
  new Scalar(200, 150));


ミラー的な感じで埋めます。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR,Imgproc.BORDER_REFLECT);


回転することでBitmapの外側に出てしまった領域で埋めます。
スライドパズルが作れそうですね。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR,Imgproc.BORDER_WRAP);


「BORDER_REFLECT」と区別がつきません。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR,Imgproc.BORDER_REFLECT_101);


「BORDER_REFLECT」と区別がつきません。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR,Imgproc.BORDER_REFLECT101);


「BORDER_REFLECT」と区別がつきません。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR,Imgproc.BORDER_DEFAULT);


元画像をそのままにして変換先にだけ上書きします。
Imgproc.warpAffine(mat, dstMat, affineTrans, dstMat.size(),
  Imgproc.INTER_LINEAR,Imgproc.BORDER_TRANSPARENT);


ちなみに単なる回転だけではなく、サイズや形状が変わるとどうなるのでしょう。
ちょっとやってみましょう。

BORDER_REPLICATE

BORDER_REFLECT

BORDER_WRAP

まぁ想定通りの結果ですね。

という事で、定数が多いと長くなりますが、また別のメソッドでも使いそうなので、覚えておくと良いでしょう。

0 件のコメント:

コメントを投稿