C#でOpenCVによる顔検出を行う方法

この記事は公開から4年以上経過しています。

今回はOpenCvSharp4を使い、C#で顔認識(検出)を行なう方法を紹介します。
C#からOpenCVを使うと、ひと昔前は自分でC++/CLIのラッパーを書く必要があるなどかなり面倒でしたが、昨今では有志がとても素晴らしいライブラリを公開してくれているため、すっかり参入障壁が取り払われたと言っても過言ではありません。

ここで紹介するコードはあくまで目的の機能を分かりやすく説明/実現するための最小限コードとなっています。このコードや説明を参考にされる場合は適切なエラーチェックや、充分な品質/動作検証を行って頂くようにお願い致します。

サンプルソースコード

ソースコードは以下の1本のみ、VisualStudio2019/C#/.NET Core3.1で作成しています。

  • 本体プログラム(Program.cs)

今回のサンプルでは、以下の判定画像ファイルと顔認識カスケードファイルを使用します。

また、上記の他にNuGetからOpenCvSharp4.Windowsパッケージを導入しておく必要があります。

本体プログラム(Program.cs)

プログラムのメイン処理です。

見ての通りなので説明するまでも無いと思いますが、簡単に説明すると、

  1. 顔認識させたい判定画像ファイルをロード
  2. 顔認識用のカスケード分類器を作成
  3. 顔認識用のグレースケール画像を作成
  4. グレースケール画像に対して顔認識を実行
  5. 検出された顔を囲む枠線を結果画像上に描画
  6. 結果画像を表示

となります。

// Program.cs
using OpenCvSharp;

namespace OpenCVTest201008
{
    internal class Program
    {
        // 判定画像パス
        private const string INPUT_IMAGE_PATH = "face_detection_test.png";

        // 顔認識用カスケードファイルパス
        private const string CLASSIFIER_FILE_PATH = "haarcascade_frontalface_default.xml";

        // メイン
        private static void Main(string[] args)
        {
            // 結果画像
            Mat matRetImage = null;

            // 顔認識用カスケード分類器を作成
            using (var haarCascade = new CascadeClassifier(CLASSIFIER_FILE_PATH))
            // 判定画像ファイルをロード
            using (var matSrcImage = new Mat(INPUT_IMAGE_PATH, ImreadModes.Color))
            using (var matGrayscaleImage = new Mat())
            {
                matRetImage = matSrcImage.Clone();

                // 入力画像をグレースケール化
                Cv2.CvtColor(
                    src: matSrcImage,
                    dst: matGrayscaleImage,
                    code: ColorConversionCodes.BGR2GRAY);

                // 顔認識を実行
                var faces = haarCascade.DetectMultiScale(
                    image: matGrayscaleImage,
                    scaleFactor: 1.1,
                    minNeighbors: 3,
                    flags: HaarDetectionType.ScaleImage,
                    minSize: new Size(100, 100));

                // 認識した顔の周りを枠線で囲む
                foreach (var face in faces)
                {
                    Cv2.Rectangle(
                        img: matRetImage,
                        rect: new Rect(face.X, face.Y, face.Width, face.Height),
                        color: new Scalar(0, 255, 255),
                        thickness: 2);
                }
            }

            // 結果画像を表示
            Cv2.ImShow("Detected faces", matRetImage);

            // キー押下を待機
            Cv2.WaitKey();

            matRetImage?.Dispose();
        }
    }
}

はい。たったこれだけです。

実行結果

プログラムを実行すると、以下のように判定画像上で検出された顔(今回は私のアバター)を黄色の四角形で囲んで表示します。アニメキャラ的な画像でも、しっかりと顔として認識できているのが凄いですね。
最小検出サイズ設定を小さくすると、右上の背景の看板のモザイク画像も顔として認識していました。

file

ちなみに画像処理でお馴染みのLennaでもこのとおり認識できています。

file

実質十数行程度のプログラムでこれほどまで簡単に顔認識機能が実装できてしまうとは、凄いの一言です。OpenCVは画像を利用した機械学習などでも必須のライブラリですので、これまで触ったことがない方は是非この機会に試してみてはいかがでしょうか。

参考ウェブサイトなど

以上です。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする