2016年7月14日木曜日

OpenCvSharpでWebカメラをキャプチャしてFormに表示

マイコンに飽きてきたというか、ハードを考えるのに飽きてきたのでまたPCに戻ってきた。
とりあえずOpenCvSharpで遊んでる。で、タイトルの件。

特に難しいことはない

Thread t;
readonly int CameraIndex;

public Form1()
{
    InitializeComponent();

    CameraIndex = 0;

    t = new Thread(new ThreadStart(ImageLoad));
    t.IsBackground = true;
    t.Start();
}

private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
    t.Abort();
}

private void ImageLoad()
{
    using (CvCapture cap = Cv.CreateCameraCapture(CameraIndex))
    {
        while (true)
        {
            using (IplImage img = cap.QueryFrame())
            {
                Bitmap bmp = BitmapConverter.ToBitmap(img);

                if (pictureBox1.Image != null)
                {
                    pictureBox1.Image.Dispose();
                }

                pictureBox1.Image = bmp;
            }
        }
    }
}

ロード時にバックグラウンドスレッドを作ってFormClosedの時に止める。バックグラウンドスレッドの中ではキャプチャを作って無限ループで読み込みと表示を行う。
OpenCvのWindowを使うときにはCv.WaitKeyが必要だが、Formに表示するなら不要。QueryFrameで適切にウエイトが入る。というかカメラが1コマ撮影しないとスレッドに処理が返らない。カメラの性能に左右されるが、数fps-数十fpsくらいで安定する。これはカメラや帯域以外にも、光量にも依存する。つまり周りが暗いとカメラはシャッタースピードを遅くする必要があるから、FPSが稼げなくなる。

ただしCaptureがカメラではなく動画ファイルとかで、リアルタイムに表示する必要があるならcap.Fpsを使って適切なディレイを設定すること。ただThreadのSleepとかはあまり正確ではないので、例えば1時間の動画ファイルをちょうど1時間で表示しなければいけない場合などは工夫が必要。

OpenCvSharpの動作確認とかで途中の画像を出力したい場合もBitmapConverter.ToBitmapでC#が扱える画像に変換してPictureBoxに渡してやればOK。

0 件のコメント:

コメントを投稿