Visual Basic でOpenCV⑤ - フィルタ処理

Visual BasicOpenCVを使用しフィルタ処理を行います。単にOpenCvSharp を利用し、Visual Basic からOpenCV を使う方法だけでなく、OpenCVカプセル化するクラスも紹介します。

ブラー

ブラー処理とは単純平滑化を行うことです。指定したカーネルサイズで単純平滑化を行います。処理対象画素(ピクセル)に対し、指定したサイズ領域の平均値(輝度値/色)を求めます。
以前のプログラムではフォームにOpenFileDialog コントロールを貼り付けていましたが、本プログラムはダイアログボックスを生成するようにしました。これにより、コントロールを貼り付ける必要はありません。以降にForm1に対するソースリストを示します。

Imports System
Imports System.IO

Imports OpenCvSharp
Imports Filters.CIoLibrary

Public Class Form1
    Private ReadOnly ttl As String = "sample"
    Private mSrc As Mat

    Public Sub New()
        MyBase.New
        InitializeComponent()

        Text = Me.ttl
        toolSSLbl.Text = "Status"
        Panel1.Dock = DockStyle.Fill    'スクロール対応
        Panel1.AutoScroll = True
        PBox.Location = New Drawing.Point(0, 0)
    End Sub

    ' adjust window size
    Private Sub AdjustWinSize(ByVal img As Image)
        PBox.Size = img.Size            'スクロール対応


        ClientSize = New Drawing.Size(  ' ウィンドウサイズ調整
                         img.Width, img.Height + MenuStrip1.Height _
                         + StatusStrip1.Height)
    End Sub

    ' 「開く」メニュー項目
    Private Sub FileMenuOpen_Click(sender As Object, e As EventArgs) _
                                                Handles FileMenuOpen.Click
        Try
            Dim cio As New CIo()
            Dim fname As String
            fname = cio.GetReadFile()
            If fname = Nothing Then Return

            mSrc = Cv2.ImRead(fname)
            PBox.Image = Extensions.BitmapConverter.ToBitmap(mSrc)

            AdjustWinSize(PBox.Image)                  ' ウィンドウサイズ調整

            toolSSLbl.Text = Path.GetFileName(fname)   'ファイル名表示
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try

    End Sub

    ' 「処理」メニュー項目
    Private Sub ToolMenuEffect_Click(sender As Object, e As EventArgs) _
                                                Handles ToolMenuEffect.Click
        Try
            If PBox.Image Is Nothing Then Return         ' 読み込んでいるか

            Cursor = Cursors.WaitCursor

            Using dst = New Mat()
                Cv2.Blur(mSrc, dst, New Size(15, 15))                   ' Blur
                PBox.Image = Extensions.BitmapConverter.ToBitmap(dst)
            End Using
        Catch ex As Exception
            MessageBox.Show(ex.Message)
        Finally
            Cursor = Cursors.Default
        End Try
    End Sub

    ' 「閉じる」メニュー項目
    Private Sub FileMenuClose_Click(sender As Object, e As EventArgs) _
                                                Handles FileMenuClose.Click
        Close()
    End Sub

End Class

Cv2.Blur で画像へブラー(平滑化)処理を行います。
処理の一部をクラス化しました。画像ファイルの読み込みや書き込みは多くのプロジェクトで共通に使用するためCIo クラスへ閉じ込めます。本プロジェクトのFileMenuOpen_Click を参照してください。CIo のGetReadFile メソッドで読み込み対象のファイル名を取得します。
ブラー処理にはカーネルサイズを指定しなければなりません。本プログラムはハードコードしましたので、変更したい場合はソースコードを書き換えてください。以降に、実行前の画像と実行結果を示します。
  
入力画像、カーネルサイズ3、そしてカーネルサイズ15で処理したものです。

CIoクラス

CIoクラスのソースリストを示します。

Namespace CIoLibrary
    Public Class CIo

        ' 読み込みファイル名を取得、
        '                ダイアログを使用して読み込みファイルを選択させる
        Public Function GetReadFile(ByVal Optional filter As _
                String = "画像ファイル(*.jpg,*.bmp,*.png)|*.jpg;*.bmp;*.png|" _
                                    & "すべてのファイル(*.*)|*.*") As String
            Dim fname As String = Nothing

            Using openDlg As OpenFileDialog = New OpenFileDialog()
                openDlg.CheckFileExists = True
                openDlg.Filter = filter
                openDlg.FilterIndex = 1
                If openDlg.ShowDialog() = DialogResult.OK Then fname = openDlg.FileName
            End Using
            Return fname
        End Function

        ' 書き込みファイル名を取得、
        '               ダイアログを使用して読み込みファイルを選択させる
        Public Function GetWriteFile(ByVal Optional filter As _
                String = "画像ファイル(*.jpg,*.bmp,*.png)|*.jpg;*.bmp;*.png|" _
                                    & "すべてのファイル(*.*)|*.*") As String
            Dim fname As String = Nothing

            Using svDlg As SaveFileDialog = New SaveFileDialog()
                svDlg.Filter = filter
                svDlg.FilterIndex = 1
                If svDlg.ShowDialog() = DialogResult.OK Then fname = svDlg.FileName
            End Using
            Return fname
        End Function

    End Class
End Namespace

本クラスは単純な機能しか持っていません。GetReadFile で読み込み対象のファイル名を取得し、GetWriteFile で書き込み対象のファイル名を取得します。
本クラスをプロジェクトへ追加する際は、他のプロジェクトと共用しますので、「リンクとして追加」してください。
「プロジェクト」-「既存の項目の追加」を選択するか、プロジェクトの上でマウスの右ボタンをクリックします。そして、「追加」-「既存の項目」を選択します。CIo.vb を追加しますが、追加のドロップダウンで「リンクとして追加」を選択してください。このように指定するとファイルの実体が追加されずファイルへのリンクが追加されます。

他のフィルター処理

先のプログラムを少し変更すると、いろいろな処理へ対応できます。以降に、ソースコードの変更対象部分を示します。
Cv2.Blur(mSrc, dst, New Size(11, 11))
この行を書き換えて、いろいろなフィルターへ対応させます。

ガウシアン

まず、ガウシアンフィルター処理を行うプログラムを紹介します。Blurメソッドを呼び出す部分を以降に示すように書き換えます
Cv2.GaussianBlur(mSrc, dst, New Size(5, 5), 10.0)
処理結果については、あとで示します。

ラプラシアン

エッジ検出フィルターの一種であるラプラシアンフィルタを紹介します。変更部分のソースコードを示します。
Cv2.CvtColor(mSrc, dst, ColorConversionCodes.BGR2GRAY)
Cv2.Laplacian(dst, dst, 0)

Cv2.Laplacianメソッドで画像のエッジ検出を行います。ラプラシアンフィルター処理は、Sobelフィルターなどとは異なったオペレータを採用します。

Sobel

Sobelフィルターを紹介します。Sobelフィルターもラプラシアンフィルタ同様エッジ検出フィルターの一種です。変更部分のソースコードを示します。
Cv2.CvtColor(mSrc, dst, ColorConversionCodes.BGR2GRAY)
Cv2.Sobel(dst, dst, -1, 0, 1)

Cv2.Sobelメソッドで画像のエッジ検出を行います。Sobel フィルターはエッジ検出を行いますが、ラプラシアンフィルタなどと異なったオペレータを採用します。

Canny

Cannyフィルター処理を行います。Cannyフィルターもエッジ検出フィルターの一種です。変更部分のソースコードを示します。
Cv2.CvtColor(mSrc, dst, ColorConversionCodes.BGR2GRAY)
Cv2.Canny(dst, dst, 40.0, 150.0)

Cv2.Cannyメソッドで画像のエッジ検出を行います。

膨張

画像の膨張処理を行うプログラムを紹介します。画素の欠損した部分を補う場合などに利用します。後述する画像収縮と併せて使用するとノイズ除去にも応用できます。変更部分のソースコードを示します。
Cv2.Dilate(mSrc, dst, New Mat())
Cv2.Dilateメソッドを使用し画像の膨張処理を行います。Cv2.Dilateメソッドは指定したカーネル内から、一番輝度の高い画素を選びます。

収縮

画像の収縮処理を行うプログラムを紹介します。画素の細かなゴミを除去するなど、先の膨張処理と組み合わせ、交互に実行することによってノイズ除去などにも応用できます。変更部分のソースコードを示します。
Cv2.Erode(mSrc, dst, New Mat())
Cv2.Erodeメソッドを使用し画像の収縮処理を行います。Cv2. Erodeメソッドは指定したカーネル内から、最も輝度の低い画素を選びます。

実行

以降に入力画像と処理結果を示します。順次、入力画像、ブラー処理、ガウシアンフィルター処理、ラプラシアン処理、Sobel フィルター処理、Canny フィルター処理、画像の膨張処理、そして画像の収縮処理を行った結果を示します。