# 人脸识别

# 简介

SmartJavaAI 人脸模块支持以下功能:

  • 人脸检测
  • 人脸特征提取(含人脸对齐)
  • 1:1 人脸比对
  • 1:N 人脸识别
  • 人脸注册与查询
  • 5点人脸关键点定位
  • 人脸属性检测(性别、年龄、口罩、眼睛状态、脸部姿态)
  • 人脸活体检测:图片、视频活体检测

# 能力展示

人脸检测

- 5点人脸关键点定位

人脸比对1:1

- 人脸对齐

人证核验

人脸比对1:N

- 人脸对齐
- 人脸注册
- 人脸库查询
- 人脸库删除

人脸属性检测

- 性别检测
- 年龄检测
- 口罩检测
- 眼睛状态检测
- 脸部姿态检测

活体检测

- 图片和视频活体检测

# 准备工作

# 1、Maven引入

在项目的 pom.xml 中添加以下依赖以及平台依赖库,详细引入方式参考 Maven 引入。如需引入全部功能,请使用 smartjavaai-all 模块。

<dependency>
    <groupId>cn.smartjavaai</groupId>
    <artifactId>smartjavaai-face</artifactId>
    <version>1.0.12</version>
</dependency>

# 2、人脸模型下载

如果在有网环境下使用,不需要下载模型(SeetaFace6模型除外)

模型名称
下载地址
兼容系统 支持设备 文件大小 适用场景
retinaface 下载 (opens new window) Windows
Linux
MacOS
CPU/GPU 110MB 高精度人脸检测
ultralightfastgenericface 下载 (opens new window) Windows
Linux
MacOS
CPU/GPU 1.7MB 高速人脸检测
seetaface6 下载 (opens new window) Windows
Linux
CPU/GPU 288MB 人脸检测、人脸比对、人脸库注册、人脸库查询
facenet 下载 (opens new window) Windows
Linux
MacOS
CPU/GPU 104MB 人脸特征提取、人脸比对

# 3、人脸库下载

当前仅 SeetaFace6 支持人脸库操作功能,需手动下载 faces-data.db(SQLite 数据库)。程序运行过程中将自动读取与写入该数据库,用于存储人脸特征与唯一标识 key,实现注册、比对、查询等功能。

点击下载 (opens new window)

注意事项:

仅使用人脸库相关功能(人脸注册、人脸查询)才需要下载人脸库

# 人脸检测

# 获取默认检测模型:

  • 默认模型:retinaface,联网自动下载
FaceModel faceModel = FaceModelFactory.getInstance().getModel();

# 获取检测模型(使用自定义模型配置)

FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.RETINA_FACE);//人脸模型
config.setConfidenceThreshold(FaceConfig.DEFAULT_CONFIDENCE_THRESHOLD);//置信度阈值
config.setNmsThresh(FaceConfig.NMS_THRESHOLD);//非极大抑制阈值
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);

# FaceModelConfig参数说明

字段名称 字段类型 默认值 说明
modelEnum FaceModelEnum RETINA_FACE 人脸模型枚举
confidenceThreshold double 0.85 置信度阈值,分数低于这个值的结果将被过滤掉。值越高越严格,越低越宽松。
similarityThreshold double 0.62 相似度阈值 作用:判断是否为同一人脸
nmsThresh double 0.45 非极大抑制阈值,用于去除重复的人脸框,当两个框的重叠度超过该值时,只保留一个,建议使用默认值
modelPath String NULL 手动指定离线模型路径
faceDbPath String NULL 人脸库路径(注册/查询功能需配置)
device DeviceEnum CPU 指定运行设备,支持 CPU/GPU

注意事项:

1、当使用 SeetaFace6 模型时,必须手动设置 modelPath,若启用人脸注册和查询功能,还需配置 faceDbPath。modelPath 为模型目录路径,无需包含具体文件名。

2、similarityThreshold目前只支持seetaface6模型使用

3、seetaface6模型不支持自定义confidenceThreshold

# FaceModelEnum人脸模型枚举说明

枚举值 说明
RETINA_FACE 高精度人脸检测模型
ULTRA_LIGHT_FAST_GENERIC_FACE 轻量人脸检测模型
FACENET_FEATURE_EXTRACTION 人脸特征提取模型
SEETA_FACE6_MODEL seetaface6全功能人脸模型

# 人脸检测方法

DetectionResponse detect(String imagePath);
DetectionResponse detect(InputStream imageInputStream);
DetectionResponse detect(BufferedImage image);
DetectionResponse detect(byte[] imageData);

# DetectionResponse字段说明

  • 返回并非json格式,仅用于字段讲解
{
  "detectionInfoList": [ // 检测信息列表
    {
      "detectionRectangle": { //矩形框
        "height": 174, // 矩形高度
        "width": 147, // 矩形宽度
        "x": 275, // 左上角横坐标
        "y": 143 // 左上角纵坐标
      },
      "faceInfo": { // 人脸信息
        "keyPoints": [ // 5个人脸关键点:循序依次为,左眼中心、右眼中心、鼻尖、左嘴角和右嘴角
          {
            "x": 339.5083751678467,
            "y": 192.76402664184573
          },
          {
            "x": 404.7374267578125,
            "y": 197.89914321899414
          },
          {
            "x": 388.9555263519287,
            "y": 231.50675201416016
          },
          {
            "x": 339.8661708831787,
            "y": 265.51241302490234
          },
          {
            "x": 397.7071800231933,
            "y": 269.7657699584961
          }
        ],
        "livenessStatus": "LIVE"
      },
      "score": 0.9995993 // 置信度分值
    }
  ]
}

# 检测并绘制人脸框

绘制人脸区域及5个人脸关键点:左眼中心、右眼中心、鼻尖、左嘴角和右嘴角

/**
 * 检测并绘制人脸
 * @param imagePath 图片输入路径(包含文件名称)
 * @param outputPath 图片输出路径(包含文件名称)
 */
void detectAndDraw(String imagePath, String outputPath);

/**
 * 检测并绘制人脸
 * @param sourceImage
 * @return
 */
BufferedImage detectAndDraw(BufferedImage sourceImage);

# 人脸特征提取

# 人脸特征提取(多人脸提取)

  • FACENET_FEATURE_EXTRACTION 特征提取模型默认使用 ULTRA_LIGHT_FAST_GENERIC_FACE 作为人脸检测模型;如果使用 SEETAFACE6 模型提取人脸特征,由于 SEETAFACE6 本身支持人脸检测,因此检测阶段将直接使用 SEETAFACE6 完成。
  • 自动裁剪人脸 + 人脸对齐
List<float[]> extractFeatures(String imagePath);
List<float[]> extractFeatures(InputStream inputStream);
List<float[]> extractFeatures(BufferedImage sourceImage);
List<float[]> extractFeatures(byte[] imageData);

# 人脸特征提取(分数最高人脸)

  • FACENET_FEATURE_EXTRACTION 特征提取模型默认使用 ULTRA_LIGHT_FAST_GENERIC_FACE 作为人脸检测模型;如果使用 SEETAFACE6 模型提取人脸特征,由于 SEETAFACE6 本身支持人脸检测,因此检测阶段将直接使用 SEETAFACE6 完成。
  • 自动裁剪人脸 + 人脸对齐
float[] extractTopFaceFeature(String imagePath);
float[] extractTopFaceFeature(BufferedImage sourceImage);
float[] extractTopFaceFeature(byte[] imageData);

# 进阶-使用自定义配置 人脸特征提取(多人脸提取)

  • 可以设置人脸检测模型等参数,具体参看FaceExtractConfig字段说明
  • 自动裁剪人脸 + 人脸对齐
List<float[]> extractFeatures(String imagePath, FaceExtractConfig config);
List<float[]> extractFeatures(BufferedImage sourceImage, FaceExtractConfig config);
List<float[]> extractFeatures(byte[] imageData, FaceExtractConfig config);

# 进阶-使用自定义配置 人脸特征提取(分数最高人脸)

  • 可以设置人脸检测模型等参数,具体参看FaceExtractConfig字段说明
  • 自动裁剪人脸 + 人脸对齐
float[] extractTopFaceFeature(String imagePath, FaceExtractConfig config);
float[] extractTopFaceFeature(BufferedImage sourceImage, FaceExtractConfig config);
float[] extractTopFaceFeature(byte[] imageData, FaceExtractConfig config);

# FaceExtractConfig参数说明

字段名称 字段类型 默认值 说明
cropFace boolean true 是否裁剪人脸
align boolean true 是否对齐人脸
detectModelConfig FaceModelConfig 人脸检测模型配置

注意事项:

1、seetaface6模型不支持使用自定义参数提取人脸特征,默认会裁剪人脸及对齐人脸

2、由于人脸对齐前提是裁剪人脸区域,因此当 align=true 时,无论 cropFace 是否为 true,系统都会执行人脸裁剪操作。

# 人脸比对

# 人脸比对(特征提取+比对)

  • 参数为图片路径、输入流、图片对象、图片字节数组
float featureComparison(String imagePath1, String imagePath2);
float featureComparison(BufferedImage sourceImage1, BufferedImage sourceImag2);
float featureComparison(InputStream inputStream1, InputStream inputStream2);
float featureComparison(byte[] imageData1, byte[] imageData2);

# 人脸比对(相似度计算)

  • 参数为extractFeatures或extractTopFaceFeature的返回结果
/**
 * 计算相似度
 * @param feature1 图1特征
 * @param feature2 图2特征
 * @return
 */
float calculSimilar(float[] feature1, float[] feature2);

# 人脸注册

boolean register(String key, String imagePath);
boolean register(String key, InputStream inputStream);
boolean register(String key, BufferedImage sourceImage);
boolean register(String key, byte[] imageData);

# 人脸查询

FaceResult search(String imagePath);
FaceResult search(InputStream inputStream);
FaceResult search(BufferedImage sourceImage);
FaceResult search(byte[] imageData);

# FaceResult字段说明

字段名称 字段类型 说明
key String 注册人脸的key值
similar float 相似度

# 人脸删除

  • 参数为调用register方法时的key值
long removeRegister(String... keys);

# 清空人脸库

long clearFace();

# 活体检测

静默活体识别根据输入的图像数据、人脸位置和人脸特征点,对输入人脸进行活体的判断,并返回人脸活体的状态。

注意事项:

1、活体识别内容增加了对图像清晰度的判断,但是还是有对其他方面的质量要求,比如人脸分辨率128x128以上,光照均匀,自然表情等。其中主要影响识别精度的为光照环境

# 获取活体检测模型:

LivenessConfig config = new LivenessConfig();
config.setModelEnum(LivenessModelEnum.SEETA_FACE6_MODEL);
//需替换为实际模型存储路径
config.setModelPath("C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models");
LivenessDetModel livenessDetModel = LivenessModelFactory.getInstance().getModel(config);

# LivenessConfig参数说明

字段名称 字段类型 默认值 说明
modelEnum LivenessModelEnum SEETA_FACE6_MODEL 模型枚举,目前支持活体检测的模型只有seetaface6模型
modelPath String NULL 手动指定离线模型路径
faceClarityThreshold float 0.3 人脸清晰度阈值,可选
realityThreshold float 0.8 人脸活体阈值,可选
frameCount int 10 视频检测帧数,可选(检测视频时有效)
device DeviceEnum CPU 指定运行设备,支持 CPU/GPU

注意事项:

1、活体识别时,如果清晰度低的话,就会直接返回:未知(UNKNOWN)。清晰度满足阈值,则判断真实度,超过阈值则认为是真人,低于阈值是非活体。

2、在视频识别模式下,会计算视频帧数内的平均值再跟帧数比较。两个阈值都符合,越高的话,越是严格。

# 图片活体检测(多人脸)

DetectionResponse detect(String imagePath)
DetectionResponse detect(BufferedImage image)
DetectionResponse detect(byte[] imageData)

# DetectionResponse字段说明

  • 返回并非json格式,仅用于字段讲解
{
  "detectionInfoList": [ // 检测信息列表
    {
      "detectionRectangle": { //矩形框
        "height": 174, // 矩形高度
        "width": 147, // 矩形宽度
        "x": 275, // 左上角横坐标
        "y": 143 // 左上角纵坐标
      },
      "faceInfo": { // 人脸信息
        "keyPoints": [ // 5个人脸关键点:循序依次为,左眼中心、右眼中心、鼻尖、左嘴角和右嘴角
          {
            "x": 339.5083751678467,
            "y": 192.76402664184573
          },
          {
            "x": 404.7374267578125,
            "y": 197.89914321899414
          },
          {
            "x": 388.9555263519287,
            "y": 231.50675201416016
          },
          {
            "x": 339.8661708831787,
            "y": 265.51241302490234
          },
          {
            "x": 397.7071800231933,
            "y": 269.7657699584961
          }
        ],
        "livenessStatus": "LIVE" //活体检测结果
      }
    }
  ]
}

# 图片活体检测(多人脸)- 基于已检测出的人脸区域和关键点

仅返回活体检测结果

List<LivenessStatus> detect(String imagePath, DetectionResponse faceDetectionResponse)
List<LivenessStatus> detect(BufferedImage image,DetectionResponse faceDetectionResponse)
List<LivenessStatus> detect(byte[] imageData,DetectionResponse faceDetectionResponse)

# 图片活体检测(单人脸)- 基于已检测出的人脸区域和关键点

  • imagePath:图片路径
  • faceDetectionRectangle:人脸检测框(人脸检测返回结果)
  • keyPoints:5个人脸关键点(人脸检测返回结果)
LivenessStatus detect(String imagePath, DetectionRectangle faceDetectionRectangle, List<Point> keyPoints)
LivenessStatus detect(BufferedImage image, DetectionRectangle faceDetectionRectangle, List<Point> keyPoints)
LivenessStatus detect(byte[] imageData, DetectionRectangle faceDetectionRectangle, List<Point> keyPoints)

# 图片活体检测(分数最高人脸)

检测图片中分数最高的人脸

LivenessStatus detectTopFace(BufferedImage image)
LivenessStatus detectTopFace(String imagePath)
LivenessStatus detectTopFace(byte[] imageData)

# 视频活体检测

活体检测分为图片模式和视频模式,两种工作模式的区别在于前者属于一帧就是可以返回识别结果,而后者要输入多个视频帧然后返回识别结果。

LivenessStatus detectVideo(InputStream videoInputStream)
LivenessStatus detectVideo(String videoPath)

注意事项:

1、视频活体检测支持常见视频格式(推荐使用mp4),内部使用ffmpeg进行视频解析。

2、输入视频的有效帧数必须 > LivenessConfig 配置参数中 frameCount 的设定值(默认阈值:10帧)

3、若不满足帧数条件,接口将抛出异常

4、输入视频文件过大,会耗费内存,建议视频文件不要过大。

# 视频活体检测(逐帧检测)

LivenessStatus detectVideoByFrame(BufferedImage frameImageData)
LivenessStatus detectVideoByFrame(byte[] frameImageData)

# 视频活体检测(逐帧检测) - 基于已检测出的人脸区域和关键点

LivenessStatus detectVideoByFrame(BufferedImage frameImage, DetectionRectangle faceDetectionRectangle, List<Point> keyPoints)
LivenessStatus detectVideoByFrame(byte[] frameData, DetectionRectangle faceDetectionRectangle, List<Point> keyPoints)

注意事项:

1、在视频活体检测模式下,检测帧数超过frameCount之后,就可以输出识别结果。这个数量相当于多帧识别结果融合的融合的帧数。当检测的帧数超过设定帧数的时候,会采用滑动窗口的方式,返回融合的最近检测的帧融合的识别结果。一般来说,在10以内,帧数越多,结果越稳定,相对性能越好,但是得到结果的延时越高。

# LivenessStatus 活体检测返回结果枚举

枚举值 说明
LIVE 活体
NON_LIVE 非活体
UNKNOWN 未知,或者人脸清晰度低
DETECTING 视频模式,检测中

# 人脸属性检测

人脸属性检测包含:性别、年龄、口罩、眼睛状态(开闭)、脸部姿态(俯仰角,偏航角,翻滚角)

# 获取人脸属性检测模型:

FaceAttributeConfig config = new FaceAttributeConfig();
config.setModelEnum(FaceAttributeModelEnum.SEETA_FACE6_MODEL);
//需替换为实际模型存储路径
config.setModelPath("C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models");
FaceAttributeModel faceAttributeModel = FaceAttributeModelFactory.getInstance().getModel(config);

# FaceAttributeConfig参数说明

字段名称 字段类型 默认值 说明
modelEnum FaceAttributeModelEnum SEETA_FACE6_MODEL 模型枚举,目前支持人脸属性检测的模型只有seetaface6模型
modelPath String NULL 手动指定离线模型路径
enableAge boolean true 是否启用年龄检测,可选
enableGender boolean true 是否启用性别检测,可选
enableHeadPose boolean true 是否启用人脸姿态检测,可选
enableEyeStatus boolean true 是否启用眼睛状态检测,可选
enableMask boolean true 是否启用口罩检测,可选
device DeviceEnum CPU 指定运行设备,支持 CPU/GPU

# 人脸属性检测(多人脸)

返回人脸检测信息+人脸属性

DetectionResponse detect(String imagePath)
DetectionResponse detect(BufferedImage image)
DetectionResponse detect(byte[] imageData)

# DetectionResponse字段说明

  • 返回并非json格式,仅用于字段讲解
{
  "detectionInfoList": [ // 检测信息列表
    {
      "detectionRectangle": { //矩形框
        "height": 174, // 矩形高度
        "width": 147, // 矩形宽度
        "x": 275, // 左上角横坐标
        "y": 143 // 左上角纵坐标
      },
      "faceInfo": { // 人脸信息
        "faceAttribute": { //人脸属性
          "age": 44, //年龄
          "genderType": "FEMALE", //性别
          "headPose": { //脸部姿态
            "pitch": 12.958274, 
            "roll": 0.19592644,
            "yaw": -4.166052
          },
          "leftEyeStatus": "OPEN",// 左眼开闭
          "rightEyeStatus": "OPEN",//右眼开闭
          "wearingMask": false //是否戴口罩
        },
        "keyPoints": [ // 5个人脸关键点:循序依次为,左眼中心、右眼中心、鼻尖、左嘴角和右嘴角
          {
            "x": 339.5083751678467,
            "y": 192.76402664184573
          },
          {
            "x": 404.7374267578125,
            "y": 197.89914321899414
          },
          {
            "x": 388.9555263519287,
            "y": 231.50675201416016
          },
          {
            "x": 339.8661708831787,
            "y": 265.51241302490234
          },
          {
            "x": 397.7071800231933,
            "y": 269.7657699584961
          }
        ]
      }
    }
  ]
}

# 人脸属性检测(多人脸)- 基于已检测出的人脸区域和关键点

仅返回人脸属性

List<FaceAttribute> detect(String imagePath, DetectionResponse faceDetectionResponse)
List<FaceAttribute> detect(BufferedImage image,DetectionResponse faceDetectionResponse)
List<FaceAttribute> detect(byte[] imageData,DetectionResponse faceDetectionResponse)

# 人脸属性检测(单人脸)- 基于已检测出的人脸区域和关键点

  • imagePath:图片路径
  • faceDetectionRectangle:人脸检测框(人脸检测返回结果)
  • keyPoints:5个人脸关键点(人脸检测返回结果)
FaceAttribute detect(String imagePath, DetectionRectangle faceDetectionRectangle, List<Point> keyPoints)
FaceAttribute detect(BufferedImage image, DetectionRectangle faceDetectionRectangle, List<Point> keyPoints)
FaceAttribute detect(byte[] imageData, DetectionRectangle faceDetectionRectangle, List<Point> keyPoints)

# 人脸属性检测(分数最高人脸)

检测图片中分数最高的人脸

LivenessStatus detectTopFace(BufferedImage image)
LivenessStatus detectTopFace(String imagePath)
LivenessStatus detectTopFace(byte[] imageData)

# FaceAttribute 字段讲解

字段名称 字段类型 说明
genderType GenderType 性别枚举
age Integer 年龄
leftEyeStatus EyeStatus 左眼状态
rightEyeStatus EyeStatus 右眼状态
wearingMask Boolean 是否带口罩
headPose HeadPose 姿态

# GenderType 性别枚举

枚举值 说明
MALE
FEMALE
UNKNOWN 未知

# EyeStatus 眼睛状态枚举

枚举值 说明
OPEN 睁眼
CLOSED 闭眼
NON_EYE_REGION 非眼部区域
UNKNOWN 未知

# HeadPose 姿态检测结果字段讲解

字段名称 字段类型 说明
pitch Float 上下(俯仰角),正值抬头,负值低头 (-90°~+90°)
yaw Float 左右(偏航角),正值右偏,负值左偏(-90°~+90°)
roll Float 倾斜(翻滚角),正值右倾,负值左倾(-90°~+90°)

# 绘制人脸属性检测结果并导出图片

通过 SmartJavaAI 提供的工具类 FaceUtils,你可以轻松地将检测到的人脸框和属性信息绘制到图片上,并导出保存。示例代码如下:

  • image:待处理的原始图像对象。

  • detectionResponse:人脸检测与属性识别的响应结果。

  • 第三个参数为导出的目标文件路径(支持 PNG/JPG 格式)。

该方法将自动在图像上绘制人脸框、性别、年龄等属性信息,并将结果保存到指定路径。

FaceUtils.drawBoxesWithFaceAttribute(image, detectionResponse,"C:/Users/Administrator/Downloads/double_person_.png");

# 完整示例代码

示例代码 (opens new window)

# 离线使用

1、首次运行,会自动下载模型及底层依赖库到缓存目录中。缓存路径请看文档:离线使用

2、seetaface6需要手动下载模型,其他模型调用都会自动下载,如果因网络问题下载失败,请手动下载模型,并放置到缓存目录中

3、可以在联网环境中运行程序一次,确保所需的依赖库已下载。然后将缓存目录复制到离线环境中相同的路径下,即可实现离线使用