C#/VB.NETで画像処理⑮<顔検出>
こんにちは、SKです。
C#/VB.NETで画像処理シリーズの第15弾。
今回は、OpenCVSharpを使って顔検出を行う方法を紹介します。
画像の中に存在する「人の顔」を検出する手法であり、誰の顔かを判断する顔認識ではありません。
OpenCVには"Haar-cascade"と呼ばれる分類器によって顔検出を行う機能があります。
Harr-cascadeの仕組みを理解しなくても、簡単なプログラムで顔検出を実装できます。
やはり超絶便利なライブラリ。動かしてみると楽しい機能なので、皆さんも是非試してみてください。
例によって、カメラ画像に顔画像を映し、検出位置に矩形を描画するプログラムを作ります。
参考リンク
OpenCVSharpとは?
(前回)背景差分
動画手順
①特徴分類器ファイルを用意する
まず、OpenCVライブラリ本体を落とします(OpenCVSharpではなく本家のサイトから)。
github.com
2020/5/26現在の最新バージョンは4.3.0です。
opencv-4.3.0-vc14_vc15.exeをクリックし、ダウンロード。
任意の場所に解凍し、sources\data\haarcascadesフォルダの中から"haarcascade_frontalface_default.xml"を探し、自分のプロジェクトの実行フォルダ(\bin\Debug)にコピーします。
↓
②顔検出データを生成する
CascadeClassifier型の変数を定義し、先ほどコピーしたxmlファイルを基に初期化します。
//顔検出データ private CascadeClassifier faceCascade; private void Process(Mat img) { //顔検出データ生成 if (faceCascade == null) { faceCascade = new CascadeClassifier(Path.Combine(Application.StartupPath, "haarcascade_frontalface_default.xml")); } }
③顔検出を行い矩形描画
カメラ画像をグレースケール化し、先ほど定義したfaceCascadeの"DetectMultiScale"関数の引数に指定します(その他のパラメータは未指定のデフォルト値でOK)。
顔を検出した座標情報がRect型の配列として返されるので、その数だけループを回し、赤色の矩形を描画します。
private void Process(Mat img) { //顔検出データ生成 if (faceCascade == null) { faceCascade = new CascadeClassifier(Path.Combine(Application.StartupPath, "haarcascade_frontalface_default.xml")); } //グレースケール化 using (Mat gray = img.CvtColor(ColorConversionCodes.BGR2GRAY)) { //顔検出 Rect[] rects = faceCascade.DetectMultiScale(gray); foreach(Rect r in rects) { //赤い四角を描画 Cv2.Rectangle(img, r, Scalar.Red, 2); } } }
実行します。
人の顔で画像検索した結果を映したモニタをWebカメラで撮っています。
画像内の人の顔をある程度検出できています。
精度はそこそこですが、極々簡単なプログラムで顔検出機能を実装することができました。
コード全文を載せておきます。
C#
using System; using System.IO; 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); Process(img); pictureBox1.Image = BitmapConverter.ToBitmap(img); } } }); } //顔検出データ private CascadeClassifier faceCascade; private void Process(Mat img) { //顔検出データ生成 if (faceCascade == null) { faceCascade = new CascadeClassifier(Path.Combine(Application.StartupPath, "haarcascade_frontalface_default.xml")); } //グレースケール化 using (Mat gray = img.CvtColor(ColorConversionCodes.BGR2GRAY)) { //顔検出 Rect[] rects = faceCascade.DetectMultiScale(gray); foreach(Rect r in rects) { //赤い四角を描画 Cv2.Rectangle(img, r, Scalar.Red, 2); } } } } }
Imports System.IO 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) Using img As New Mat Do v.Read(img) Process(img) PictureBox1.Image = img.ToBitmap Loop End Using End Using End Sub) End Sub '顔検出データ Private faceCascade As CascadeClassifier = Nothing Private Sub Process(ByVal img As Mat) '顔検出データ生成 If faceCascade Is Nothing Then faceCascade = New CascadeClassifier(Path.Combine(Application.StartupPath, "haarcascade_frontalface_default.xml")) End If 'グレースケール化 Using gray As Mat = img.CvtColor(ColorConversionCodes.BGR2GRAY) '顔検出 Dim rects As Rect() = faceCascade.DetectMultiScale(gray) For Each r As Rect In rects '赤い四角を描画 Cv2.Rectangle(img, r, Scalar.Red, 2) Next End Using End Sub End Class
C#/VB.NETで画像処理シリーズは、この辺で一区切りつけようと思います。
優れたGUI設計環境を持つC#/VB.NET言語、多種多様な画像処理を簡単に実現できるOpenCVライブラリ、そしてそれらを繋ぐラッパーライブラリOpenCVSharp、まだあまり広くは知られていないかもしれませんが、非常に美しい組み合わせだと私は思います。
これまでの記事を通して、画像処理プログラムは決して難しくない、楽しみながら学べる分野であるということが、少しでも伝われば幸いです。
次は、簡単なゲームプログラミングをやろうかと検討中。。