はじめに
今回は、OpenCvSharpを使い、画像の中の顔や体などを検出してみたいと思います。
OpenCvSharpのインストールや、サンプルアプリの作成は以下の記事を参考にしてください。
Visual Studio 2022のインストールにつきましては、以下の記事にまとめましたので参考ください。
また、本技術を簡単に確認できるようなアプリを作成しました。
ソースコードも公開しており、アプリでは物体検出の精度を簡単に確認することができます。
カスケード分類器の用意
概要
OpenCVには、画像の中の物体検出を行う機能があります。
例えば、「顔はこういうもの」と学習したデータをカスケード分類器と呼ばれます。
自分で作成することもできますが、今回はOpenCVで用意されているカスケード分類器を使用します。
以下にXMLファイルが用意されていますので、以降で試してみましょう。
カスケード分類器一覧
カスケード分類器 | 概要 |
---|---|
haarcascade_eye.xml | 目 |
haarcascade_eye_tree_eyeglasses.xml | メガネをしている目 |
haarcascade_frontalcatface.xml | 猫の顔 |
haarcascade_frontalcatface_extended.xml | 猫の顔 |
haarcascade_frontalface_alt.xml | 正面の顔 |
haarcascade_frontalface_alt2.xml | 正面の顔 |
haarcascade_frontalface_alt_tree.xml | 正面の顔 |
haarcascade_frontalface_default.xml | 正面の顔 |
haarcascade_fullbody.xml | 体 |
haarcascade_lefteye_2splits.xml | 左目 |
haarcascade_licence_plate_rus_16stages.xml | ロシアのナンバープレート |
haarcascade_lowerbody.xml | 下半身 |
haarcascade_profileface.xml | 横顔 |
haarcascade_righteye_2splits.xml | 右目 |
haarcascade_russian_plate_number.xml | ロシアのナンバープレート |
haarcascade_smile.xml | 笑顔 |
haarcascade_upperbody.xml | 上半身 |
顔検出
サンプル画像の用意
人の顔が写っている画像を用意します。
以下のフリー素材を使用させていただきました。
以下の場所に画像を保存しました。
D:\project\img\face1.jpg
物体検出
まずは、正面の顔を検出してみましょう。
以下にアクセスし、カスケード分類器をダウンロードします。
画面上の「Raw」ボタンをクリックします。
テキスト画面が開きますので、Ctrl+Sでファイルに名前をつけて保存します。
XMLファイルは任意の場所に保存します。
私は以下の場所に保存しました。
D:\project\haarcascades\haarcascade_frontalface_default.xml
適当なボタンをフォームに配置し、ボタンのクリックイベントに処理を実装します。
ダウンロードしたカスケード分類器のパスを指定しています。
private void button3_Click(object sender, EventArgs e)
{
// 画像とカスケード分類器の読み込み
using (var mat = new Mat(@"D:\project\img\face1.jpg"))
using (var cascade = new CascadeClassifier(@"D:\project\haarcascades\haarcascade_frontalface_default.xml"))
{
// 検出
foreach (Rect rectDetect in cascade.DetectMultiScale(mat))
{
// 枠を表示
Rect rect = new Rect(rectDetect.X, rectDetect.Y, rectDetect.Width, rectDetect.Height);
Cv2.Rectangle(mat, rect, new OpenCvSharp.Scalar(255, 255, 0), 2);
}
Cv2.ImShow("image", mat);
}
}
実行してみましょう。
正しく顔が検出されました。
正面の顔については、他にもhaarcascade_frontalface_alt.xmlなど4つありますが、それぞれで検出する精度が違うようです。
顔検出がうまくいかない場合は、他のも試すと良いでしょう。
目の検出
次に、目の検出を試してみましょう。
先ほどと同様の手順で、haarcascade_eye.xmlをダウンロードします。
コードは以下です。カスケード分類器の指定が違うだけで、処理は同じです。
private void button4_Click(object sender, EventArgs e)
{
// 画像とカスケード分類器の読み込み
using (var mat = new Mat(@"D:\project\img\face1.jpg"))
using (var cascade = new CascadeClassifier(@"D:\project\haarcascades\haarcascade_eye.xml"))
{
// 検出
foreach (Rect rectDetect in cascade.DetectMultiScale(mat))
{
// 枠を表示
Rect rect = new Rect(rectDetect.X, rectDetect.Y, rectDetect.Width, rectDetect.Height);
Cv2.Rectangle(mat, rect, new OpenCvSharp.Scalar(255, 255, 0), 2);
}
Cv2.ImShow("image", mat);
}
}
実行してみると、誤検知していました・・😅
メガネをしている目の検出
次は、メガネをしている目を検出してみます。(メガネをしていない目も検出しました)
以下のフリー素材を使用しました。
haarcascade_eye_tree_eyeglasses.xmlをダウンロードします。
コードは以下です。
private void button5_Click(object sender, EventArgs e)
{
// 画像とカスケード分類器の読み込み
using (var mat = new Mat(@"D:\project\img\face2.jpg"))
using (var cascade = new CascadeClassifier(@"D:\project\haarcascades\haarcascade_eye_tree_eyeglasses.xml"))
{
// 検出
foreach (Rect rectDetect in cascade.DetectMultiScale(mat))
{
// 枠を表示
Rect rect = new Rect(rectDetect.X, rectDetect.Y, rectDetect.Width, rectDetect.Height);
Cv2.Rectangle(mat, rect, new OpenCvSharp.Scalar(255, 255, 0), 2);
}
Cv2.ImShow("image", mat);
}
}
メガネをしていても、正しく目を検出できました。
体の検出
体の検出をしてみます。
以下のフリー素材を使用しました。
haarcascade_fullbody.xmlをダウンロードします。
コードは以下です。
// 画像とカスケード分類器の読み込み
using (var mat = new Mat(@"D:\project\img\body1.jpg"))
using (var cascade = new CascadeClassifier(@"D:\project\haarcascades\haarcascade_fullbody.xml"))
{
// 検出
foreach (Rect rectDetect in cascade.DetectMultiScale(mat))
{
// 枠を表示
Rect rect = new Rect(rectDetect.X, rectDetect.Y, rectDetect.Width, rectDetect.Height);
Cv2.Rectangle(mat, rect, new OpenCvSharp.Scalar(255, 255, 0), 2);
}
Cv2.ImShow("image", mat);
}
体を検出しました。
猫の検出
折角なので最後に、猫の顔を検出します。
以下のフリー素材を使用しました。
haarcascade_frontalcatface.xmlをダウンロードします。
コードは以下です。
private void button7_Click(object sender, EventArgs e)
{
// 画像とカスケード分類器の読み込み
using (var mat = new Mat(@"D:\project\img\cat.jpg"))
using (var cascade = new CascadeClassifier(@"D:\project\haarcascades\haarcascade_frontalcatface.xml"))
{
// 検出
foreach (Rect rectDetect in cascade.DetectMultiScale(mat))
{
// 枠を表示
Rect rect = new Rect(rectDetect.X, rectDetect.Y, rectDetect.Width, rectDetect.Height);
Cv2.Rectangle(mat, rect, new OpenCvSharp.Scalar(255, 255, 0), 2);
}
Cv2.ImShow("image", mat);
}
}
一匹だけ検出しました。🙂
さいごに
OpenCVが用意している、カスケード分類器を使用して、画像の物体検出を行いました。
カスケード分類器は自作することもできるので、さらに精度を上げたいとか、特殊な検出もできるかも知れませんね。
お疲れさまでした。😊
他にも私のブログで、OpenCVについて解説している記事がありますのでご覧ください。
コメント