Visual BasicでOpenCVを使用し色や輝度の処理を行います。標準的なWindows フォームを使用し色や輝度の処理を行います。
反転
画像の色を反転するプログラムを紹介します。
プログラム開発
画像処理の説明に先立ち、フォームを簡単に説明します。MenuStripコントロール、StatusStripコントロール、OpenFileDailogコントロール、Panelコントロール、そしてPictureBoxコントロールなどを配置します。PanelコントロールとPictureBoxコントロールは依存関係があります。
フォームにコントロールを貼り付ける順序が異なると、Panel コントロールがMenuStripコントロールやStatusStripコントロールの下に入り込むときがあります。これを避けるため、最初にMenuStripコントロールやStatusStripコントロールを配置し、次にPanel コントロールを配置します。最後のPictureBox コントロールはPanel コントロールの上に配置します。
メニューを以降に示します。メニューに対応するメソッドは、メニュー項目をダブルクリックすると、自動的にメソッドが定義され、該当のソースファイル部分へカーソルが移動します。その部分に、適宜コードを記述します。
以降に、ソースリストを示します(Form1.vb)。
Imports System Imports System.IO Imports OpenCvSharp Public Class Form1 Private ttl As String = "sample" Private mSrc As Mat Public Sub New() MyBase.New InitializeComponent() Text = Me.ttl OpenFileDialog1.FileName = "" ToolStripStatusLabel1.Text = "Status" Panel1.Dock = DockStyle.Fill 'スクロール対応 Panel1.AutoScroll = True PictureBox1.Location = New Drawing.Point(0, 0) End Sub ' 開く」メニュー項目 Private Sub FileMenuOpen_Click(sender As Object, e As EventArgs) _ Handles FileMenuOpen.Click Try OpenFileDialog1.CheckFileExists = True OpenFileDialog1.Filter = ("画像ファイル(*.bmp,*.jpg)|*.bmp;*.jpg|" _ + "すべてのファイル(*.*)|*.*") OpenFileDialog1.FilterIndex = 1 If (OpenFileDialog1.ShowDialog = DialogResult.OK) Then Me.mSrc = Cv2.ImRead(OpenFileDialog1.FileName) PictureBox1.Image = Extensions.BitmapConverter.ToBitmap(Me.mSrc) PictureBox1.Size = PictureBox1.Image.Size ' ウィンドウサイズ調整 ClientSize = New Drawing.Size(PictureBox1.Width, PictureBox1.Height _ + MenuStrip1.Height + StatusStrip1.Height) 'ファイル名表示 ToolStripStatusLabel1.Text = Path.GetFileName(OpenFileDialog1.FileName) End If 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 PictureBox1.Image Is Nothing Then Return ' 読み込んでいるか Cursor = Cursors.WaitCursor Using dst = New Mat Cv2.BitwiseNot(Me.mSrc, dst) ' negative PictureBox1.Image = Extensions.BitmapConverter.ToBitmap(dst) End Using Catch ex As Exception MessageBox.Show(ex.Message) Finally Me.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
コンストラクターでコントロールの各種設定を行います。たとえば、Panel コントロールのAutoScroll プロパティをTrue に設定します。PictureBox コントロールはPanel コントロール上に配置されています。Panel コントロールのAutoScroll プロパティをTrue に設定しているので、PictureBox コントロールのサイズが Panel コントロールより大きくなると自動でスクロールバーが現れます。
[開く]メニュー項目が選択されるとFileMenuOpen_Click メソッドが呼び出されます。例外を捕捉するためにTry と Catch で囲みます。まず、OpenFileDialog オブジェクトの ShowDialog メソッドで「ファイルを開く」ダイアログを表示させます。使用者がファイルを選択し[開く]を選択すると、ShowDialog メソッドはDialogResult.OK を返します。使用者が[キャンセル]を選択すると、DialogResult.OK 以外が返ってきます。キャンセルされた場合はすぐにメソッドを抜けます。ファイルが選択されたら、OpenCvSharp のImRead メソッドでファイルを読み込みます。それをMat オブジェクトmSrc へ設定します。このままではVB.NET のPictureBoxコントロールへ表示できないため、OpenCvSharp.Extensions.BitmapConverter.ToBitmap メソッドでBitmap オブジェクトへ変換します。これをPictureBox オブジェクトのImage プロパティに設定することで、画像をフォームに表示します。
次に、PictureBox コントロールのSize プロパティを画像サイズに合わせます。さらに、フォームの ClientSize プロパティを画像の大きさに合わせ、画像を表示できるサイズに変更します。幅は画像の幅をそのまま使用しますが、高さは画像の高さに加え、MenuStripコントロールやStatusStripコントロールの高さを加えます。
最後に、表示したファイル名をStatusStripコントロールに表示します。「ファイルを開く」ダイアログが返すFileName をそのまま表示したのでは、パスまで表示されてしまいます。そこで、Path クラスのGetFileName メソッドでパス名からファイル名のみを取り出し表示します。
[処理]メニュー項目が選択されると ToolMenuEffect_Click メソッドが呼び出されます。画像が読み込まれていなかったら、メソッドをすぐに抜けます。読み込まれていたらMat オブジェクトmSrc の色反転処理を行います。その結果を、[開く]メニュー項目の処理と同様にBitmap オブジェクトへ変換し、PictureBox コントロールのImage プロパティに設定します。
[閉じる]ボタンをクリックするとFileMenuClose_Click メソッドへ制御が渡ってきます。単純に、Close メソッドを呼び出し、プログラムを終了させます。
実行
以降に実行例を示します。まず、画像を読み込み、[処理]メニュー項目が選択したときの様子を図で示します。
画像ファイルを読み込むと、フォームに画像が表示されます。[処理]メニュー項目を選択すると、画像の色が反転されます。
グレイスケール
カラー画像をグレイスケール画像へ変換するプログラムを示します。ソースコードの変更は、ごく僅かです。ToolMenuEffect_ClickメソッドのBitwiseNotメソッド呼び出しをCvtColorメソッドへ変更するのみです。以降に、ソースコードの変更部分を抜粋して示します。先のプログラムの、
Cv2.BitwiseNot(Me.mSrc, dst)
を
Cv2.CvtColor(mSrc, dst, ColorConversionCodes.BGR2GRAY)
へ変更します。
以降に入力画像と処理結果を示します。実行前の画像はカラー、実行後の画像はグレイスケールです。
輝度平滑化
画像の輝度を平滑化するプログラムを紹介します。輝度が一部に偏っているとき、その部分を広げ、見やすくします。以降に、変更部分のコードを示します。
: Using dst = New Mat Cv2.CvtColor(mSrc, dst, ColorConversionCodes.BGR2GRAY) ' 輝度平滑化 Cv2.EqualizeHist(dst, dst) ' 輝度平滑化 PictureBox1.Image = Extensions.BitmapConverter.ToBitmap(dst) End Using :
本プログラムは、画像の輝度を平滑化します。OpenCvSharp の輝度平滑化関数は、グレイスケール画像を対象としているため、以前紹介した方法でカラー画像をグレイスケール画像へ変換します。Cv2.EqualizeHistメソッドで輝度平滑化後の画像をdst へ求めます。以降に、実行例を示します。
輝度が偏っていると、その部分が広げられるためコントラストが増したように見えます。輝度が極端に偏っている場合、その部分が引き伸ばされるため、暗い部分が、より暗くなる場合もあります。
なお、画像を読み込む際にCv2.ImReadメソッドの第2 引数にImreadModes.Grayscale を与えると、入力画像の種別にかかわらず、必ずグレイスケールで読み込むことができます。このような方法を採用すると、Cv2.CvtColorメソッドの呼び出しは省略できます。以降に、簡略化したコードを示します。
: mSrc = Cv2.ImRead(OpenFileDialog1.FileName, ImreadModes.Grayscale) : Cv2.EqualizeHist(mSrc, dst) ' 輝度平滑化 :
閾値処理(スレッショルド処理)
画像に閾値処理(スレッショルド処理)へ行うには、Cv2.Thresholdメソッドを使用します。先ほどと同様、Cv2.Thresholdメソッドは、グレイスケール画像を対象としているため、カラー画像をグレイスケール画像へ変換します。閾値は60.0、最大値は210.0とします。そして閾値処理タイプはThresholdTypes.Binary を指定します。閾値処理(スレッショルド処理)後の画像をdst へ求めます。
WPF バージョン
本ブログでは基本的に「Windows フォームアプリ」を利用しますが、ここでは簡単に「WPF アプリケーション」も紹介します。既に、「WPF アプリケーション」の作成法は紹介していますので、ソースリストの説明を行います。以降に、MainWindow.xaml と MainWindow.xaml.cs のソースリストを示します。
まず、MainWindow.xamlのソースリストを示します。
<Window x:Class="MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApp" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <DockPanel LastChildFill="True"> <Menu DockPanel.Dock="Top" VerticalAlignment="Top"> <MenuItem Header="ファイル(_F)"> <MenuItem Header="開く(_O)" Click="MenuItem_Open_Click"/> <MenuItem Header="閉じる(_C)" Click="MenuItem_Close_Click"/> </MenuItem> <MenuItem Header="ツール(_T)"> <MenuItem Header="処理(_E)" Click="MenuItem_Effect_Click"/> </MenuItem> </Menu> <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto"> <Image Name ="Image" HorizontalAlignment="Left" VerticalAlignment="Top" Stretch="None"/> </ScrollViewer> </DockPanel> </Grid> </Window>
ほとんど以前のものと同じです。変更点は、"ツール(T)"メニューが増えただけです。分かりやすいように、「ツール」メニューを示します。
次に、xaml に対するvb のソースリストを示します。
Imports Microsoft.Win32 Imports OpenCvSharp Imports OpenCvSharp.WpfExtensions Class MainWindow Private mMat As Mat Private Sub MenuItem_Open_Click(sender As Object, e As RoutedEventArgs) Dim dialog = New OpenFileDialog With { .Filter = "全てのファイル (*.*)|*.*" } If dialog.ShowDialog() = True Then mMat = New Mat(dialog.FileName) Image.Source = BitmapSourceConverter.ToBitmapSource(mMat) SizeToContent = SizeToContent.WidthAndHeight End If End Sub ' 「処理」メニュー項目 Private Sub MenuItem_Effect_Click(sender As Object, e As RoutedEventArgs) If mMat Is Nothing Then Return Using dst = New Mat() Cv2.BitwiseNot(mMat, dst) ' Negative Image.Source = BitmapSourceConverter.ToBitmapSource(dst) End Using End Sub ' 「閉じる」メニュー項目 Private Sub MenuItem_Close_Click(sender As Object, e As RoutedEventArgs) Close() End Sub End Class
画像を読み込むメソッドと加工するメソッドが別メソッドのため、画像を保存するMatオブジェクトをクラスのPrivateとし、メソッド間でアクセスできるようにします。次に「ツール」-「処理」メニュー項目に対応するMenuItem_Effect_Clickメソッドを追加します。処理内容は、Windows フォームアプリと、ほとんど同じです。本プログラムの、
Cv2.BitwiseNot(mSrc, dst)
を先のプログラムと同じように変更することで、グレイスケールなどへ変更できます。
実行
[開く]メニュー項目を選択して「開く」ダイアログが表示し、ファイルを選ぶと画像がウィンドウに表示されます。
[処理]メニュー項目を選択すると、画像の色が反転されます。また、ウィンドウサイズを画像より小さくするとスクロールバーが現れます。
先のプログラムの、
Cv2.BitwiseNot(mMat, dst)
を
Cv2.CvtColor(mMat, dst, ColorConversionCodes.BGR2GRAY)
Cv2.EqualizeHist(dst, dst)
へ変更し画像の輝度を平滑化したものを紹介します。輝度が一部に偏っているとき、その部分を広げ、見やすくします。
ここで紹介したプログラムはWindowsフォームアプリと同じような手法を採用しています。WPFアプリケーションですので、ImageのSourceなどへ画像をバインドするとプログラムは簡単になります。そのようなBindやViewModelを利用した例は後述する予定ですが、OpenCVの説明が趣旨ですので、あくまでも予定は未定です。