このアプリケーションでは、画像内で検出された顔のランドマークを検出できる。画像内で見つかったすべての顔のランドマークを検出し、それらを顔の入れ替え(face swapping)や顔の平均化(face averaging)など、さまざまなアプリケーションでさらに活用できる。この機能は現在OpenCVで利用可能である。
// Command to be typed for running the sample
./sampleDetectLandmarks -file=trained_model.dat -face_cascade=lbpcascadefrontalface.xml -image=/path_to_image/image.jpg
コマンドパラメータの説明 {tutorial_face_training_parameters}
* model_filename f : (必須) 読み込む学習済みモデルを格納したバイナリファイルへのパス [例 - /data/file.dat]
- image i : (必須) 顔のランドマークを検出する対象画像へのパス。[例 - /data/image.jpg]
- face_cascade c : (必須) 顔検出器として使用したい顔カスケードのxmlファイルへのパス。
コードの理解
このチュートリアルでは、顔のランドマーク検出のサンプルコードを説明する。さっそくコードに入ろう。
c++
CascadeClassifier face_cascade;
face_cascade.load(cascade_name);
Mat img = imread(image);
Ptr<Facemark> facemark = createFacemarkKazemi());
facemark->loadModel(filename);
cout<<"Loaded model"<<endl;
上記のコードは、顔の領域を検出するためのCascadeClassifierと、顔ランドマーク検出クラスのインスタンスを作成する。顔ランドマーク検出用の学習済みモデルと、顔検出用のカスケードファイルを読み込む必要がある。また、ランドマークを検出する対象の画像も読み込む。
c++
vector<Rect> faces;
resize(img,img,Size(460,460),0,0,INTER_LINEAR_EXACT);
Mat gray;
std::vector<Rect> faces;
if(img.channels()>1){
cvtColor(img.getMat(),gray,COLOR_BGR2GRAY);
}
else{
gray = img.getMat().clone();
}
equalizeHist( gray, gray );
face_cascade.detectMultiScale( gray, faces, 1.1, 3,0, Size(30, 30) );
いくつかの前処理を行った後、まず顔の候補領域を検出する必要がある(これは vector<Rect> に格納される)。また、小さい画像のほうが処理速度が速いため、画像はより小さいサイズにリサイズされる。
c++
vector< vector<Point2f> > shapes;
if (facemark->fit(img,faces,shapes))
{
for ( size_t i = 0; i < faces.size(); i++ )
{
cv::rectangle(img,faces[i],Scalar( 255, 0, 0 ));
}
for (unsigned long i=0;i<faces.size();i++){
for(unsigned long k=0;k<shapes[i].size();k++)
cv::circle(img,shapes[i][k],5,cv::Scalar(0,0,255),FILLED);
}
namedWindow("Detected_shape");
imshow("Detected_shape",img);
waitKey(0);
}
次に、検出された各顔のシェイプを格納するためのベクトルのベクトルを作成する。上記のコードは fit 関数を呼び出して画像内で検出されたすべての顔のシェイプを取得し、続いて顔を囲む矩形を描画して目的のランドマークをマークする。
検出結果