Dlib库中提供了正脸人脸关键点检测的接口,这里参考dlib/examples/face_landmark_detection_ex.cpp中的代码,通过调用Dlib中的接口,实现正脸人脸关键点检测的测试代码,测试代码如下:
/* reference: dlib/examples/face_landmark_detection_ex.cpp
This program shows how to find frontal human faces in an image and
estimate their pose. The pose takes the form of 68 landmarks. These are
points on the face such as the corners of the mouth, along the eyebrows, on
the eyes, and so forth
*/
int test_face_landmark()
{
// download: http://dlib.net/files/shape_predictor_68_face_landmarks.dat.bz2
const std::string shape_predictor_68_face_landmarks = "E:/GitCode/Face_Test/src/dlib/data/shape_predictor_68_face_landmarks.dat";
// We need a face detector. We will use this to get bounding boxes for
// each face in an image.
dlib::frontal_face_detector detector = dlib::get_frontal_face_detector();
// And we also need a shape_predictor. This will predict face
// landmark positions given an image and face bounding box
dlib::shape_predictor sp;
dlib::deserialize(shape_predictor_68_face_landmarks) >> sp;
std::vector images{ "1.jpg", "2.jpg", "3.jpg", "4.jpeg", "5.jpeg", "6.jpg", "7.jpg", "8.jpg", "9.jpg", "10.jpg",
"11.jpeg", "12.jpg", "13.jpeg", "14.jpg", "15.jpeg", "16.jpg", "17.jpg", "18.jpg", "19.jpg", "20.jpg" };
std::vector count_faces{ 1, 2, 6, 0, 1, 1, 1, 2, 1, 1,
1, 1, 1, 1, 1, 1, 1, 0, 8, 2 };
std::string path_images{ "E:/GitCode/Face_Test/testdata/" };
if (images.size() != count_faces.size()) {
fprintf(stderr, "their size that images and count_faces are mismatch\n");
return -1;
}
for (int i = 0; i < images.size(); i++) {
cv::Mat matSrc = cv::imread(path_images + images[i], 1);
if (matSrc.empty()) {
fprintf(stderr, "read image error: %s\n", images[i].c_str());
return -1;
}
dlib::array2d img;
dlib::load_image(img, path_images + images[i]);
// Make the image larger so we can detect small faces.
pyramid_up(img);
// Now tell the face detector to give us a list of bounding boxes
// around all the faces it can find in the image.
std::vector dets = detector(img);
fprintf(stderr, "detect face count: %d, actual face count: %d\n", dets.size(), count_faces[i]);
// Now we will go ask the shape_predictor to tell us the pose of
// each face we detected.
std::vector shapes;
for (unsigned long j = 0; j < dets.size(); ++j) {
dlib::full_object_detection shape = sp(img, dets[j]);
fprintf(stderr, "landmark num: %d\n", shape.num_parts());
dlib::rectangle rect = shape.get_rect();
fprintf(stderr, "rect: left = %d, top = %d, width = %d, height = %d\n", rect.left() / 2, rect.top() / 2, rect.width() / 2, rect.height() / 2);
cv::rectangle(matSrc, cv::Rect(rect.left() / 2, rect.top() / 2, rect.width() / 2, rect.height() / 2), cv::Scalar(0, 255, 0), 2);
for (int pt = 0; pt < shape.num_parts(); pt++) {
cv::circle(matSrc, cv::Point(shape.part(pt).x() / 2, shape.part(pt).y() / 2), 1, cv::Scalar(0, 0, 255), 2);
}
}
std::string save_result = path_images + "_" + images[i];
cv::imwrite(save_result, matSrc);
}
int width = 200;
int height = 200;
cv::Mat dst(height * 5, width * 4, CV_8UC3);
for (int i = 0; i < images.size(); i++) {
std::string input_image = path_images + "_" + images[i];
cv::Mat src = cv::imread(input_image, 1);
if (src.empty()) {
fprintf(stderr, "read image error: %s\n", images[i].c_str());
return -1;
}
cv::resize(src, src, cv::Size(width, height), 0, 0, 4);
int x = (i * width) % (width * 4);
int y = (i / 4) * height;
cv::Mat part = dst(cv::Rect(x, y, width, height));
src.copyTo(part);
}
std::string output_image = path_images + "result.png";
cv::imwrite(output_image, dst);
return 0;
}
执行结果如下图: