C++とOpenCVで実現するリアルタイム顔検出の方法を解説
リアルタイムでの顔検出は、静止画における顔検出と基本的な仕組みはほぼ同じです。最大の違いは、リアルタイム顔検出ではカメラからの動画ストリームを扱う必要があるという点です。
本プログラムでは「VideoCapture()」関数を使用しています。この関数はカメラから動画をキャプチャし、取得したフレームを一時的に行列(Mat)に格納します。ここではデフォルトのカメラから動画をキャプチャし、フレームを「video_stream」行列に順次読み込みながら処理を行います。
リアルタイム顔検出のサンプルコード
以下のプログラムは、Webカメラの映像から人間の顔をリアルタイムで検出するものです。
#include<iostream>
#include<opencv2/highgui/highgui.hpp>
#include<opencv2/imgproc/imgproc.hpp>
//このヘッダーには「rectangle()」関数の定義が含まれています//
#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++){ //顔の位置を特定する
Mat faceROI = video_stream(faces[i]);//検出した顔を行列に保存//
int x = faces[i].x;//顔矩形の開始点のx座標を取得//
int y = faces[i].y;//顔矩形の開始点のy座標を取得//
int h = y + faces[i].height;//矩形の高さを計算//
int w = x + faces[i].width;//矩形の幅を計算//
rectangle(video_stream, Point(x, y), Point(w, h), Scalar(255, 0, 255), 2, 8, 0);//顔の周囲に矩形を描画//
}
imshow("Face Detection", video_stream);
//検出された顔を表示//
if (waitKey(10) == 27){ //各フレームの待機時間は10ミリ秒//
break;
}
}
return 0;
}
コードのポイント解説
1. 動画ストリームの取得
「VideoCapture real_time(0)」により、デフォルトのWebカメラ(デバイス番号0)を開きます。whileループ内の「real_time.read(video_stream)」で、カメラから1フレームずつ読み込み、「video_stream」行列に格納します。
2. カスケード分類器の読み込み
「CascadeClassifier」クラスのオブジェクトを作成し、OpenCVに同梱されている学習済み分類器「haarcascade_frontalface_alt.xml」を読み込みます。このXMLファイルは、Haar特徴に基づいて正面を向いた顔を検出するための分類器です。
3. 顔の検出と矩形の描画
「detectMultiScale()」関数がフレーム内の顔を検出し、その位置とサイズを矩形(Rect)のベクトルに格納します。検出された各顔について、開始座標(x, y)と幅・高さから矩形の四隅を計算し、「rectangle()」関数でマゼンタ色(Scalar(255, 0, 255))の枠を描画します。
4. 表示と終了条件
「imshow()」で検出結果をリアルタイムに表示し、「waitKey(10)」により各フレーム間に10ミリ秒の待機時間を設けます。ESCキー(ASCIIコード27)が押されるとループを抜けてプログラムが終了します。
出力結果
プログラムを実行すると、カメラ映像の中の顔が自動的に検出され、顔の周囲に矩形の枠がリアルタイムで表示されます。

-
C++とOpenCVでバイナリ画像(二値画像)を作成する方法を解説
バイナリ画像(二値画像)とは、黒と白の2色のみで表現されるデジタル画像のことです。画像処理の観点から見ると、バイナリ画像は「0」と「1」という2つの値しか持たないピクセルで構成されています。ピクセルの値が0の場合は純粋な黒を、値が1の場合は純粋な白を表します。グレースケール画像では、各ピクセルが256段階の異なる値を持つのに対し、バイナリ画像では2つの値しか存在しません。このシンプルさゆえに、バイナリ画像はさまざまな用途で活用されています。例えば、モルフォロジー変換(形態学的処理)ではバイナリ画像が必要であり、背景から物体の形状を抽出する処理にもバイナリ画像が用いられます。OpenCVを使用す
-
C++のnew演算子を使って2次元配列を動的に宣言・生成する方法
動的な2次元配列とは、基本的に「配列へのポインタ」を要素とする配列(ポインタの配列)のことです。つまり、各行が独立した1次元配列としてヒープ上に確保され、それらの先頭アドレスを格納するポインタ配列によって全体が管理されます。下図は、3×4の2次元配列のイメージです。アルゴリズムC++のnew演算子で2次元配列を動的に確保する手順は以下の通りです。Begin 配列の寸法(行数・列数)を宣言する。 new を使って 2次元配列 a[][] を動的に確保する。 配列に要素を代入する。 配列の内容を出力する。 delete でメモリを解放する。 Endサンプルコ