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

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

##環境
2020年9月
windows10
visualStduio 2019 C#
OpenCvSharp4
WEBカメラ
ロジクールのフルHD動画も撮影可能なウェブカム｢HD Pro Webcam C910｣
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547467/968119fe-8a57-9c6f-17ae-098cb3e735f2.png)

##概要

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547467/f41f9666-a46b-de27-d10e-5fc9785dea42.png)

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



+ button2で、フルパスで指定した画像を読み込んで、OpencvSharpの機能使って顔認識
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547467/4dafe6da-c0a6-3b08-6a41-100c42d1f219.png)
顔でないところも顔と認識している。
オープンソースでここまで出来るのは凄いと思う。

##OpenCvSharp4のインストール

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

OpenCvSharp4
バージョン　4.4.0.20200725
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547467/a423ad4f-0bfd-eda3-d561-51b8b7094f04.png)

##プロジェクトの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547467/d84e5cdc-9635-2f75-5ef9-d5e92c4f77bf.png)

+ 構成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547467/d9262b33-3ca3-3987-4ca1-30bbb8455fe2.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/