今天是2018年第一天,首先真诚地祝福各位同行朋友元旦快乐,在未来开发之路不断进步,为促进公司发展壮大、为提升人们生活品质以实现自我价值。言归正传,继续探讨Android移动端的图片处理,使用NDK实现人脸抠图。天天P图、美图秀秀们都具备P图技能,让女孩秒变网红脸、明星脸,这技能令人爱不释手,简直是女神打印机。那么到底如何实现这变脸大法呢?经过自己研究,总结出三个步骤:人脸检测—>人脸抠图—>人脸替换。

1、人脸检测

        利用Android系统自带人脸检测API,只需要创建FaceDetector,传入图片宽度、高度以及检测人脸最大数这三个参数:

faceDetector = new FaceDetector(mFace.getWidth(), mFace.getHeight(), N_MAX);

然后开始人脸检测,传入图片以及人脸数组:

int nFace = faceDetector.findFaces(mFace, face);

2、人脸抠图

根据人脸检测结果,得到人脸的眼坐标与中间坐标,计算出人脸矩形:left、top、right、bottom,最后根据这四个坐标点进行人脸抠图。先看下Java版本的方法:

    public int[] extractFaceByJava(Bitmap bitmap, int left, int top, int right, int bottom){int width = bitmap.getWidth();int height = bitmap.getHeight();int mWidth = right-left;int mHeight = bottom-top;int[] pixels = new int[width*height];int[] mPixels = new int[mWidth*mHeight];//获取bitmap的所有pixel像素点bitmap.getPixels(pixels, 0, width, 0, 0, width, height);//获取ROI(区域遍历)for(int x=left; x<right; x++){for(int y=top; y<bottom; y++){mPixels[(y-top)*mWidth + (x-left)] = pixels[y*width + x];}}return mPixels;}

下面是NDK版本的方法,供Java层调用:

jintArray
Java_com_frank_image_ImageUtil_extractFace(JNIEnv *env, jobject, jobject bitmap, jint left, jint top, jint right, jint bottom){AndroidBitmapInfo bitmapInfo;int *pixelColor;int x, y;int mWidth = right-left;int mHeight = bottom-top;jint *mPixels = new jint[mWidth*mHeight];if (AndroidBitmap_getInfo(env, bitmap, &bitmapInfo) < 0){LOGI("AndroidBitmap_getInfo error...");return NULL;}if(AndroidBitmap_lockPixels(env, bitmap, (void **) &pixelColor) < 0){LOGI("AndroidBitmap_lockPixels error...");return NULL;}//获取ROI(区域遍历)for(y=top; y<bottom; y++){for(x=left; x<right; x++){mPixels[(y-top)*mWidth + (x-left)] = *(pixelColor + y*bitmapInfo.width + x);}}AndroidBitmap_unlockPixels(env, bitmap);LOGI("extractFace has done...");jintArray newPixel = env->NewIntArray(mWidth*mHeight);env->SetIntArrayRegion(newPixel, 0, mWidth*mHeight, mPixels);return newPixel;
}

另外,在研究openCV时,发现它提供一个封装好的方法,可以很轻松获取ROI区域:

    /***利用openCV的ROI实现人脸抠图(需要导入openCV库)*/public Bitmap extractFaceByOpenCV(Mat src, int left, int top, int right, int bottom){//创建ROI矩形区域Rect ROI = new Rect(left, top, right-left, bottom-top);//根据原图得到ROI区域Mat roiMat = new Mat(src, ROI);Bitmap bitmap = Bitmap.createBitmap(src.width(), src.height(), Bitmap.Config.ARGB_8888);//Mat转成BitmapUtils.matToBitmap(roiMat, bitmap);return bitmap;}

聊了这么多,中场暂停休息下,看看人脸抠图效果:
  

3、人脸替换

其实人脸替换需要重复第一步,进行人脸检测,然后把目标人脸替换原本人脸。整个过程如下:

    /*** 人脸替换* @return Bitmap*/public Bitmap doExchangeFace(Bitmap src, Bitmap faceBitmap){if(faceBitmap == null){return src;}int nFace = faceDetector.findFaces(src, face);if(nFace > 0){Face f  = face[0];PointF midPoint = new PointF();float dis = f.eyesDistance();f.getMidPoint(midPoint);int dd = (int)(dis);int width = dd * 2;int height = dd * 2 + compensation;faceBitmap = Bitmap.createScaledBitmap(faceBitmap, width, height, true);return extractFaceHelper.exchangeFace(src, faceBitmap, (int)(midPoint.x - dd), (int)(midPoint.y - dd),(int)(midPoint.x + dd), (int)(midPoint.y + dd) + compensation);}return src;}

上面调用的NDK的实现方法:

jobject
Java_com_frank_image_ImageUtil_exchangeFace(JNIEnv *env, jobject, jobject src, jobject face,jint left, jint top, jint right, jint bottom){AndroidBitmapInfo srcInfo, faceInfo;int *srcColor, *faceColor;int x, y;if (AndroidBitmap_getInfo(env, src, &srcInfo) < 0|| AndroidBitmap_getInfo(env, face, &faceInfo) < 0){LOGI("AndroidBitmap_getInfo error...");return NULL;}if(AndroidBitmap_lockPixels(env, src, (void **) &srcColor) < 0|| AndroidBitmap_lockPixels(env, face, (void **) &faceColor) < 0){LOGI("AndroidBitmap_lockPixels error...");return NULL;}for(y=top; y<bottom; y++){for(x=left; x<right; x++){*(srcColor + y*srcInfo.width + x) = *(faceColor + (y-top)*faceInfo.width + (x-left));}}AndroidBitmap_unlockPixels(env, src);AndroidBitmap_unlockPixels(env, face);LOGI("extractFace has done...");return src;
}

由此可见,JNI可以获取Bitmap地址,直接操作Bitmap像素数据,节省内存开销,并且效率比Java方法相对高一点。

人脸替换的效果并不是很理想,因为每个人脸大小不一致,需要根据目标人脸进行压缩,而且这里抠图是矩形人脸,没有无缝替换原本人脸。大家别介意,在这里只为分享实现思路。

图片处理——NDK实现人脸抠图相关推荐

  1. java代码自动抠图_Opencv java实现人脸抠图和行为识别

    基于java的OpenCV环境搭建(Windows平台上ecplise) https://blog..net/qq_32447301/article/details/78494913 https:// ...

  2. ECCV2022 | 网易AI 基于单幅图片的实时高分辨率人脸重演算法

    网易互娱 AI Lab 提出了一种基于单幅图片的实时高分辨率人脸重演算法,分别在台式机 GPU 和手机端 CPU 上支持以实时帧率生成 1440x1440 和 256×256 分辨率的人脸重演图像. ...

  3. Qt+OpenCV之图片中的人脸识别及人脸抠图

    效果 OpenCV函数知识点 imread() 功能:载入图像 函数原型:Mat cv::imread ( const String & filename, int flags = IMREA ...

  4. ECCV 2022 | 网易互娱AI Lab提出首个基于单幅图片的实时高分辨率人脸重演算法

    点击下方卡片,关注"CVer"公众号 AI/CV重磅干货,第一时间送达 点击进入-> CV 微信技术交流群 转载自:机器之心 |  作者:网易互娱AI Lab 网易互娱 AI ...

  5. 【飞桨PaddlePaddle学习心得】paddle学习创意赛-人脸抠图

    目标 paddlehub项目链接:https://aistudio.baidu.com/aistudio/projectdetail/437104 PaddleHub DeepLabv3+模型(dee ...

  6. 图片识别出处_AI人脸识别

    前言 最近网络上爆火的藏族小哥哥丁真,大家都知道吗? 十几天前凭借一张纯真.干净.帅气的脸霸屏各大短视频平台,连各大电视台新闻媒体都争相报道,这个藏族小伙瞬间火了!! 网友们对于丁真的长相评价不一,我 ...

  7. 免扣(抠)PNG格式图片,让你告别抠图之痛!

    大家平时找透明背景的图片都是从哪里寻找的? 在做项目设计的时候,用最多的素材就是png图片了,往往我们辛辛苦苦找了一张好看的图 片,结果背景特别突兀.这个时候就希望有一个神奇的魔法,可以把这些令人讨厌 ...

  8. 百度人脸识别技术应用003---百度云离线SDK_Android版_功能分析_获取摄像头视频流中的图片_发给百度人脸识别API_识别搜索_或先同步百度云人脸信息_然后本地人脸识别

    1.基于上一节,我们已经把百度云上的人脸库,建好了,然后我们可以从,百度云官网拿到, 离线人脸识别的SDK. SDK下载_文字识别SDK_语音识别SDK-百度AI开放平台 这里可以点进去下载 2.然后 ...

  9. 使用OpenCV-python识别图片视频中的人脸和眼睛

    文章目录 思路和核心代码 识别图像中的人脸 识别视频中的人脸和眼睛 思路和核心代码 思路如下: 首先需要一个训练好的人脸和眼睛特征数据库,用于识别人脸和眼睛 识别出人脸和眼睛之后,返回所在的区域(一般 ...

最新文章

  1. python编程入门课 视频教程-Python编程零基础入门课
  2. linux 内核配置mmc,Linux内核编译,配置本机驱动
  3. [LaunchPad] 超声波测试,数码管显示
  4. 将java项目做成app_将鸿蒙做成和EMUI一致,又兼容安卓APP,华为已立于不败之地...
  5. No valid Qt version set. Set one in Tools/Options 问题(QT)
  6. log4j mysql_log4j写入mysql数据库 | 学步园
  7. 使用PlantUML和VS Code轻松实现UML
  8. 跨境电商全球趋势与独立站布局的关键点
  9. 一行一行分析JQ源码学习笔记-03
  10. 设置oracle odbc,Oracle Windows ODBC 数据源配置
  11. JAVA必备——Struts
  12. win10下安装PyCharm以及激活
  13. 【Tableau server 8.0】Tableau server 考试真题回顾总结
  14. 2021西湖论剑 Re wp
  15. 新浪短网址生成java_2020最新的新浪短网址(T.CN短链接)API接口分享
  16. 移动优先和桌面优先的状态
  17. excel 中如何设置误差线以及其意义
  18. animal farm 第一章阅读笔记
  19. 路由器和三层交换机的搞笑文章
  20. Linux Overview

热门文章

  1. Disney电影《CARS/赛车总动员》
  2. 通过无线连接oracle,手机如何用无线连接电脑传输文件 4种手机电脑文件无线传输方法...
  3. 音视频工程企业专项资质证书
  4. 【转载】30岁开始实现我的程序员梦
  5. python 小说爬虫_小说爬虫python
  6. python画菱形的代码_Python怎么用星号画平行四边形菱形()
  7. 计算机产品设计需要学什么,工业设计主要学习什么内容
  8. DNS域传送漏洞(一)
  9. 长期使用笔记本触控板请以中指为主
  10. PDF文件太大了怎么办?几个免费PDF压缩工具推荐给你!