画像の膨張・収縮処理を行う

画像の『膨張・収縮処理』とは、Webをググルと 一般に2値化された画像に対し行われ、ターゲットとなるピクセルの周辺に1ピクセルでも 白があれば白に置き換える膨張処理(Dilation)と、逆に1ピクセルでも 黒があれば黒に置き換える収縮処理(Erosion)からなり、ノイズを消す処理に用いるとのこと。
ただし OpenCvでは 『マルチチャンネルの場合、各チャンネルが個別に処理される』となっています。(
OpenCv-CookBook参照)つまりは 2値化された画像のみならず グレースケールさらにはカラー画像もそれなりの処理がされることになります。Andoroid版の実験では カメラで撮影した画像を2値化してテストデータとしましたが、今回は同じデータをグレースケール化したものを透視変換だけ行いそのままテストデータにします。

注)画像の『膨張・収縮処理』については 以下のサイトに詳しく記述されています。
http://imagingsolution.blog107.fc2.com/blog-entry-101.html
http://d.hatena.ne.jp/shokai/20090203/1233608481

フォームには 次のボタンを準備しました。

  • 透視変換 読み込んだ画像の正規化を行う
  • 膨張一回 膨張処理を一回行う
  • 膨張三回 膨張処理を三回行う
  • 収縮一回 収縮処理を一回行う
  • 収縮三回 収縮処理を三回行う

なお 膨張は Cv.Dilate(src, dst, element, n) 収縮はCv.Erode(src, dst, element, n) となります。
ここで 構造要素を示すelementをnullにすると ターゲットとなるピクセルは 3×3の矩形の中心で この3x3のピクセルの値をもとに 膨張・収縮処理を行います。またnは処理回数を示します。
構造要素を示すelementはIplConvKernel クラスで
IplConvKernel(int cols, int rows, int anchor_x, int anchor_y, ElementShape shape)
で定義します。
int cols,int rows: 構造要素のcols,rows
int anchor_x, int anchor_y: アンカー(ターゲット)となるピクセル位置
0 ≦ anchor_x < (cols -1) , 0 ≦ anchor_y < (rows -1)
ElementShape shape:列挙型 Rect,Ellispe,Crossから選択します。ただし Customの使い方はわかりませんでした。

 コーディング 
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using OpenCvSharp;
namespace OpenCvShp
{
    public partial class Form1 : Form
    {
        private IplImage img;
        public Form1()
        {
            InitializeComponent();
        }

        //初期処理(画像データ読み込み・表示)
        private void timer1_Tick(object sender, EventArgs e)
        {
            img = new IplImage(@”C:¥OpenCvTest¥Data¥a320_240.jpg”, LoadMode.GrayScale);
            timer1.Enabled = false;
            pictureBox1.Invalidate();
        }

        //透視変換(正規化)
        private void btnPerspective_Click(object sender, EventArgs e)
        {
            CvPoint2D32f[] src_pf = new CvPoint2D32f[] {
                new CvPoint2D32f( 26, 19), new CvPoint2D32f( 9, 148),
                new CvPoint2D32f(237, 146), new CvPoint2D32f(223, 29) };
            CvPoint2D32f[] dst_pf = new CvPoint2D32f[] {
                new CvPoint2D32f( 9, 19), new CvPoint2D32f( 9, 148),
                new CvPoint2D32f(237, 148), new CvPoint2D32f(237, 19) };
            CvMat perspective_matrix = Cv.GetPerspectiveTransform(src_pf, dst_pf);
            Cv.WarpPerspective(img, img, perspective_matrix, Interpolation.Linear,
                new CvScalar(0, 0, 0));
            pictureBox1.Invalidate();
        }

        //膨張1回
        private void btnDilate1_Click(object sender, EventArgs e)
        {
            Cv.Dilate(img, img, null, 1);
            pictureBox1.Invalidate();
        }
    
        //膨張3回 private void btnDilate3_Click(object sender, EventArgs e)
        {
            Cv.Dilate(img, img, null, 3);
            pictureBox1.Invalidate();
        }

        //収縮1回
        private void btnErode1_Click(object sender, EventArgs e)
        {
            Cv.Erode(img, img, null, 1);
            pictureBox1.Invalidate();
        }

        //収縮3回
        private void btnErode3_Click(object sender, EventArgs e)
        {
            Cv.Erode(img, img, null, 3);
            pictureBox1.Invalidate();
        }

        //描画処理
        private void pictureBox1_Paint(object sender, PaintEventArgs e)
        {
            if (!timer1.Enabled)
            {
                Bitmap bmp = new Bitmap(img.Width, img.Height);
                bmp = img.ToBitmap();
                e.Graphics.DrawImage(bmp, 0, 0, bmp.Width, bmp.Height);
                bmp.Dispose();
            }
        }
    }
}
 処理結果 
1) 元の画像 2) 透視変換して画像を正規化した状態
この画像をテストデータとします。 
3) 2)から『膨張一回』をクリックした状態 4) 2)から『膨張三回』をクリックした状態
5) 2)から『収縮一回』をクリックした状態 6) 2)から『収縮三回』をクリックした状態

このDilateメソッド Erodeメソッドは単独で使うことは まれで 膨張・収縮を繰り返し処理を行う場合が多くあります。 とくに、同じ回数分だけ膨張して収縮する処理をクロージング(Closing)、 同じ回数分だけ収縮して膨張する処理をオープニング(Opening)とよびます。実際に2)のデータをもとに実験してみます。

1) 膨張1回 → 収縮1回 2) 収縮1回 → 膨張1回 
3) 膨張3回 → 収縮3回 4) 収縮3回 → 収縮3回

 カラー画像を直接処理すると 

初めにOpenCvでは カラー画像もそれなりに膨張・収縮しょりができるはず と書きました。今度はその実験をします。次の2つの処理手順の結果を比較します。

  • 元の画像 ⇒ 膨張3回 ⇒ グレースケール化
  • 元の画像 ⇒ グレースケール化 ⇒ 膨張3回
元の画像  

カラー画像を直接膨張3回した結果

⇒ グレースケール化した画像

元画像をグレースケール化した画像

⇒ 3回膨張

2つの手順とも同じ結果が得られました。

 Windows7 Vs2008 OpenCv2.4 And OpenCvSharp
スポンサーリンク
Rectangle大広告
Rectangle大広告

シェアする

  • このエントリーをはてなブックマークに追加

フォローする