前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >OpenCV基于Landmark实现人脸交换

OpenCV基于Landmark实现人脸交换

作者头像
OpenCV学堂
发布2018-07-26 10:37:31
1.2K0
发布2018-07-26 10:37:31
举报

OpenCV基于Landmark实现人脸交换

川剧是中国最知名的戏曲剧种之一,变脸是川剧表演的特技之一,在对象传承上有着严格的师门派别。有点扯远啦,回来!其实主要是我们今天要用OpenCV干的事情跟这个有点关系,OpenCV基于Landmark实现人脸关键点提取,对结果善加利用可以实现人脸交换,对特定对象施加变脸术。OpenCV开发者不学川剧也一样可以给各种人变脸,当然前提是会写代码,会做OpenCV。首先简单说一下原理与流程。

一:原理与流程

基本原理是利用OpenCV的级联检测器实现人脸检测然后基于Landmak的LBF模型实现人脸68个关键点提取,基于关键点数据实现三角剖分与维诺图计算,经过几何变换之后得到mask区域,再利用OpenCV无缝克隆算法相关API实现换脸。整个工作流程如下:

二:代码实现

1.创建Landmark关键点检测器

// 人脸检测与Landmark68个关键点检测
CascadeClassifier face_cascade;
face_cascade.load(cascade_name);
FacemarkLBF::Params params;
params.n_landmarks = 68; // 68个标注点
params.initShape_n = 10;
params.stages_n = 5; // 算法的5个强化步骤
params.tree_n = 6; // 模型中每个标注点结构树 数目
params.tree_depth = 5; // 决策树深度

// 创建LBF landmark 检测器
Ptr<FacemarkLBF> facemark = FacemarkLBF::create(params);
facemark->setFaceDetector((FN_FaceDetector)myDetector, &face_cascade);
facemark->loadModel(modelfile_name);
cout << "Loaded model" << endl;

2.Landmark关键点检测

//vector to store the faces detected in the image
vector<Rect> faces1, faces2;
vector< vector<Point2f> > shape1, shape2;

//Detect faces in the current image
float ratio1 = (float)img1.cols / (float)img1.rows;
float ratio2 = (float)img2.cols / (float)img2.rows;
resize(img1, img1, Size((int)(640 * ratio1), (int)(640 * ratio1)), 0, 0, INTER_LINEAR_EXACT);
resize(img2, img2, Size((int)(640 * ratio2), (int)(640 * ratio2)), 0, 0, INTER_LINEAR_EXACT);

Mat img1Warped = img2.clone();
facemark->getFaces(img1, faces1);
facemark->getFaces(img2, faces2);

//Initialise the shape of the faces
facemark->fit(img1, faces1, shape1);
facemark->fit(img2, faces2, shape2);

3.三角剖分变换

vector<Point2f> points1 = shape1[z];
vector<Point2f> points2 = shape2[z];
img1.convertTo(img1, CV_32F);
img1Warped.convertTo(img1Warped, CV_32F);
// Find convex hull
vector<Point2f> boundary_image1;
vector<Point2f> boundary_image2;
vector<int> index;
convexHull(Mat(points2), index, false, false);
for (size_t i = 0; i < index.size(); i++)
{
    boundary_image1.push_back(points1[index[i]]);
    boundary_image2.push_back(points2[index[i]]);
}
// Triangulation for points on the convex hull
vector< vector<int> > triangles;
Rect rect(0, 0, img1Warped.cols, img1Warped.rows);
divideIntoTriangles(rect, boundary_image2, triangles);
// Apply affine transformation to Delaunay triangles
for (size_t i = 0; i < triangles.size(); i++)
{
    vector<Point2f> triangle1, triangle2;
    // Get points for img1, img2 corresponding to the triangles
    for (int j = 0; j < 3; j++)
    {
        triangle1.push_back(boundary_image1[triangles[i][j]]);
        triangle2.push_back(boundary_image2[triangles[i][j]]);
    }
    warpTriangle(img1, img1Warped, triangle1, triangle2);
}

4.计算与模板生成

// 计算与生成模板
vector<Point> hull;
for (size_t i = 0; i < boundary_image2.size(); i++)
{
    Point pt((int)boundary_image2[i].x, (int)boundary_image2[i].y);
    hull.push_back(pt);
}
Mat mask = Mat::zeros(img2.rows, img2.cols, img2.depth());
fillConvexPoly(mask, &hull[0], (int)hull.size(), Scalar(255, 255, 255));

5.无缝克隆

//    无缝克隆 
Rect r = boundingRect(boundary_image2);
Point center = (r.tl() + r.br()) / 2;
Mat output;
img1Warped.convertTo(img1Warped, CV_8UC3);
seamlessClone(img1Warped, img2, mask, center, output, NORMAL_CLONE);
imshow("Face_Swapped", output);
imwrite("D:/face_swap_demo.png", output);

三:运行效果

原图一

原图二

人脸交换结果

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-05-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 OpenCV学堂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • OpenCV基于Landmark实现人脸交换
  • 一:原理与流程
  • 二:代码实现
  • 三:运行效果
相关产品与服务
人脸识别
腾讯云神图·人脸识别(Face Recognition)基于腾讯优图强大的面部分析技术,提供包括人脸检测与分析、比对、搜索、验证、五官定位、活体检测等多种功能,为开发者和企业提供高性能高可用的人脸识别服务。 可应用于在线娱乐、在线身份认证等多种应用场景,充分满足各行业客户的人脸属性识别及用户身份确认等需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档