SKProgramLab

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

C#/VB.NETで画像処理②<カメラ画像をPictureBoxに表示>

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

C#/VB.NETで画像処理シリーズの第2弾。
カメラの画像を.NETの画像表示コントロールPictureBoxに表示していきます。

OpenCVSharpとは?

skprogramlab.hatenablog.com

プロジェクトの作成方法

skprogramlab.hatenablog.com

動画手順

youtu.be

①FormにPictureBoxを配置する

Form1のデザイナー画面に、ツールボックスからPictureBoxを配置。 f:id:SKProgramLab:20200311221646p:plain

追加したPictureBox1のプロパティで、下記の設定を行います。
Dock→"Fill"
f:id:SKProgramLab:20200311221844p:plain
SizeMode→"Zoom"
f:id:SKProgramLab:20200311224555p:plain
BackColor→"Black"
f:id:SKProgramLab:20200311222103p:plain

こんな感じです。 f:id:SKProgramLab:20200311222133p:plain

Webカメラ画像を取得する

OpenCVSharpのVideoCaptureを使ってWebカメラから画像を取得し、まずはCv2.ImShowで表示してみます。 Form1のLoadイベント内に下記を記述します。

using (VideoCapture v = new VideoCapture(0))
using (Mat img = new Mat())
{
    while (true)
    {
        v.Read(img);
        Cv2.ImShow("img", img);
        Cv2.WaitKey(1);
    }
}

f:id:SKProgramLab:20200311222835p:plain

PCにWebカメラを繋げてプログラムを実行すると、カメラ画像が表示されます。
f:id:SKProgramLab:20200311223154p:plain
※映っているのは以前出張で行ったフランスのアルザス地方のマグカップです。

③MatをBitmapに変換しPictureBoxに表示する

PictureBoxに表示する画像はBitmap型である必要があります。
"OpenCVSharp.Extensions"をインポートし、"BitmapConverter.ToBitmap"関数でMat→Bitmap変換できます。

また、画像取得の無限ループとフォームのメインスレッドを分離するために、ループをサブスレッド化します。
マルチスレッドについては詳しく説明しませんが、.NETではとりあえず"Task.Run"の中にぶっこめばOKです。(←超簡単!)

Task.Run(() =>
{
    using (VideoCapture v = new VideoCapture(0))
    using (Mat img = new Mat())
    {
        while (true)
        {
            v.Read(img);
            pictureBox1.Image = BitmapConverter.ToBitmap(img);
        }
    }
});

f:id:SKProgramLab:20200311225428p:plain

実行すると、フォームのPictureBox上にカメラ画像が表示されました。 f:id:SKProgramLab:20200311225208p:plain
これで準備OK!
次回から画像処理でカメラ画像をこねくり回していきましょう。

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

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
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);
                        pictureBox1.Image = BitmapConverter.ToBitmap(img);
                    }
                }
            });
        }
    }
}
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),
                           img As New Mat
                             Do
                                 v.Read(img)
                                 PictureBox1.Image = img.ToBitmap
                             Loop
                     End Using
                 End Sub)
    End Sub

End Class


個人的には、VB.NETの方が記述がシンプルで好きです。
C#セミコロン書かなくていい仕様にならないですかね?笑