OpenCV 5.0.0
Open Source Computer Vision
読み込み中...
検索中...
見つかりません
🤖 AIによる機械翻訳(非公式) — これは OpenCV 5.0.0 公式リファレンス(英語)を AI (Claude) で自動翻訳したものです。訳に誤りを含む場合があります。正確な情報は 公式英語版(原文) を参照してください。
Facemark APIの利用

目標

このチュートリアルでは、以下のことができるようになる

  • Facemark オブジェクトを生成する。
  • facemark アルゴリズムにユーザー定義の顔検出器を設定する
  • アルゴリズムを学習させる。
  • 学習済みモデルを使用して、与えられた画像から顔のランドマークを検出する。

準備

このチュートリアルを続ける前に、顔のランドマーク検出のデータセットをダウンロードしておく必要がある。http://www.ifp.illinois.edu/~vuongle2/helen/ から取得できる helen データセットのダウンロードを推奨する(注意! このアルゴリズムはこのデータセットでの学習に約 9GB の RAM を必要とする)。

アノテーション形式が API でサポートされていることを確認すること。アノテーションファイルの内容は以下のスニペットのようになっているはずである:

version: 1
n_points: 68
{
212.716603 499.771793
230.232816 566.290071
...
}

次に行うことは、画像ファイルの一覧とアノテーションファイルの一覧をそれぞれ含む2つのテキストファイルを作成することである。両方のファイルで画像とアノテーションの順序が一致していることを確認すること。さらに、相対パスではなく絶対パスを使うことを推奨する。Linux マシンでファイル一覧を作成する例

ls $PWD/trainset/*.jpg > images_train.txt
ls $PWD/trainset/*.pts > annotation_train.txt

images_train.txt の内容例

/home/user/helen/trainset/100032540_1.jpg
/home/user/helen/trainset/100040721_1.jpg
/home/user/helen/trainset/100040721_2.jpg
/home/user/helen/trainset/1002681492_1.jpg

annotation_train.txt の内容例

/home/user/helen/trainset/100032540_1.pts
/home/user/helen/trainset/100040721_1.pts
/home/user/helen/trainset/100040721_2.pts
/home/user/helen/trainset/1002681492_1.pts

facemark オブジェクトの作成

/*create the facemark instance*/
FacemarkLBF::Params params;
params.model_filename = "helen.model"; // the trained model will be saved using this filename
Ptr<Facemark> facemark = FacemarkLBF::create(params);

カスタム顔検出関数の設定

まず、独自の顔検出関数を作成する必要がある。カスタムパラメータを保存するために struct を作成する必要があるかもしれない。あるいは、これらのパラメータを myDetector 関数内にハードコードしてしまってもよい。

struct Conf {
cv::String model_path;
double scaleFactor;
Conf(cv::String s, double d){
model_path = s;
scaleFactor = d;
face_detector.load(model_path);
};
CascadeClassifier face_detector;
};
bool myDetector(InputArray image, OutputArray faces, Conf *conf){
Mat gray;
if (image.channels() > 1)
cvtColor(image, gray, COLOR_BGR2GRAY);
else
gray = image.getMat().clone();
equalizeHist(gray, gray);
std::vector<Rect> faces_;
conf->face_cascade.detectMultiScale(gray, faces_, conf->scaleFactor, 2, CASCADE_SCALE_IMAGE, Size(30, 30) );
Mat(faces_).copyTo(faces);
return true;
}

次のスニペットは、カスタム検出器を facemark オブジェクトに設定し、それを使って顔を検出する方法を示している。一部の facemark オブジェクトは学習プロセス中に顔検出器を使用する場合があることに留意すること。

Conf config("../data/lbpcascade_frontalface.xml", 1.4);
facemark->setFaceDetector(myDetector, &config); // we must guarantee proper lifetime of "config" object

以下は、ユーザー定義の顔検出関数を使って顔を検出するためのスニペットである。

Mat img = imread("../data/himym3.jpg");
std::vector<cv::Rect> faces;
facemark->getFaces(img, faces, config);
for(int j=0;j<faces.size();j++){
cv::rectangle(img, faces[j], cv::Scalar(255,0,255));
}
imshow("result", img);
waitKey(0);

facemark オブジェクトの学習

  • まず、学習パラメータを設定する必要がある
    params.n_landmarks = 68; // number of landmark points
    params.initShape_n = 10; // number of multiplier for make data augmentation
    params.stages_n=5; // amount of refinement stages
    params.tree_n=6; // number of tree in the model for each landmark point
    params.tree_depth=5; //he depth of decision tree
    facemark = FacemarkLBF::create(params);
  • そして次に、用意したデータセットからファイルリストを読み込む必要がある。
    std::vector<String> images_train;
    std::vector<String> landmarks_train;
    loadDatasetList("images_train.txt","annotation_train.txt",images_train,landmarks_train);
  • 次のステップは、学習サンプルを facemark オブジェクトに追加することである。
    Mat image;
    std::vector<Point2f> facial_points;
    for(size_t i=0;i<images_train.size();i++){
    image = imread(images_train[i].c_str());
    loadFacePoints(landmarks_train[i],facial_points);
    facemark->addTrainingSample(image, facial_points);
    }
  • 学習処理を実行する
    /*train the Algorithm*/
    facemark->training();

学習済みモデルを用いて与えられた画像から顔のランドマークを検出する。

  • まず最初に、学習済みモデルを読み込む。事前学習済みモデルはこのリンクからダウンロードすることもできる https://raw.githubusercontent.com/kurnianggoro/GSOC2017/master/data/lbfmodel.yaml
    facemark->loadModel(params.model_filename);
  • 顔を検出する
    facemark->getFaces(img, faces, config);
  • フィッティング処理を実行する
    std::vector<std::vector<Point2f> > landmarks;
    facemark->fit(img, faces, landmarks);
  • 結果を表示する
    for(int j=0;j<faces.size();j++){
    face::drawFacemarks(img, landmarks[j], Scalar(0,0,255));
    }
    imshow("result", img);
    waitKey(0);