顔、目、口を認識するためのOpenCVの使用法 - C++での実装
本記事では、OpenCVのHaar Cascadeを使用して画像中の顔と目を検出する方法について説明します。まず、Haar Cascadeについて簡単に紹介します。
Haar Cascadeの紹介
Haar Cascadeは、2001年にPaul ViolaとMichael Jonesによって導入された、コンピュータビジョンにおける物体検出のための広く使用されている手法です。この技術は、画像やビデオ内の顔や目などの物体を検出するために機械学習を利用します。このプロセスには、Haar-like特徴が使用されます。これらは、本質的に物体を認識するためのデジタル画像特徴であり、エッジやテクスチャなどの特定の領域を強調する単純な矩形パターンです。
Haar Cascadeは、特に顔や目の検出に効果的であり、多くの顔認識システムにおいて重要なコンポーネントとなっています。人気のあるコンピュータビジョンライブラリであるOpenCVには、顔や目などの一般的な物体のための事前訓練されたHaar Cascade分類器が含まれており、C++プロジェクトに簡単に統合することができます。これにより、Haar Cascadeは物体検出タスクに取り組む開発者にとって強力かつアクセスしやすいツールとなります。
Haar Cascadeの準備
HaarCascadeフォルダーは、前回の記事で紹介したopencv\build\etc\haarcascadesのパスにあります。このフォルダーをプロジェクトのbuildフォルダーにコピーします。ただし、このフォルダーには顔を認識するhaarcascade_frontalface_default.xmlと目を認識するhaarcascade_eye.xmlは含まれていますが、口を認識するhaarcascade_mcs_mouth.xmlは含まれていません。口を認識するためには、以下のリンクからhaarcascade_mcs_mouth.xmlをダウンロードして追加します。
この記事で使用する画像ファイルimage.jpgです。
次に、C++プログラムを修正して、顔、目、口を検出する方法を示します。
修正後のmain.cpp
#include <iostream>
#include <opencv2/opencv.hpp>
// 画像中の顔、目、口を検出する関数
void FacialPartsDetect(cv::Mat& image)
{
// 顔、目、口の検出のためのHaarカスケード分類器をロード
cv::CascadeClassifier face_cascade;
cv::CascadeClassifier eyes_cascade;
cv::CascadeClassifier mouth_cascade;
// 顔のカスケードファイルをロード
if (!face_cascade.load("../haarcascades/haarcascade_frontalface_default.xml"))
{
std::cerr << "顔のカスケードのロードエラー\n";
return;
}
// 目のカスケードファイルをロード
if (!eyes_cascade.load("../haarcascades/haarcascade_eye.xml"))
{
std::cerr << "目のカスケードのロードエラー\n";
return;
}
// 口のカスケードファイルをロード
if (!mouth_cascade.load("../haarcascades/haarcascade_mcs_mouth.xml"))
{
std::cerr << "口のカスケードのロードエラー\n";
return;
}
// 入力画像をグレースケールに変換
cv::Mat gray;
cv::cvtColor(image, gray, cv::COLOR_BGR2GRAY);
cv::equalizeHist(gray, gray); // コントラストを改善するためにヒストグラム均等化を適用
// グレースケール画像で顔を検出
std::vector<cv::Rect> faces;
face_cascade.detectMultiScale(gray, faces, 1.1, 3, 0, cv::Size(30, 30));
// 検出された各顔に対してループ
for (size_t i = 0; i < faces.size(); i++)
{
// 顔の周りに四角形を描画
cv::rectangle(image, faces[i], cv::Scalar(255, 0, 0), 2);
// 検出された顔内で目を検出するための領域(ROI)を定義
cv::Mat faceROI = gray(faces[i]);
// 顔のROI内で目を検出
std::vector<cv::Rect> eyes;
eyes_cascade.detectMultiScale(faceROI, eyes, 1.1, 3, 0, cv::Size(15, 15));
for (size_t j = 0; j < eyes.size(); j++)
{
cv::Rect eye = eyes[j];
eye.x += faces[i].x;
eye.y += faces[i].y;
cv::rectangle(image, eye, cv::Scalar(0, 255, 0), 2);
}
// 顔の下半分を口検出のためのROIとして定義
cv::Mat lower_faceROI = gray(cv::Rect(faces[i].x, faces[i].y + faces[i].height / 2, faces[i].width, faces[i].height / 2));
// 下顔のROI内で口を検出
std::vector<cv::Rect> mouths;
mouth_cascade.detectMultiScale(lower_faceROI, mouths, 1.1, 3, 0, cv::Size(30, 30));
for (size_t k = 0; k < mouths.size(); k++)
{
cv::Rect mouth = mouths[k];
mouth.x += faces[i].x;
mouth.y += faces[i].y + faces[i].height / 2;
cv::rectangle(image, mouth, cv::Scalar(0, 0, 255), 2);
}
}
}
int main()
{
// 画像をロード
cv::Mat image = cv::imread("../../image.jpg");
// 画像が正常にロードされたかチェック
if (image.empty())
{
std::cerr << "エラー: 画像をロードできませんでした。" << std::endl;
return -1;
}
// 画像を800x600にリサイズ
cv::Mat resized_image;
cv::resize(image, resized_image, cv::Size(800, 600));
// 顔部位検出関数を呼び出す
FacialPartsDetect(resized_image);
// 検出結果をウィンドウに表示
cv::imshow("Display Image", resized_image);
// 無限にキー入力を待つ
cv::waitKey(0);
return 0;
}
プログラムの主な流れ
Haarカスケード分類器のロード: 顔、目、口を検出するための事前訓練されたHaarカスケード分類器をロードします。それぞれのカスケードファイルが正しくロードされているか確認します。
画像のグレースケール変換: 入力画像をグレースケールに変換し、コントラストを改善するためにヒストグラム均等化を適用します。
顔の検出: detectMultiScale関数を使用してグレースケール画像内の顔を検出します。この関数は、画像内の複数のスケールで物体を検出します。
目と口の検出: 検出された顔ごとに、目と口の検出を行います。目の検出は顔領域全体で行い、口の検出は顔の下半分の領域で行います。
検出結果の描画: 検出された顔、目、口に対してそれぞれ異なる色の四角形を描画します。顔は赤、目は緑、口は青で表示されます。
実行と結果の確認
修正が終わったら、もう一度ビルドして実行します。その際、顔、目、口がそれぞれ赤、緑、青の四角で表示されることを確認します。以下は処理済みの画像の例です。
この記事では、OpenCVのHaar Cascadeを使用して、画像中の顔、目、口を検出する方法について説明しました。次回は、さらに高度な認識技術について紹介します。
エンジニアファーストの会社 株式会社CRE-CO
su_myat_phyu
参考