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);