C++
 Computer >> コンピューター >  >> プログラミング >> C++

C++とOpenCVでリアルタイム顔追跡を実現する方法

本記事では、OpenCVを使ってリアルタイムで顔を追跡する方法を解説します。このプログラムは前回の顔検出プログラムと基本的な構造は同じですが、大きく2つの点が異なります。

  • 顔を識別する際に、長方形(rectangle)の代わりに楕円(ellipse)を使用している点
  • 検出した顔の座標をコンソールウィンドウに表示するための cout 文を追加している点

リアルタイム顔検出プログラム

以下は、Webカメラの映像からリアルタイムで人間の顔を検出・追跡するC++プログラムの完全なコードです。

#include<iostream>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
//このヘッダーには図形描画関数の定義が含まれています//
#include<opencv2/objdetect/objdetect.hpp>
//このヘッダーにはCascadeClassifier(カスケード分類器)の定義が含まれています//
#include<string>
using namespace std;
using namespace cv;
int main(int argc, char** argv) {
    Mat video_stream;//ビデオストリームからのフレームを保持する行列を宣言//
    VideoCapture real_time(0);//デフォルトのWebカメラから動画をキャプチャ//
    namedWindow("Face Detection");//結果を表示するウィンドウを宣言//
    string trained_classifier_location = "C:/opencv/sources/data/haarcascades/haarcascade_frontalface_alt.xml";//学習済みXML分類器の場所を文字列で定義//
    CascadeClassifier faceDetector;//CascadeClassifierクラスのオブジェクト「faceDetector」を宣言//
    faceDetector.load(trained_classifier_location);//学習済みXML分類器をオブジェクトに読み込む//
    vector<Rect>faces;//検出した顔を格納する矩形ベクトル「faces」を宣言//
    while (true) {
        faceDetector.detectMultiScale(video_stream, faces, 1.1, 4, CASCADE_SCALE_IMAGE, Size(30, 30));//'video_stream'行列内の顔を検出//
        real_time.read(video_stream);//カメラからフレームを読み込み、'video_stream'行列に格納//
        for (int i = 0; i < faces.size(); i++){ //顔の位置を特定するためのループ//
            Point center(faces[i].x + faces[i].width * 0.5, faces[i].y + faces[i].height * 0.5);//顔の中心座標を取得//
            ellipse(video_stream, center,Size(faces[i].width * 0.5, faces[i].height * 0.5), 0, 0, 360, Scalar(255, 0, 255), 4, 8, 0);//顔に楕円を描画//
            int horizontal = (faces[i].x + faces[i].width * 0.5);//座標の水平方向(X)の値を取得//
            int vertical=(faces[i].y + faces[i].width * 0.5);//座標の垂直方向(Y)の値を取得//
            cout << "Position of the face is:" << "(" << horizontal << "," << vertical << ")" << endl;
            //コンソールウィンドウに顔の位置を表示//
        }
        imshow("Face Detection", video_stream);
        //検出した顔を表示//
        if (waitKey(10) == 27){ //各フレームごとの待機時間は10ミリ秒//
            break;
        }
    }
    return 0;
}

実行結果

このプログラムを実行すると、Webカメラの映像がウィンドウに表示され、検出された顔の周囲にマゼンタ色の楕円がリアルタイムに描画されます。同時に、コンソールウィンドウには顔の中心座標(X, Y)が継続的に出力されます。

C++とOpenCVでリアルタイム顔追跡を実現する方法

C++とOpenCVでリアルタイム顔追跡を実現する方法

コードの重要ポイント

CascadeClassifier(カスケード分類器)

CascadeClassifierは、OpenCVに標準搭載されているオブジェクト検出用のクラスです。今回はHaar特徴ベースの学習済み分類器「haarcascade_frontalface_alt.xml」を読み込み、正面顔を検出しています。このXMLファイルはOpenCVのインストールフォルダ内のdata/haarcascadesディレクトリに含まれています。パスは環境に合わせて適宜変更してください。

detectMultiScale() 関数

画像中から複数のサイズの顔を検出する関数です。主な引数は以下の通りです。

  • 1.1:スケールファクター。画像を縮小しながら多段階で検出を行う際の縮小率
  • 4:minNeighbors。誤検出を減らすために必要な近傍矩形の最小数
  • Size(30, 30):検出対象となる顔の最小サイズ

楕円の描画と座標の出力

検出した顔の矩形情報から中心点を計算し、ellipse()関数で顔を囲む楕円を描画します。さらに、中心のX座標・Y座標をcoutでコンソールに出力することで、顔の位置を数値として把握できます。この仕組みを応用すれば、顔の位置に連動したロボット制御やUI操作など、さまざまなアプリケーションへの拡張が可能です。

  1. C++とOpenCVを使って線を描画する方法

    OpenCVで線を描画するには、始点と終点の2つの座標が必要です。さらに、線を描くためのキャンバス(描画領域)も用意しなければなりません。線を描画するために必要な要素OpenCVでは、キャンバスとして機能するのが行列(Mat)です。この行列に対して、線の始点と終点を定義し、加えて以下の情報も指定します。線の色線の太さつまり、OpenCVで線を描くには、行列・2つの点・色・線の太さという4つの要素を宣言しておく必要があります。必要なヘッダーファイルOpenCVで線を描画するには、<imgproc.hpp>ヘッダーをインクルードします。これは、line()関数がこのヘッダー内で定義され

  2. C++とOpenCVで画像のチャンネル数を取得する方法を解説

    この記事では、OpenCVを使って画像のチャンネル数を調べる方法について解説します。プログラムを実行すると、コンソール画面に画像のチャンネル数が表示されます。チャンネル数を取得するには、OpenCVが提供するchannels()メソッドを使用します。このメソッドは、Matクラスのオブジェクト(画像行列)に対して呼び出すことで、その画像のチャンネル数を整数値として返します。例えば、カラー画像の場合は通常3チャンネル(BGR)、グレースケール画像の場合は1チャンネルとなります。画像処理を行う際、扱っている画像がカラーかモノクロかを判別するために、チャンネル数の確認は非常に重要な処理の一つです。以下