当前位置: 首页 > 工具软件 > Flandmark > 使用案例 >

flandmark人脸检测库的用法

魏刚豪
2023-12-01

之前用dlib库检测人脸的68个特征点,虽然特征点比较准确,但如果被检测图片比较大,效率就比较低。而且脸部模型数据文件shape_predictor_68_face_landmarks.dat有95MB太大了。

后来发现flandmark这样一个轻量级的人脸检测库,大概只有5MB左右。检测的特征点少一些,只有8个。不过如果作一般用途,这8个点足够了。下面简单贴出相关代码。
主要参考来自于:http://cmp.felk.cvut.cz/~uricamic/flandmark/

下载的包里有例子,我作了一些修改,libflandmark也在里面。

声明所需的变量

#include "libflandmark/flandmark_detector.h"

/*
*    5   1    2   6
*
*
*          0/7
*
*
*       3       4
*
*/
CvHaarClassifierCascade* faceCascade;
FLANDMARK_Model * model;

初始化:

HSFaceFlandmark::HSFaceFlandmark()
{
    char szModuleFilePath[MAX_PATH];
    int n = GetModuleFileNameA(0, szModuleFilePath, MAX_PATH); //获得当前执行文件的路径
    szModuleFilePath[ strrchr(szModuleFilePath, '\\') - szModuleFilePath + 1 ] = 0;//将最后一个"\\"后的字符置为0
    DBG("================= '%s'\n", szModuleFilePath);

    char faceCascadeFilename[MAX_PATH];
    char flandmarkmodelFilename[MAX_PATH];
    sprintf(faceCascadeFilename, "%s/haarcascade_frontalface_alt.xml",szModuleFilePath);
    sprintf(flandmarkmodelFilename, "%s/flandmark_model.dat",szModuleFilePath);

    // Haar Cascade file, used for Face Detection.
    //char faceCascadeFilename[] = "./haarcascade_frontalface_alt.xml";
    // Load the HaarCascade classifier for face detection.

    faceCascade = (CvHaarClassifierCascade*)cvLoad(faceCascadeFilename, 0, 0, 0);
    if( !faceCascade )
    {
        DBG("Couldnt load Face detector '%s'\n", faceCascadeFilename);
    }

    model = flandmark_init(flandmarkmodelFilename);
    if (model == 0)
    {
        DBG("Structure model wasn't created. Corrupted file flandmark_model.dat?\n");
    }
}

8个关键点检测的API

int detectFaceInImage(IplImage *orig, cv::Mat& img, double *landmarks)
{
    IplImage frame = IplImage(img);
    IplImage *input = cvCreateImage(cvSize(frame.width, frame.height), IPL_DEPTH_8U, 1);
    cvConvertImage(&frame, input);

    int bbox[4] = {0};
    // Smallest face size.
    CvSize minFeatureSize = cvSize(80, 80);
    int flags =  CV_HAAR_DO_CANNY_PRUNING;
    // How detailed should the search be.
    float search_scale_factor = 1.1f;
    CvMemStorage* storage;
    CvSeq* rects;
    int nFaces;

    storage = cvCreateMemStorage(0);
    cvClearMemStorage(storage);

    // Detect all the faces in the greyscale image.
    rects = cvHaarDetectObjects(input, faceCascade, storage, search_scale_factor, 2, flags, minFeatureSize);
    nFaces = rects->total;

    for (int iface = 0; iface < (rects ? nFaces : 0); ++iface)
    {
        CvRect *r = (CvRect*)cvGetSeqElem(rects, iface);

        bbox[0] = r->x;
        bbox[1] = r->y;
        bbox[2] = r->x + r->width;
        bbox[3] = r->y + r->height;

        flandmark_detect(input, bbox, model, landmarks);

        // display landmarks
//        cvRectangle(orig, cvPoint(bbox[0], bbox[1]), cvPoint(bbox[2], bbox[3]), CV_RGB(255,0,0) );
//        cvRectangle(orig, cvPoint(model->bb[0], model->bb[1]), cvPoint(model->bb[2], model->bb[3]), CV_RGB(0,0,255) );
//        cvCircle(orig, cvPoint((int)landmarks[0], (int)landmarks[1]), 3, CV_RGB(0, 0,255), CV_FILLED);
//        for (int i = 2; i < 2*model->data.options.M; i += 2)
//        {
//            cvCircle(orig, cvPoint(int(landmarks[i]), int(landmarks[i+1])), 3, CV_RGB(255,0,0), CV_FILLED);
//        }
    }
//    if (nFaces > 0)
//    {
//        DBG("Faces detected: %d; \n", nFaces);
//    }

    cvReleaseMemStorage(&storage);
    cvReleaseImage(&input);
    return nFaces;
}

用法:

//cv::Mat& img 这里就是需要检测人脸的图片,我这里都是用cv::Mat作为输入格式

IplImage frameRet = IplImage(img);
//这里存放检测到人脸8个特征点的坐标
double landmarks[MAX_LANDMARK_POINT * 2] = {0};

int faceNum = detectFaceInImage(&frameRet, img, landmarks);

if(faceNum > 0)
{
    for (int i = 0; i < 2 * MAX_LANDMARK_POINT; i += 2)
    {
        //cv::circle(retImg, cvPoint(int(landmarks[i]), int(landmarks[i+1])), 2, CV_RGB(255,0,0), CV_FILLED);
    }
}
//我这里只需要8个点坐标,frameRet其实没什么用
 类似资料: