前回実験した、膨張(Dilation)と収縮(Erosion)はそれ単体で利用されることは少なく、それぞれを組み合わせることで様々な画像処理を行います。
このあたりをまとめて「モルフォロジー演算」と呼び、ノイズ除去や平滑化などに利用されます。
OpenCVでは膨張、収縮を併せると7種類の演算が実装されていて、Imgproc.morphologyEx()メソッドを利用します。
Imgproc.morphologyEx(Mat src, Mat dst, int op, Mat kernel,
Point anchor, int iterations)
Mat src 処理したい元画像のMat
Mat dst 変換後Mat
int op 演算の種類
Mat kernel 使用する構造要素を表すMat
Point anchor 要素内のアンカー位置
int iterations 実行回数
op以外の引数は、Imgproc.dilate()や、Imgproc.erode()と同じです。
opについては、Imgprocに用意された以下の定数から選択します。
MORPH_ERODE 結果はerode()と同様
MORPH_DILATE 結果はdilate()と同様
MORPH_OPEN オープニング
MORPH_CLOSE クロージング
MORPH_GRADIENT モルフォロジー勾配(エッジ検出)
MORPH_TOPHAT トップハット
MORPH_BLACKHAT ブラックハット
オープニングは収縮した結果に対して同じ回数だけ膨張する処理を指します。
クロージングは膨張した結果に対して同じ回数だけ収縮する処理を指します。
モルフォロジー勾配は膨張した結果から収縮した結果を差し引く処理を指します。
トップハットは元画像からオープニングした画像を差し引く処理を指します。
ブラックハットはクロージングした画像から元画像を差し引く処理を指します。
なお、余談ですが「Imgproc.MORPH_」から始まる定数は、上記以外にも「MORPH_RECT」「MORPH_CROSS」「MORPH_ELLIPSE」の3つあります。
これらは、Imgproc.getStructuringElement()メソッドで利用し、モルフォロジー演算の引数(kernel)となる、指定されたサイズと形状の構造要素を返します。
それでは実際にやってみましょう。
元画像は月にしてみます。
「Imgproc.THRESH_OTSU」を利用すると単なる円になってしまうので、閾値を指定して二値化します。
Imgproc.threshold(mat, mat, 220.0, 255.0, Imgproc.THRESH_BINARY_INV);
まずは収縮です。
Imgproc.morphologyEx(mat, mat, Imgproc.MORPH_ERODE, new Mat(), new Point(-1, -1), 3);
続いて膨張です。
Imgproc.morphologyEx(mat, mat, Imgproc.MORPH_DILATE, new Mat(), new Point(-1, -1), 3);
オープニング。(収縮 ⇒ 膨張)
Imgproc.morphologyEx(mat, mat, Imgproc.MORPH_OPEN, new Mat(), new Point(-1, -1), 3);
クロージング。(膨張 ⇒ 収縮)
Imgproc.morphologyEx(mat, mat, Imgproc.MORPH_CLOSE, new Mat(3, 3, CvType.CV_8UC1), new Point(-1, -1), 3);
モルフォロジー勾配。(膨張 マイナス 収縮)
Imgproc.morphologyEx(mat, mat, Imgproc.MORPH_GRADIENT, new Mat(), new Point(-1, -1), 3);
トップハット。(元画像 マイナス オープニング)
Imgproc.morphologyEx(mat, mat, Imgproc.MORPH_TOPHAT, new Mat(), new Point(-1, -1), 3);
ブラックハット。(クロージング マイナス 元画像)
Imgproc.morphologyEx(mat, mat, Imgproc.MORPH_BLACKHAT, new Mat(), new Point(-1, -1), 3);
ということで、モルフォロジー演算にはゴミ、ノイズの除去や、単純二値化では検出出来ないものを検出、抽出出来るようにしたりなど、様々な応用が考えられます。
0 件のコメント:
コメントを投稿