记录--从AI到美颜全流程讲解
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助https://img2020.cnblogs.com/blog/2149129/202107/2149129-20210719135854680-672185839.jpg
美颜和短视频
美颜相关APP可以说是现在手机上的必备的软件,例如抖音,快手,拍出的“照骗”和视频不加美颜效果,估计没有人敢传到网上。很多人一直好奇美颜类APP是如何开发出来的。本文就大致讲一下在Android上如何实现实时修改唇色效果。其它功能例如美白,腮红都是类似的原理
下图的唇色修改效果就是想实现的功能
https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/7/29/173993eccfb11acf~tplv-t2oaga2asx-zoom-in-crop-mark:4536:0:0:0.awebp
美颜原理
美颜是的基本原理就是深度学习加计算机图形学。深度学习用来人脸检测和人脸关键点检测。计算机图形学用来磨皮,瘦脸和画妆容。一般在Android上使用OpenGLES,IOS为Metal。由于计算机图形学概念较多和复杂,本文中用Android的Canvas替代。
人脸检测 & 人脸关键点
[*]人脸检测指的是对图片或者视频流中的人脸进行检测,并定位到图片中的人脸。
[*]人脸关键点检测是对人脸中五官和脸的轮廓进行关键点定位,一般情况下它紧接在人脸检测后。
https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/7/29/173993f52f9d92ec~tplv-t2oaga2asx-zoom-in-crop-mark:4536:0:0:0.awebp
我们将使用TengineKit来实现实时大红唇效果。
TengineKit
免费移动端实时人脸212关键点SDK。是一个易于集成的人脸检测和人脸关键点SDK。它可以在各种手机上以非常低的延迟运行。
github.com/OAID/Tengin…
https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/7/29/17399402c12f869d~tplv-t2oaga2asx-zoom-in-crop-mark:4536:0:0:0.awebp
实现口红效果
配置 Gradle
Project中的build.gradle添加
repositories {
...
mavenCentral()
...
}
allprojects {
repositories {
...
mavenCentral()
...
}
}主Module中的build.gradle添加 dependencies {
...
implementation 'com.tengine.android:tenginekit:1.0.5'
...
}配置 manifests
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>相对于上篇用摄像头来做效果,本文用gif图来代替摄像头的输入的视频流,如果想用摄像头实现,可以参考:
用开源212点人脸关键点实现Android人脸实时打码 zhuanlan.zhihu.com/p/161038093
处理Gif传过来的图片流
首先我们先初始化TengineKit:
[*]选用normal处理模式
[*]打开人脸检测和人脸关键点功能
[*]设置图片流格式为RGBA
[*]设置输入图片流的宽高,此处为gif图的预览宽高
[*]设置输出图片流的宽高,此处为GifImageView的宽高,此处和gif一致,所以用gif图的宽高代替
com.tenginekit.Face.init(getBaseContext(),
AndroidConfig.create()
.setNormalMode()
.openFunc(AndroidConfig.Func.Detect)
.openFunc(AndroidConfig.Func.Landmark)
.setInputImageFormat(AndroidConfig.ImageFormat.RGBA)
.setInputImageSize(facingGif.getGifWidth(), facingGif.getGifHeight())
.setOutputImageSize(facingGif.getGifWidth(), facingGif.getGifHeight())
);通过关键点得到嘴唇的形状
Path getMouthLandmarks(FaceLandmarkInfo fi){ Path outPath = new Path(); outPath.moveTo(fi.landmarks.get(180).X,fi.landmarks.get(180).Y); for(int i = 180; i < 189; i++){ outPath.lineTo( <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>fi.landmarks.get(i).X, <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>fi.landmarks.get(i).Y ); } for(int i = 204; i >= 196; i--){ outPath.lineTo( <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>fi.landmarks.get(i).X, <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>fi.landmarks.get(i).Y ); } outPath.close(); Path inPath = new Path(); inPath.moveTo(fi.landmarks.get(180).X,fi.landmarks.get(180).Y); for(int i = 195; i >= 188; i--){ inPath.lineTo( <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>fi.landmarks.get(i).X, <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>fi.landmarks.get(i).Y ); } for(int i = 204; i80) { alpha = (int) (alpha * 0.9f + 0.5f); } alpha = (int) (Color.alpha(color) * ((float) alpha / 255))0){ faceLandmarks = faceDetect.landmark2d(); if(faceLandmarks != null){ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>for (int i = 0; i < faceLandmarks.size(); i++) { <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/> Path m_p = getMouthLandmarks(faceLandmarks.get(i)); <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/> LipDraw.drawLipPerfect(canvas, m_p, Color.WHITE, 100); <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>} } } return out_bitmap; } });效果对比
https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/7/29/173994149c845c09~tplv-t2oaga2asx-zoom-in-crop-mark:4536:0:0:0.awebp
https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/7/29/17399416d05cf3e4~tplv-t2oaga2asx-zoom-in-crop-mark:4536:0:0:0.awebp
https://juejin.cn/post/6855129006367309832
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
https://img2020.cnblogs.com/blog/2149129/202107/2149129-20210719144042684-15122820.jpg
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
页:
[1]