4
4

More than 3 years have passed since last update.

VisualStudio2019C#とOpenCvSharp4でWEBカメラ撮影して保存、顔認識

Last updated at Posted at 2020-10-31

VisualStudio2019C#とOpenCvSharp4でWEBカメラ撮影して保存、顔認識

環境

2020年9月
windows10
visualStduio 2019 C#
OpenCvSharp4
WEBカメラ
ロジクールのフルHD動画も撮影可能なウェブカム「HD Pro Webcam C910」
image.png

概要

image.png

  • button1でカメラ撮影
    bin\Debug\out
    に出力。顔部分を赤枠で囲う。

  • button2で、フルパスで指定した画像を読み込んで、OpencvSharpの機能使って顔認識
    image.png
    顔でないところも顔と認識している。
    オープンソースでここまで出来るのは凄いと思う。

OpenCvSharp4のインストール

ツール>NuGetパッケージマネージャ>ソリューションのNuGetの管理

OpenCvSharp4
バージョン 4.4.0.20200725
image.png

プロジェクトの作成

image.png

  • 構成 image.png

「haarcascade_frontalface_default.xml」は以下より取得
https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml

  • ソースコード
Form1.cs
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;


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

        private void button1_Click(object sender, EventArgs e)
        {
            Util.Camera camera = new Util.Camera();

            //カメラ撮影して保存
            camera.cap();

        }

        private void button2_Click(object sender, EventArgs e)
        {
            Util.Camera camera = new Util.Camera();

            //画像を読み込んで、顔に赤枠をつける
            camera.Isface(textBox1.Text);

        }
    }
}

Util.Camera.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using OpenCvSharp; //OpenCvSharp4 4.4.0.20200725 (2020年7月25日 土曜日 (2020/07/25))
using System.Drawing;
using System.Windows.Forms;
using System.Diagnostics;
using System.Drawing.Imaging;
using System.IO;
using System.Reflection;

namespace Csharp_camera.Util
{
    class Camera
    {
        int WIDTH = 640;
        int HEIGHT = 480;
        OpenCvSharp.VideoCapture capture;
        private Mat _matframe;

        private Mat matframe { get { return _matframe; }set { _matframe = value; } }

        public async void cap()
        {
            try
            {
                //ラムダ式は、デリゲート型に変換できます。 
                Func<Mat> function = () => capture_work();

                //Task.Run(Action) メソッドの引数として使用すると、バックグラウンドで実行
                matframe = await Task.Run(function);

                //画像取得出来ていれば
                if (matframe != null)
                {

                    File.createDir(Directory.GetCurrentDirectory() + @"\out");
                    string path_img = Directory.GetCurrentDirectory() + @"\out\" + File.timestap() + ".png";

                    Func<bool> savefunc = () => save(path_img, matframe);
                    if (!(await Task.Run(savefunc)))
                    {
                        //Error
                    }
                    else
                    {
                        string path_img_face = Directory.GetCurrentDirectory() + @"\out\" + File.timestap() + "_face.png";


                        //顔認識
                        if (!await Task.Run(() => Isface( path_img, path_img_face)))
                        {
                            //Error
                        }

                    }
                }
            }
            catch(Exception e)
            {
                Debug.WriteLine(e.ToString());
            }
        }

        public async void Isface(string path_img)
        {

            string dir = Path.GetDirectoryName(path_img);
            string filename = Path.GetFileNameWithoutExtension(path_img);

            string path_img_face = dir + @"\" + filename + "_face.png";

            //顔認識
            if (!await Task.Run(() => Isface(path_img, path_img_face)))
            {
                //Error
            }

        }


        private Mat capture_work()
        {
            //カメラ画像取得用のVideoCapture作成
            capture = new VideoCapture(0);

            //カメラが見つからない場合
            if (!capture.IsOpened())
            {
                MessageBox.Show("camera was not found!");
            }

            capture.FrameWidth = WIDTH;
            capture.FrameHeight = HEIGHT;

            //取得先のMat作成
            Mat matframe = new Mat(HEIGHT, WIDTH, MatType.CV_8UC3);

            try
            {
                capture.Grab();
                capture.Read(matframe);


            }
            catch(Exception e)
            {
                Debug.WriteLine(e.ToString());
                return null;
            }

            return matframe;
        }

        private void bmp(ref Bitmap bmp)
        {

            //表示用のBitmap作成
            bmp = new Bitmap(matframe.Cols, matframe.Rows, (int)matframe.Step(), System.Drawing.Imaging.PixelFormat.Format24bppRgb, matframe.Data);

        }

        private bool save(string path, Mat mat)
        {
            //エンコード
            ImageEncodingParam encodingParam = new ImageEncodingParam(ImwriteFlags.PngBilevel, 0);

            var buffer = new byte[mat.Rows * mat.Cols * mat.Channels()];

            Cv2.ImEncode(".png", mat, out buffer, encodingParam);

            // デコードして保存する
            mat = Cv2.ImDecode(buffer, ImreadModes.Color);

            // 画像の保存
            Cv2.ImWrite(path, mat);

            return true;
        }

        /// <summary>
        /// 顔認識
        /// </summary>
        /// <returns></returns>
        public bool Isface( string path_img, string path_img_face)
        {

            string path_xml = Directory.GetCurrentDirectory() + @"\xml\haarcascade_frontalface_default.xml";

            //顔の矩形を抽出
            using (Mat mat = new Mat(path_img))
            {
                // 分類機の用意
                using (CascadeClassifier cascade = new CascadeClassifier(path_xml))
                {
                    foreach (Rect rectFace in cascade.DetectMultiScale(mat))
                    {
                        // 見つかった場所に赤枠を表示
                        Rect rect = new Rect(rectFace.X, rectFace.Y, rectFace.Width, rectFace.Height);
                        Cv2.Rectangle(mat, rect, new OpenCvSharp.Scalar(0, 0, 255), 2);
                    }
                }

                //画像を保存
                save(path_img_face, mat);

            }

            return true;
        }
    }
}

File.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using System.IO;
using System.Reflection;

namespace Csharp_camera.Util
{
    static class File
    {


        /// <summary>
        /// タイムスタンプ
        /// </summary>
        /// <returns></returns>
        public static string timestap()
        {
            DateTime dateTime = DateTime.Now;
            string rlt = dateTime.ToString("yyyyMMdd_HHmmss");

            return rlt;
        }


        /// <summary>
        /// フォルダ作成
        /// </summary>
        /// <returns></returns>
        public static bool createDir(string path)
        {

            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            return true;
        }


    }
}

参考URL

https://www.it-swarm.dev/ja/c%23/c%EF%BC%83%E3%81%A7byte-%E3%81%8B%E3%82%89%E7%94%BB%E5%83%8F%E3%83%9C%E3%83%83%E3%82%AF%E3%82%B9%E3%81%AB%E7%94%BB%E5%83%8F%E3%82%92%E9%85%8D%E7%BD%AE%E3%81%99%E3%82%8B%E6%96%B9%E6%B3%95/942181192/
https://dobon.net/vb/dotnet/graphics/drawimage.html
https://qiita.com/miwazawa/items/50cf5b913b058f59daa6
https://shimat.github.io/opencvsharp_docs/html/5ae63540-c121-e3ff-d58f-39f5fc3ffdf7.htm
http://ni4muraano.hatenablog.com/entry/2017/11/20/190000
http://it-confiado.com/blog/%E3%83%89%E3%83%A9%E3%83%83%E3%82%B0%E3%82%A2%E3%83%B3%E3%83%89%E3%83%89%E3%83%AD%E3%83%83%E3%83%97%E3%81%A7%E3%83%91%E3%82%B9%E3%82%92%E6%B8%A1%E3%81%99/

4
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
4