SKProgramLab

Let's Enjoy Programming! ~画像処理/IoT/機械学習など~

C#/VB.NETで画像処理⑦<画像を二値化する>

こんにちは、SKです。
f:id:SKProgramLab:20200310203357p:plain:w100

C#/VB.NETで画像処理シリーズの第7弾。
カメラの画像を二値化します。

二値化、つまり画像を白(255)か黒(0)の二値に振り分ける処理は、画像処理の分野で最も多く使われる処理の1つなので、是非マスターしましょう。

OpenCVSharpとは?

skprogramlab.hatenablog.com

カメラ画像表示アプリケーション

skprogramlab.hatenablog.com

(前回)画像を回転する

skprogramlab.hatenablog.com

動画手順

youtu.be

①二値化ボタンを配置する

前回同様、フォーム上にボタンを配置します。
このボタンを押すと、二値化フラグを立て、カメラ画像を二値化してPictureBoxに表示するようにします。 表示テキストは"Threshold"に。 f:id:SKProgramLab:20200405132452p:plain

二値化フラグのbool変数isThreshを追加します。
f:id:SKProgramLab:20200405132540p:plain

②画像を二値化する

画像を二値化するには、まずOpenCVCvtColor関数でカラー画像をグレースケール画像に変換した後、Threshold関数で二値化します。

二値化の閾値処理にはいくつか種類がありますが、ここでは大津(Otsu)の手法というものを使います。これは、画像全体の輝度値の分布から最適な閾値を自動で決めてくれる便利な手法です。

CvtColor関数

http://opencv.jp/opencv-2.1/cpp/miscellaneous_image_transformations.html#cv-cvtcolor
・第1引数:入力画像
・第2引数:出力画像
・第3引数:色変換の種類(BGR2GRAY)

Threshold関数

http://opencv.jp/opencv-2svn/cpp/miscellaneous_image_transformations.html?highlight=threshold#cv-threshold
・第1引数:入力画像
・第2引数:出力画像
・第3引数:閾値
・第4引数:最大値
・第5引数:閾値処理の種類(Otsu)

private void Process(Mat img)
{
    if (isThresh)
    {
        Cv2.CvtColor(img, img, ColorConversionCodes.BGR2GRAY);
        Cv2.Threshold(img, img, 0, 255, ThresholdTypes.Otsu);
    }
}

f:id:SKProgramLab:20200405133311p:plain

実行します。
起動時 f:id:SKProgramLab:20200405133422p:plain
Threshold押下時
f:id:SKProgramLab:20200405133446p:plain

最後に、コード全文を載せておきます。
C#

using System;
using System.Threading.Tasks;
using System.Windows.Forms;
using OpenCvSharp;
using OpenCvSharp.Extensions;

namespace WindowsFormsApp1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            Task.Run(() =>
            {
                using (VideoCapture v = new VideoCapture(0))
                using (Mat img = new Mat())
                {
                    while (true)
                    {
                        v.Read(img);
                        Process(img);
                        pictureBox1.Image = BitmapConverter.ToBitmap(img);
                    }
                }
            });
        }

        private bool isThresh = false;

        private void Process(Mat img)
        {
            if (isThresh)
            {
                Cv2.CvtColor(img, img, ColorConversionCodes.BGR2GRAY);
                Cv2.Threshold(img, img, 0, 255, ThresholdTypes.Otsu);
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            isThresh = !isThresh;
        }
    }
}


VB.NET

Imports OpenCvSharp
Imports OpenCvSharp.Extensions

Public Class Form1

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Task.Run(Sub()
                     Using v As New VideoCapture(0)
                         Using img As New Mat
                             Do
                                 v.Read(img)
                                 Process(img)
                                 PictureBox1.Image = img.ToBitmap
                             Loop
                         End Using
                     End Using
                 End Sub)
    End Sub

    Private isThresh As Boolean = False

    Private Sub Process(ByVal img As Mat)
        If isThresh Then
            Cv2.CvtColor(img, img, ColorConversionCodes.BGR2GRAY)
            Cv2.Threshold(img, img, 0, 255, ThresholdTypes.Otsu)
        End If
    End Sub

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        isThresh = Not isThresh
    End Sub

End Class