4回続いた 『画像を平滑化する』シリーズも終わり 今度は 『エッジ画像を求める』シリーズ。 『エッジ画像を求める』メソッドには、Sobel,Laplacian,Cannyの3種類があります。まず最初は、一次微分(差分)を用いてエッジ検出を行うSobelです。
static void Sobel(Mat src, Mat dst, int ddepth, int dx, int dy)
static void Sobel(Mat src, Mat dst, int ddepth, int dx, int dy, int ksize)
static void Sobel(Mat src, Mat dst, int ddepth, int dx, int dy, int ksize, double scale)
static void Sobel(Mat src, Mat dst, int ddepth, int dx, int dy, int ksize, double scale, double delta)
static void Sobel(Mat src, Mat dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType)
Mat src : 処理したい元の画像
Mat dst : 変換後のエッジ画像
int ddepth : 変換後画像のビット深度。通常は src.depth()を指定すれば良いようです。
int dx, int dy : x 方向,y 方向の微分次数。
int ksize : 拡張 Sobel カーネルのサイズです。
OpenCvのリファレンスおよびjavadoc によれば 1,3,5,7 とありますが
『ぎーくなぁど』には 奇数かつ31以下とあります。
実験の結果ではksize=21でもエラーにはなりませんでした。
double scale : 計算されたデリバティブの値の任意のスケールファクタ
double delta : オプションのデルタ値
int borderType : ピクセル外挿手法
scale ,delta は OpenCvのリファレンスにも記述がなく borderTypeは『画像を回転する』と同じなのでscale 以降を除いて実験します。
実行結果 |
dxを変えてみます。
上段:元画像 本を撮影した画像を透視変換したもの
中段:Imgproc.Sobel(mat1, mat2, mat.depth(), 1, 0, 1);
下段:Imgproc.Sobel(mat1, mat3, mat.depth(), 2, 0, 1);
ちょっと表現できませんが(笑)確かに違う・・・・
ドキュメントのおすすめ版?
OpenCvのリファレンスによると
Sobelは大抵( dx= 1, dy = 0, ksize = 3) あるいは ( dx= 0, dy= 1, ksize= 3)で呼ばれることが多い
と書いてあります。
このパターンを実験しました。
上段:元画像
中段:Imgproc.Sobel(mat1, mat2, mat.depth(), 0, 1, 3);
下段:Imgproc.Sobel(mat1, mat3, mat.depth(), 1, 0, 3);
これは結果がはっきりわかります。黒⇒白に変化するエッジが反応し白く見えています。
(微分なので当然か・・)
dx=0とすると 縦方向の変化 dy=0とすると 横方向の変化に強く反応しています。
(次の実験の中段と比較してください。)
ksizeを変えてみます。
上段:元画像
中段:Imgproc.Sobel(mat1, mat2, mat.depth(), 1, 1, 3);
下段:Imgproc.Sobel(mat1, mat3, mat.depth(), 1, 1, 5);
ksize=CV_SCHARRとしてScharr フィルタを利用してみます。
上段:元画像
中段:Imgproc.Sobel(mat1, mat2, mat.depth(), 0, 1,CV_SHARR);
下段:Imgproc.Sobel(mat1, mat3, mat.depth(), 1, 0, CV_SHARR);
小さな変化を拾っている感じがします。
by Android2.2 with OpenCv 2.3.1 for Android |