C++とOpenCVを使って画像内の最大の顔を検出する方法
このチュートリアルでは、画像の中から最も大きい顔だけを検出する方法を解説します。基本的な処理の流れは通常の顔検出と同じですが、ここでは追加で Rect構造体 と forループ を組み合わせることで、複数検出された顔の中から最大のものを特定する点がポイントです。
最大の顔を切り出す仕組み
顔領域を切り出す関数の基本的な書式は以下の通りです。
Mat faceROI = image_with_humanface(maxRect)
maxRect には、画像内で検出された最大の顔の位置(座標)とサイズ(面積)の情報が格納されています。上記の1行は、元画像から maxRect が示す領域を同じ位置のまま切り取り、その結果を faceROI という行列に保存する処理を行っています。
静止画から最大の顔を検出するサンプルプログラム
以下のプログラムは、静止画の中から最も大きい顔を検出し、その周囲に矩形を描画します。
#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 image_with_humanface;//顔が写った画像を読み込むための行列を宣言//
image_with_humanface = imread("person.jpg");//顔が写った画像を読み込む//
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);//学習済み分類器をオブジェクトに読み込む//
vector<Rect>faces;//「faces」という名前の矩形ベクトルを宣言//
faceDetector.detectMultiScale(image_with_humanface, faces, 1.1, 4, CASCADE_FIND_BIGGEST_OBJECT);//画像中の顔を検出//
Rect maxRect;//矩形を宣言(デフォルトのサイズは0ピクセル)//
for (int i = 0; i < faces.size(); i++){ //最大の顔を検出するためのforループ//
if (faces[i].area() > maxRect.area()){ //各顔の面積を計算し、maxRectの面積と比較//
maxRect = faces[i];//最大の顔に対応する矩形をmaxRectに保存//
}
}
for (size_t i = 0; i < faces.size(); i++){ //顔の周囲に矩形を描画するためのループ//
Mat faceROI = image_with_humanface(maxRect);//maxRectと同じサイズの行列に顔領域を保存//
int x = maxRect.x;//顔矩形の始点のx座標(列)を取得//
int y = maxRect.y;//顔矩形の始点のy座標(行)を取得//
int h = y + maxRect.height;//矩形の高さを計算//
int w = x + maxRect.width;//矩形の幅を計算//
rectangle(image_with_humanface, Point(x, y), Point(w, h), Scalar(255, 0, 255), 3, 6, 0);//最大の顔の周囲に矩形を描画//
}
imshow("Face Detection",image_with_humanface);//最大の顔を表示//
waitKey(0);//キー入力を待ってプログラムを終了
return 0;
}コードのポイント
- detectMultiScale():Haar Cascades分類器を使って画像中の顔を検出し、その結果をRect型のベクトルに格納します。
- area()による面積比較:各検出結果の面積を順番に比較し、最も大きな矩形をmaxRectに保持することで最大の顔を特定します。
- rectangle():検出した最大の顔の周囲に指定色・指定太さの矩形を描画します。
実行結果
プログラムを実行すると、画像の中で最も大きい顔の周囲にマゼンタ色(BGR値:255, 0, 255)の矩形が描画され、「Face Detection」ウィンドウに結果が表示されます。
-
C++とOpenCVを使って線を描画する方法
OpenCVで線を描画するには、始点と終点の2つの座標が必要です。さらに、線を描くためのキャンバス(描画領域)も用意しなければなりません。線を描画するために必要な要素OpenCVでは、キャンバスとして機能するのが行列(Mat)です。この行列に対して、線の始点と終点を定義し、加えて以下の情報も指定します。線の色線の太さつまり、OpenCVで線を描くには、行列・2つの点・色・線の太さという4つの要素を宣言しておく必要があります。必要なヘッダーファイルOpenCVで線を描画するには、<imgproc.hpp>ヘッダーをインクルードします。これは、line()関数がこのヘッダー内で定義され
-
C++とOpenCVで画像のチャンネル数を取得する方法を解説
この記事では、OpenCVを使って画像のチャンネル数を調べる方法について解説します。プログラムを実行すると、コンソール画面に画像のチャンネル数が表示されます。チャンネル数を取得するには、OpenCVが提供するchannels()メソッドを使用します。このメソッドは、Matクラスのオブジェクト(画像行列)に対して呼び出すことで、その画像のチャンネル数を整数値として返します。例えば、カラー画像の場合は通常3チャンネル(BGR)、グレースケール画像の場合は1チャンネルとなります。画像処理を行う際、扱っている画像がカラーかモノクロかを判別するために、チャンネル数の確認は非常に重要な処理の一つです。以下