OpenCV 4.12.0
开源计算机视觉
加载中...
搜索中...
无匹配项
使用 Facemark API

目标

本教程将帮助您:

  • 创建一个 Facemark 对象。
  • 为 facemark 算法设置用户自定义的人脸检测器
  • 训练该算法。
  • 使用训练好的模型从给定图像中检测面部特征点。

准备工作

在继续本教程之前,您应该下载面部特征点检测的数据集。我们建议您下载 HELEN 数据集,该数据集可以在 http://www.ifp.illinois.edu/~vuongle2/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 对象

/*创建 facemark 实例*/
FacemarkLBF::Params params;
params.model_filename = "helen.model"; // 训练好的模型将使用此文件名保存
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); // 我们必须保证 "config" 对象的正确生命周期

这是使用用户自定义的人脸检测器函数检测人脸的代码片段。

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; // 地标点的数量
    params.initShape_n = 10; // 用于数据增强的乘数
    params.stages_n=5; // 细化阶段的数量
    params.tree_n=6; // 每个地标点模型中的树数量
    params.tree_depth=5; // 决策树的深度
    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);
    }
  • 执行训练过程
    /*训练算法*/
    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);