• 基于Landmark的人脸对齐以及裁剪方法


     利用Landmarks进行人脸对齐裁剪是人脸检测中重要的一个步骤。效果如下图所示:

    基本思路为:

    a.人脸检测

      人脸的检测不必多说了,基本Cascade的方式已经很不错了,或者用基于HOG/FHOG的SVM/DPM等。这些在OpenCVDLIB都有。

    b.在检测到的人脸上进行Landmarks检测,获得一系列的Landmark点

      对齐算法很多,特别是前几年人脸对齐获得了巨大的成功。

      [1].One Millisecond Face Alignment with an Ensemble of Regression Trees by Vahid Kazemi and Josephine Sullivan, CVPR 2014

      [2].人脸对齐SDM原理----Supervised Descent Method and its Applications to Face Alignment

    c.利用检测到的Landmarks和模板的Landmarks,计算仿射矩阵H;然后利用H,直接计算得到对齐后的图像。

      直接上代码:

    #include <opencv2/opencv.hpp>
    using namespace cv;
    //原始图像大小
    #define IMAGE_WIDTH 640
    #define IMAGE_HEIGHT 480
    //输出的图像大小(裁剪后的)
    #define IMAGE_WIDTH_STD 90
    #define IMAGE_HEIGHT_STD 90
    
    #define LANDMARK_SIZE 8//对齐点的个数
    #define LANDMARK_SIZE_DOUBLE 16//对齐点个数的两倍
    
    Point2f srcTri[LANDMARK_SIZE];//对齐点的Point2f数组,检测到的人脸对齐点,注意这里是基于原始图像的坐标点
    Point2f destTri[LANDMARK_SIZE];//对齐点的Point2f数组,模板的Landmarks,注意这是一个基于输出图像大小尺寸的坐标点
                                   //对齐点的double数组
    double template_landmark[LANDMARK_SIZE_DOUBLE] = {
        0.0792396913815, 0.339223741112, 0.0829219487236, 0.456955367943,
        0.0967927109165, 0.575648016728, 0.122141515615, 0.691921601066,
        0.168687863544, 0.800341263616, 0.239789390707, 0.895732504778,
        0.325662452515, 0.977068762493, 0.422318282013, 1.04329000149,
        0.531777802068, 1.06080371126, 0.641296298053, 1.03981924107,
        0.738105872266, 0.972268833998, 0.824444363295, 0.889624082279,
        0.894792677532, 0.792494155836, 0.939395486253, 0.681546643421,
        0.96111933829, 0.562238253072, 0.970579841181, 0.441758925744
    };
    
    
    int main()
    {
        VideoCapture vcap;
        if (!vcap.open(0))
        {
            return 0;
        }
    
        for (int i = 0; i < LANDMARK_SIZE; i++)
        {
            srcTri[i] = Point2f(template_landmark[i * 2] * 90 + IMAGE_HEIGHT / 2, template_landmark[i * 2 + 1] * 90 + IMAGE_WIDTH / 2);
            destTri[i] = Point2f(template_landmark[i * 2] * IMAGE_HEIGHT_STD, template_landmark[i * 2 + 1] * IMAGE_WIDTH_STD);
        }
        //Mat warp_mat = getAffineTransform( srcTri, destTri );//使用仿射变换,计算H矩阵
        Mat warp_mat = cv::estimateRigidTransform(srcTri, destTri, false);//使用相似变换,不适合使用仿射变换,会导致图像变形
        Mat frame;
        Mat warp_frame(200, 200, CV_8UC3);
        while (1)
        {
            vcap >> frame;
            warpAffine(frame, warp_frame, warp_mat, warp_frame.size());//裁剪图像
    
            imshow("frame", frame);//显示原图像
            imshow("warp_frame", warp_frame);//显示裁剪后得到的图像
    
            waitKey(10);
        }
        return 0;
    }

     效果图:

    注意以上效果非真实的对齐裁剪的效果。实际的对齐裁剪可以做的很好。

  • 相关阅读:
    Android 蓝牙4.0 BLE (onServicesDiscovered 返回 status 是 129,133时)
    Android 读取蓝牙设备信息开发
    Android RxJava
    Android 通信 EventBus
    数据仓库基础介绍
    探索SQL Server元数据(三):索引元数据
    探索SQL Server元数据(二)
    MySQL常见备份方案
    hivesql优化的深入解析
    mysql执行计划看是否最优
  • 原文地址:https://www.cnblogs.com/cv-pr/p/5438351.html
Copyright © 2020-2023  润新知