opengl 实现瘦脸等脸部微调
文章目录
- 美颜瘦脸
- 先看效果
- 先上源码
- 实现
- 识别人脸并定位特征点
- 人脸分割
- 瘦脸变形
- 像素偏移后结果
- 去掉特征点后结果
美颜瘦脸
在这个靠脸吃饭的时代,有张漂亮的脸蛋无疑会令你加分不少;那万一天生的颜值不够怎么办呢?。。。还有美颜来拯救。
现在很多相机以及大多数修图软件都提供了瘦脸的功能。现在主流的瘦脸功能都是基于opengl来完成的。
先看效果
原图:
瘦脸:
很明显下面的照片要比上面的照片的脸要瘦了很多。
下面一步步去实现这些功能。
先上源码
VS2019的项目,环境完整,可直接运行
实现
识别人脸并定位特征点
用dlib或者face++或者自己训练个神经网络去识别出特征点。
这里我用dlib 识别出特征点
初始化dlib:
dlib::frontal_face_detector detector;dlib::shape_predictor pose_model;std::string facemodel = "./model/shape_predictor_68_face_landmarks.dat";detector = dlib::get_frontal_face_detector();dlib::deserialize(facemodel) >> pose_model;
识别人脸并保存特征点
dlib::cv_image<dlib::bgr_pixel> cimg(src);std::vector<dlib::rectangle> faces = detector(cimg); // Detect facesdlib::full_object_detection shape; // Find the pose of one facefacelandmarks.clear();if (faces.size() > 0) {shape = pose_model(cimg, faces[0]);facerect = cv::Rect(cv::Point2i(faces[0].left(), faces[0].top()), cv::Point2i(faces[0].right() + 1, faces[0].bottom() + 1));for (int i = 0; i < 68; i++) {facelandmarks.push_back(cv::Point2f(shape.part(i).x(), shape.part(i).y()));}}else {return -1;}
识别的特征点如下 共68个:
人脸分割
这里为了简单只将图片分为26个三角形。若想效果更平滑,可以将图片分的更细。
//人脸分割cv::Point2f LALL0 = cv::Point2f(-1.0f, -1.0f);cv::Point2f LALL1 = cv::Point2f(-1.0f, 1.0f);cv::Point2f LALL2 = cv::Point2f(1.0f, 1.0f);cv::Point2f LALL3 = cv::Point2f(1.0f, -1.0f);cv::Point2f LFace30 = cv::Point2f(facelandmarks[30].x * 2.0 / width - 1.0, (height - facelandmarks[30].y) * 2.0 / height - 1.0);cv::Point2f LFace3 = cv::Point2f(facelandmarks[3].x * 2.0 / width - 1.0, (height - facelandmarks[3].y) * 2.0 / height - 1.0);cv::Point2f LFace4 = cv::Point2f(facelandmarks[4].x * 2.0 / width - 1.0, (height - facelandmarks[4].y) * 2.0 / height - 1.0);cv::Point2f LFace5 = cv::Point2f(facelandmarks[5].x * 2.0 / width - 1.0, (height - facelandmarks[5].y) * 2.0 / height - 1.0);cv::Point2f LFace6 = cv::Point2f(facelandmarks[6].x * 2.0 / width - 1.0, (height - facelandmarks[6].y) * 2.0 / height - 1.0);cv::Point2f LFace7 = cv::Point2f(facelandmarks[7].x * 2.0 / width - 1.0, (height - facelandmarks[7].y) * 2.0 / height - 1.0);cv::Point2f LFace8 = cv::Point2f(facelandmarks[8].x * 2.0 / width - 1.0, (height - facelandmarks[8].y) * 2.0 / height - 1.0);cv::Point2f LFace9 = cv::Point2f(facelandmarks[9].x * 2.0 / width - 1.0, (height - facelandmarks[9].y) * 2.0 / height - 1.0);cv::Point2f LFace10 = cv::Point2f(facelandmarks[10].x * 2.0 / width - 1.0, (height - facelandmarks[10].y) * 2.0 / height - 1.0);cv::Point2f LFace11 = cv::Point2f(facelandmarks[11].x * 2.0 / width - 1.0, (height - facelandmarks[11].y) * 2.0 / height - 1.0);cv::Point2f LFace12 = cv::Point2f(facelandmarks[12].x * 2.0 / width - 1.0, (height - facelandmarks[12].y) * 2.0 / height - 1.0);cv::Point2f LFace13 = cv::Point2f(facelandmarks[13].x * 2.0 / width - 1.0, (height - facelandmarks[13].y) * 2.0 / height - 1.0);cv::Point2f VALL0 = cv::Point2f(0.0f, 1.0f);cv::Point2f VALL1 = cv::Point2f(0.0f, 0.0f);cv::Point2f VALL2 = cv::Point2f(1.0f, 0.0f);cv::Point2f VALL3 = cv::Point2f(1.0f, 1.0f);cv::Point2f VFace30 = cv::Point2f(facelandmarks[30].x / width, facelandmarks[30].y / height);cv::Point2f VFace3 = cv::Point2f(facelandmarks[3].x / width, facelandmarks[3].y / height);cv::Point2f VFace4 = cv::Point2f(facelandmarks[4].x / width, facelandmarks[4].y / height);cv::Point2f VFace5 = cv::Point2f(facelandmarks[5].x / width, facelandmarks[5].y / height);cv::Point2f VFace6 = cv::Point2f(facelandmarks[6].x / width, facelandmarks[6].y / height);cv::Point2f VFace7 = cv::Point2f(facelandmarks[7].x / width, facelandmarks[7].y / height);cv::Point2f VFace8 = cv::Point2f(facelandmarks[8].x / width, facelandmarks[8].y / height);cv::Point2f VFace9 = cv::Point2f(facelandmarks[9].x / width, facelandmarks[9].y / height);cv::Point2f VFace10 = cv::Point2f(facelandmarks[10].x / width, facelandmarks[10].y / height);cv::Point2f VFace11 = cv::Point2f(facelandmarks[11].x / width, facelandmarks[11].y / height);cv::Point2f VFace12 = cv::Point2f(facelandmarks[12].x / width, facelandmarks[12].y / height);cv::Point2f VFace13 = cv::Point2f(facelandmarks[13].x / width, facelandmarks[13].y / height);float vertices[] = {//----位置---- ---纹理---LALL0.x, LALL0.y, 0.0f, VALL0.x, VALL0.y,LALL1.x, LALL1.y, 0.0f, VALL1.x, VALL1.y,LALL2.x, LALL2.y, 0.0f, VALL2.x, VALL2.y,LALL3.x, LALL3.y, 0.0f, VALL3.x, VALL3.y,LFace30.x, LFace30.y, 0.0f, VFace30.x, VFace30.y,LFace3.x, LFace3.y, 0.0f, VFace3.x, VFace3.y,LFace4.x, LFace4.y, 0.0f, VFace4.x, VFace4.y,LFace5.x, LFace5.y, 0.0f, VFace5.x, VFace5.y,LFace6.x, LFace6.y, 0.0f, VFace6.x, VFace6.y,LFace7.x, LFace7.y, 0.0f, VFace7.x, VFace7.y,LFace8.x, LFace8.y, 0.0f, VFace8.x, VFace8.y,LFace9.x, LFace9.y, 0.0f, VFace9.x, VFace9.y,LFace10.x, LFace10.y, 0.0f, VFace10.x, VFace10.y,LFace11.x, LFace11.y, 0.0f, VFace11.x, VFace11.y,LFace12.x, LFace12.y, 0.0f, VFace12.x, VFace12.y,LFace13.x, LFace13.y, 0.0f, VFace13.x, VFace13.y};unsigned int indices[] = {0,1,5,5,1,4,4,1,2,2,4,15,15,2,3,0,5,6,0,6,7,0,7,8,0,8,9,0,9,10,0,10,3,3,10,11,3,11,12,3,12,13,3,13,14,3,14,15,4,5,6,4,6,7,4,7,8,4,8,9,4,9,10,4,10,11,4,11,12,4,12,13,4,13,14,4,14,15};
瘦脸变形
只需要将图中标记的点按照箭头方向拖动,即可实现瘦脸,为了不显得太过于尖锐,我们将范围包括到附近的几个点。
关于像素偏移调节,可以参考这篇文章
shader:
#version 330 core
precision mediump float;in vec2 TexCoord;
out vec4 outColor;
uniform sampler2D inputTexture;uniform float face5x;
uniform float face5y;vec2 stretchFun(vec2 textureCoord, vec2 originPosition, vec2 targetPosition, float radius,float curve)
{vec2 direction = targetPosition - originPosition;float infect = distance(textureCoord, originPosition)/radius;infect =1.0 - pow(infect,curve);infect = clamp(infect,0.0,1.0);vec2 offset = direction * infect;vec2 result = textureCoord - offset;return result;
}void main(){vec2 A1 = vec2(face5x,face5y);vec2 A2 = vec2(face5x+0.02f,face5y + 0.01f);vec2 TexCoord2 = stretchFun(TexCoord,A1,A2,0.19f,2.0f);vec3 tmpColor = texture(inputTexture, TexCoord2).rgb;outColor = vec4(tmpColor,1.0f);
}
像素偏移后结果
去掉特征点后结果
完成
opengl 实现瘦脸等脸部微调相关推荐
- OpenGL ES 实现瘦脸大眼效果
该原创文章首发于微信公众号:字节流动 旧文中我们用 OpenGL 给小姐姐实现了瘦身和大长腿效果,结果小姐姐眯着眼睛.嘟着嘴说,我需要瘦身和大长腿效果吗? 笔者若有所思地看着她的眼睛和脸庞,终于弄明白 ...
- matlab瘦脸大眼的代码,OpenGL ES 实现瘦脸大眼效果
Hi 小姐姐,这是你要的大眼瘦脸效果? 该原创文章首发于微信公众号:字节流动 旧文中我们用 OpenGL 给小姐姐实现了瘦身和大长腿效果,结果小姐姐眯着眼睛.嘟着嘴说,我需要瘦身和大长腿效果吗? 笔者 ...
- Python实现PhotoShop人脸液化变形效果
在PhotoShop中,我们经常利用液化工具的向前工具来对人脸进行形变处理,例如瘦脸.放大眼睛等常规P图操作. 瘦脸与眼睛放大可以算作图像局部扭曲算法的一个应用,其参考文献可以追溯至1993年的一篇博 ...
- android对图片提升清晰度,轻颜相机如何提升图片清晰度?
大家都知道,轻颜相机是一款非常优秀的美颜相机软件,拥有时下最流行的滤镜和美颜效果,是众多爱美人士必不可少的美颜工具之一,拍照时支持脸部微调,后期就不用再P,功能十分强大.不过,最近有用户反映,拍出来的 ...
- 在OpenGL中利用shader进行实时瘦脸大眼等脸型微调
在OpenGL中利用shader进行实时瘦脸大眼等脸型微调 在现在这个靠脸吃饭的时代,如果你没有一张瓜子脸一双大眼睛,那还怎么去吃饭呢,而现在一些直播视频App相机应用基本都会有瘦脸大眼效果.本文是在 ...
- OpenGL ES之实现“瘦脸大眼”效果
一."瘦脸效果"的实现 瘦脸效果的实现,是将指定区域内的像素按照一定的规则进行整体偏移,从而形成一种对脸部挤压的效果: 如下所示,BC 表示偏移方向和偏移程度的向量,将圆内的所有像 ...
- 图像滤镜艺术---人脸编辑(五官微调+瘦脸美型)
写本文的目的,实际上是对目前人脸美型这一块技术做个总结,跟大家 分享一下! 目前提到美颜算法,大家都会想到磨皮美白 /大眼瘦脸,实际上做好 美颜这件事情,关乎的不仅仅是这些,还有五官的协调比例等,今天 ...
- 人像瘦脸效果实现(网格液化)——OpenGL实现
一.网格液化形变 1.液化 网格液化形变是指,事先将图片划分成若干个网格,再对其中某一些网格的坐标进行变换,以达到图像形变的效果. 网格可以是四边形,或三角形,在计算机图形当中用三角形 ...
- OpenGL Shader 自动瘦脸与眼睛放大
图像局部扭曲算法有三个:局部缩放(Local Scaling)算法.局部平移(Local Transition)算法和局部旋转(Local Rotation)算法.其中应用局部缩放算法可实现眼睛放大, ...
最新文章
- java 清空一个list数据库_java – JPA EntityManager删除数据库中的所有记录
- 字节跳动简历冷却期_干货 | 字节跳动HR是如何挑选简历的?
- 手机号正则_这20个正则表达式,对你有大帮助,快来Make
- Android之 如何解决ScrollView 和ListView滑动冲突的问题如何解决ScrollView can host only one direct child
- 火狐查看html的隐藏域,IE/火狐/Chrome操作display:none对象所遇问题解答
- 来自IT公司速查手册的各大IT公司薪资和待遇内幕
- 计算机应用基础实操题怎么操,计算机基础实操试题
- python编程语言在线编译手机_groovy在线运行,groovy在线编译,支持手机在线编程写代码 - Groovy教程...
- sql查询重复订单号
- wifi的WPS功能
- Android集合之SparseArray、ArrayMap详解
- IDEA中写代码间距变大报红,报错Cannot resolve symbol
- PS打开时显示程序出错
- 聚类分析及R编程实现
- 我国最高山峰是珠穆朗玛峰:8848m,我现在有一张足够大的纸张,厚度为:0.01m。请问,我折叠多少次,就可 以保证厚度不低于珠穆朗玛峰的高度?
- Windows cmd 进入其他盘
- 评价星星三级样式:好、一般、差
- 国庆西北环游之旅(一大波照骗来袭)
- 003day (css文本、列表、背景相关属性,精灵图的制作)
- 瓦里安、勃林格殷格翰将参展第四届进博会;森世海亚集团中国区总部落地上海 | 医药健闻...
热门文章
- “玩伴女郎”误入学术圈--lena图象的使用数字图像历史上最重要的事件之一
- python画漫画_用Python抓腾讯漫画?
- python模拟微信发红包算法_微信红包的随机算法是怎样实现的?
- XDOJ-车牌限行_分支结构-7
- UGNX Imachining VoluMill动态与高速铣视频教程
- 捂碳星球|换季整理衣橱,衣服该怎么存放和处理?
- 分布式事务--TCC--流程/原理
- 抖音小店无货源店群,我走过最长的路,就是同行的套路!
- Android studio 连接Mysql数据库
- 【线性代数(13)】矩阵的特征值与特征向量含义及性质