2012年3月24日土曜日

画像を平滑化する その1 - OpenCV for Android


おなじみの平滑化です。

はい。すいません。読めすらしません。
「へいかつか」と読みますが、いわゆるぼかし処理です。

いくつか種類があるようで、利用するフィルタ毎にメソッドが用意されています。

ガウシアンフィルタを用いた平滑化を行うにはImgproc.GaussianBlur()メソッドを利用します。

Imgproc.GaussianBlur(Mat src, Mat dst, Size ksize,
double sigma1, double sigma2, int borderType)

Mat src      処理したい元画像のMat
Mat dst      変換後Mat
Size ksize    ガウシアンカーネルサイズ
double sigma1  ガウシアンカーネルのx方向の標準偏差
double sigma2  ガウシアンカーネルのy方向の標準偏差
int borderType  ピクセル外挿手法


ksizeについては、ksize.widthとksize.heightがそれぞれ正の奇数である必要があります。
サイズを大きくすると、それだけぼかしが強くなります。
ゼロを指定した場合は、sigma1、sigma2から計算されます。

sigma1、sigma2については、それぞれx方向(横方向)、y方向(縦方向)の標準偏差です。
ksizeの対応する方向軸がゼロの場合のみ計算に利用されます。
片方がゼロであれば、もう片方と等しくなるよう設定され、両方がゼロであればksizeから計算されます。

borderTypeについては、画像を回転する その2 - OpenCV for Androidの第6引数と同じで、画像の外側をどう扱うかを指定します。
例によって省略可能です。



メディアンフィルタを用いた平滑化を行うにはImgproc.medianBlur()メソッドを利用します。

Imgproc.medianBlur(Mat src, Mat dst, int ksize)

Mat src     処理したい元画像のMat
Mat dst     変換後Mat
int ksize    アパーチャサイズ


ksizeについては、1より大きな奇数を指定します。
ネットで調べるとksizeによって、処理出来る画像の画像のビット深度が違うと書いてありますが、特にエラーは出ませんでした。



バイラテラルフィルタを用いた平滑化を行うにはImgproc.bilateralFilter()メソッドを利用します。
基本的に処理が重たい割りに、大きな変化はありません。

Imgproc.bilateralFilter(Mat src, Mat dst, int d,
double sigmaColor, double sigmaSpace, int borderType)

Mat src          処理したい元画像のMat
Mat dst          変換後Mat
int d            各ピクセル近傍領域の直径
double sigmaColor   色空間におけるフィルタシグマ
double sigmaSpace  座標空間におけるフィルタシグマ
int borderType      ピクセル外挿手法

srcについては、tyepがCV_8UC1かCV_8UC3である必要があります。
CvType.typeToString(mat.type())で確認し、必要に応じて変換して処理します。

dについては、この値が大きくなるとぼかしが強くなります。
ゼロ以下の場合は、sigmaSpaceから計算されます。

sigmaColorについては、この値が大きくなると、近くにある色的により遠くのピクセルが混ぜ合わせられます。

sigmaSpaceについては、この値が大きくなると、より遠くのピクセル同士が影響しあいます。
dがゼロ以下の場合のみ計算に利用されます。

borderTypeについては、同じく省略可能です。



それでは長くなりましたが、実際にやってみましょう。


元画像です。


ガウシアンフィルタです。
Imgproc.GaussianBlur(mat, dstMat, new Size(11, 11), 0, 0);


ksizeを変更してみます。
Imgproc.GaussianBlur(mat, dstMat, new Size(51, 3), 0, 0);


メディアンフィルタです。
Imgproc.medianBlur(mat, dstMat, 7);


ksizeを変更してみます。
Imgproc.medianBlur(mat, dstMat, 21);


バイラテラルフィルタです。
Imgproc.cvtColor(mat, mat, Imgproc.COLOR_RGBA2BGR);
Imgproc.bilateralFilter(mat, dstMat, 10, 50, 0);
Imgproc.cvtColor(dstMat, dstMat, Imgproc.COLOR_BGR2RGBA);


dを変更してみます。
かなり重たいです。
Imgproc.cvtColor(mat, mat, Imgproc.COLOR_RGBA2BGR);
Imgproc.bilateralFilter(mat, dstMat, 50, 50, 0);
Imgproc.cvtColor(dstMat, dstMat, Imgproc.COLOR_BGR2RGBA);




しかし、なぜGaussianBlur()だけ大文字から始まるんでしょう??
謎です。


1 コメント:

  1. こんにちは。

    平滑化、ボケた感じになったり絵のようになったりで、面白いですね。

    返信削除