人脸框抠图如何实现
最近在尝试做一个人脸识别项目,在对比几款主流人脸识别SDK后,采用了虹软的Arcface SDK,因为它提供了免费版本,并且可以离线使用,接入难度也比较低。项目中有一个需求就是显示检测到的人脸,但是如何从一张图片中抠取合适大小的人脸呢?本文将从以下步骤来介绍如何实现:
1. 如何获得人脸框
2. 如何根据人脸框裁剪
3. 如何进行结果图旋转
4. 应用场景举例
1. 如何获得人脸框
首先我们来看一下虹软Android ArcFace SDK用于人脸检测的detectFaces函数以及人脸数据类FaceInfo:
detectFaces函数:
参数 | 类型 | 说明 |
data | byte[] | 图像数据的内存 |
width | int | 图像的宽 |
height | int | 图像的高 |
format | int | 图像的格式 |
faceInfoList | List\<FaceInfo> | 人脸检测结果列表 |
FaceInfo定义:
变量 | 类型 | 说明 |
rect | Rect | 人脸在图像中的坐标 |
orient | int | 人脸的朝向 |
faceId | int | 人脸id,用于标识人脸 |
人脸检测函数介绍的文章有很多,这里就不多做介绍了。FaceInfo中的rect就是我们用来抠取人脸的重要参数,下图就是根据它画出的人脸框。
2. 如何根据人脸框裁剪
以Android平台为例,Bitmap类提供了函数**createBitmap**(Bitmap source, int x, int y, int width, int height)
变量 | 类型 | 说明 |
source | Bitmap | 原始图像 |
x | int | 人脸框左上角y坐标 |
y | int | 人脸框左上角y坐标 |
width | int | 新图像的宽 |
height | int | 新图像的高 |
使用这个函数就可以抠取任意区域内图像内容:
java //原图 Bitmap source; //人脸框 Rect faceRect; //创建Bitmap Bitmap.createBitmap(source,faceRect.left,faceRect.top,faceRect.width(),faceRect.height();
3. 如何进行结果图旋转
FaceInfo中orient代表这个人脸在图像中的朝向,当其不为0°的时候,需要根据实际情况进行旋转。
旋转角度 | 类型 | 说明 |
ASF_OC_0 | int | 0° |
ASF_OC_90 | int | 逆时针90° |
ASF_OC_180 | int | 180° |
ASF_OC_270 | int | 顺时针90° |
以下是旋转代码
java //原图 Bitmap source; //人脸框 Rect faceRect; //创建Bitmap,假设需要顺时针旋转90° Matrix matrix = new Matrix(); matrix.postRotate(90); Bitmap.createBitmap(source, faceRect.left, faceRect.top, faceRect.width(), faceRect.height(), matrix, true);
4. 应用场景举例
例如门禁场景下,需要显示人脸(抠图)或者上传人脸图片到服务端。如果上传完整的图像,则会占用大量的存储空间以及网络资源,所以上传抠取的人脸图片是比较合适的,但是根据检测所得的人脸框抠取的人脸是不完整的,所以需要对人脸框做一些后期处理,最简单的方案就是宽高分别向外扩大其1/2长度。示例代码如下:
java //原图 Bitmap source; //人脸框 Rect faceRect; //调整人脸框 Rect newRect = new Rect(faceRect); //确保人脸框在图像内 if (newRect.left < 0) { newRect.left = 0; } if (newRect.top < 0) { newRect.top = 0; } if (newRect.right > source.getWidth()) { newRect.right = source.getWidth(); } if (newRect.bottom > source.getHeight()) { newRect.bottom = source.getHeight(); } // int offsetX = Math.min(Math.min(faceRect.width()/2,newRect.left), source.getWidth() - newRect.right); int offsetY = Math.min(Math.min(faceRect.height()/2,newRect.top), source.getHeight() - newRect.bottom); newRect.inset(-offsetX, -offsetY); //创建Bitmap,假设需要顺时针旋转90° Matrix matrix = new Matrix(); matrix.postRotate(90); Bitmap.createBitmap(source, newRect.left, newRect.top, newRect.width(), newRect.height(), matrix, true);
温馨提示:
虹软人脸识别Android Demo中提供了很多人脸识别相关功能,如:画人脸框适配方案;异步人脸特征提取;异步人脸特征比对等等,有需要可以在下面链接下载:
Android Demo可在虹软人脸识别开放平台下载
- 动手实操 | 如何用 Python 实现人脸识别,证明这个杨幂是那个杨幂?
- 如何通过OpenFace实现人脸识别框架
- 干货 | 详解如何用深度学习消除背景,实现抠图
- 如何实现基于微信小程序的人脸识别
- 如何通过OpenFace实现人脸识别框架
- 如何实现两个人脸照片的变换
- 如何用 200 行 JavaScript 代码实现人脸检测?
- Vegas如何实现多点抠图?
- 如何用 200 行 JavaScript 代码实现人脸检测?
- 动手实操 | 如何用 Python 实现人脸识别,证明这个杨幂是那个杨幂?
- 如何使用 Opencv 实现人脸检测和人脸识别?
- 动手实操:如何用 Python 实现人脸识别,证明这个杨幂是那个杨幂?
- 图片处理——NDK实现人脸抠图
- CorelDRAW中如何实现抠图
- python---如何用Python实现iPhone X的人脸解锁功能?
- 用C++实现单例模式3——如何在不使用锁和C++11的情况下,用C++实现线程安全的Singleton
- 如何在C#中实现图片缩放
- 高速飞机上换引擎,MQ如何实现平滑迁移?
- 如何实现WiFi Display互联:我的一次WiFi Display(Miracast)功能发送端(source)和接收端(sink)的实现笔记
- 如何实现两台服务器间无密码的传输数据和操作