如何使用Java实现工业级人脸识别?免费开源方案来了!_smartjavaai
🍬Java轻量级、免费、离线AI工具箱,致力于帮助Java开发者零门槛使用AI算法模型 像Hutool一样简单易用的Java AI工具箱
SmartJavaAI是什么?
SmartJavaAI是专为JAVA 开发者打造的一个功能丰富、开箱即用的 JAVA AI算法工具包,致力于帮助JAVA开发者零门槛使用各种AI算法模型,开发者无需深入了解底层实现,即可轻松在 Java 代码中调用人脸识别、目标检测、OCR 等功能。底层支持包括基于 DJL (Deep Java Library) 封装的深度学习模型,以及通过 JNI 接入的 C++/Python 算法,兼容多种主流深度学习框架如 PyTorch、TensorFlow、ONNX、Paddle 等,屏蔽复杂的模型部署与调用细节,开发者无需了解 AI 底层实现即可直接在 Java 项目中集成使用,后续将持续扩展更多算法,目标是构建一个“像 Hutool 一样简单易用”的 JAVA AI 通用工具箱
🚀 人脸能力展示
人脸检测

人脸比对1:1

人证核验

人脸比对1:N
- 人脸注册
- 人脸库查询
- 人脸库删除

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

活体检测
- 图片和视频活体检测

人脸表情识别
- 7种表情检测

🚀 核心亮点
针对 Java 开发者在集成智能算法时常见的两大痛点:
-
🐍 主流AI深度学习框架(PyTorch/TensorFlow)的Python生态与Java工程体系割裂
-
⚙️ 现有算法方案分散杂乱,封装不统一,使用门槛高,不易直接服务于 Java 业务开发
实现了:
✅ 开箱即用 - 两行代码即可调用算法
✅ 支持多种深度学习引擎 - Pytorch、Tensorflow、MXNet、ONNX Runtime
✅ 功能丰富 - 当前支持人脸识别与目标检测,未来将陆续支持 OCR、图像分类、NLP 等多个 AI 领域任务,构建全面的智能算法体系。
✅ 跨平台兼容 - 支持Windows/Linux/macOS系统(x86 & ARM架构)
📌 支持功能
✅ 已实现功能
SmartJavaAI
人脸模块支持以下功能:
- 人脸检测:5点人脸关键点定位
- 人脸识别:人脸512维特征提取、人脸对齐、1:1 人脸比对、1:N 人脸识别
- 人脸库:人脸注册、更新、查询、删除(支持向量数据库milvus/sqlite)
- 人脸属性检测:性别、年龄、口罩、眼睛状态、脸部姿态
- 静默活体检测:图片、视频活体检测
- 人脸表情识别:7种表情识别
- 人脸质量评估:亮度评估、清晰度评估、完整度评估、姿态评估、遮挡评估
🌟 AI集成方式对比
✅ 轻量级部署
✅ 社区资源丰富
❌ 需本地安装环境
✅ 提供完整文档和SDK
✅ 支持离线活体检测
❌ 商业授权费用高
❌ 代码不可控
✅ 支持高并发
✅ 自带模型迭代
❌ 按调用量计费
❌ 有数据安全风险
✅ 支持自定义算法
✅ 识别精度高
❌ 进程通信性能损耗(30%+)
❌ 异常处理复杂度翻倍
✅ 支持主流深度学习框架
✅ 可加载预训练模型(99%+)
❌ 需处理模型加载、预处理、后处理等复杂技术细节
✅ 提供丰富、开箱即用API
✅ 上手简单,单一Jar包集成
安装
1、Maven引入
在项目的 pom.xml 中添加以下依赖以及平台依赖库,详细引入方式参考 Maven 引入。如需引入全部功能,请使用 smartjavaai-all 模块。
<dependency> <groupId>cn.smartjavaai</groupId> <artifactId>smartjavaai-face</artifactId> <version>1.0.19</version></dependency>
2、模型简介
模型下载
人脸检测模型(FaceDetection、FaceLandmarkExtraction)
支持功能:
- 人脸检测
- 5点人脸关键点定位
人脸识别模型(FaceRecognition)
支持功能:
- 人脸512维特征提取
- 人脸对齐(人脸矫正)
- 人脸特征比对(内积[IP]、欧氏距离[L2]、余弦相似度[COSINE])
静态活体检测(RGB)模型(Silent face-anti-spoofing、FaceLivenessDetection)
支持功能:
- 检测图片中的人脸是否为来自认证设备端的近距离裸拍活体人脸对象(裸拍活体正面人脸是指真人未经重度PS、风格化、人工合成等后处理的含正面人脸)
人脸表情识别模型(FacialExpressionRecognition、fer)
支持功能:
- 支持识别7种表情:neutral(中性)、happy(高兴)、sad(悲伤)、surprise(惊讶)、fear(恐惧)、disgust(厌恶)、anger(愤怒)
人脸属性识别模型(GenderDetection、AgeDetection、EyeClosenessDetection、FacePoseEstimation)
支持功能:
- 性别检测
- 年龄检测
- 闭眼检测
- 人脸姿态检测
- 戴口罩检测
人脸质量评估模型(FaceQualityAssessment)
支持功能:
- 亮度评估
- 清晰度评估
- 完整度评估
- 姿态评估
- 遮挡评估
注意事项:RetinaFace、UltraLightFastGenericFace、FaceNet可以不指定离线模型,可联网自动下载
方法说明
注意:
下面的很多接口及代码最新版本都有变化,请前往官网http://smartjavaai.cn,查看最新代码及文档
人脸检测
人脸检测(Face Detection),就是给定一幅图像,找出图像中的人脸位置,通常用一个矩形框框起来
获取默认检测模型:
- 默认模型:retinaface,联网自动下载
FaceDetModel faceDetModel = FaceDetModelFactory.getInstance().getModel();
获取模型(使用自定义模型配置)
FaceDetConfig config = new FaceDetConfig();config.setModelEnum(FaceModelEnum.RETINA_FACE);//人脸检测模型config.setConfidenceThreshold(FaceConfig.DEFAULT_CONFIDENCE_THRESHOLD);//置信度阈值config.setNmsThresh(FaceConfig.NMS_THRESHOLD);//非极大抑制阈值FaceDetModel faceDetModel = FaceDetModelFactory.getInstance().getModel(config);
FaceDetConfig参数说明
::: warning 注意事项:
1、seetaface6模型不支持自定义confidenceThreshold
:::
人脸检测方法
R<DetectionResponse> detect(String imagePath);R<DetectionResponse> detect(BufferedImage image);R<DetectionResponse> detect(byte[] imageData);R<DetectionResponse> detect(InputStream imageInputStream)R<DetectionResponse> detectBase64(String base64Image);
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 } ] }, \"score\": 0.9995993 // 置信度分值 } ]}
检测并绘制人脸框
绘制人脸区域及5个人脸关键点:左眼中心、右眼中心、鼻尖、左嘴角和右嘴角
/** * 检测并绘制人脸 * @param imagePath 图片输入路径(包含文件名称) * @param outputPath 图片输出路径(包含文件名称) */R<Void> detectAndDraw(String imagePath, String outputPath);/** * 检测并绘制人脸 * @param sourceImage * @return */R<BufferedImage> detectAndDraw(BufferedImage sourceImage);
人脸识别
人脸识别就是将两张人脸的特征信息进行比对,给出一对人脸图像的相似度,从而判断两张人脸是否是同一个人,若相似度高于阈值则认为是同一个人,否则为不同的人。
人脸识别的类型:
- 人脸验证——1:1人脸识别
通过提取两张人脸的特征进行相似度对比,最终返回相应的置信度得分,根据特征匹配程度决定“拒绝”或者“接受”。用于判断两个输入人脸是否属于同一人,适用于身份识别及相似脸查询等应用查询
- 人脸检索——1:N人脸识别
在大规模人脸数据库中找出与待检索人脸相似度最高的一个或多个人脸。通过创建的待查人员的面部特征,可以在人脸数据库中迅速查找,可用于身份确认以及身份查询等应用场景
人脸识别流程
可分为以下四个步骤:
获取图像数据:利用摄像头获取要检测的图像
-
人脸检测:检测出图片中要识别的一个或多个人脸,获取人脸区域和坐标位置
-
人脸对齐(校正): 根据人脸关键点检测的结果,将不同姿态的人脸转换为相对正脸
-
人脸识别:在已准备的数据库中,匹配一个或多个人脸,完成人脸识别
注意:人脸识别和人脸检测并非同一技术。人脸检测是人脸识别完整流程中的一个环节。在用摄像头采集含有人脸的图像或视频流后,首先就需要用人脸检测技术自动检测、提取当中的人脸,随后才能进入人脸图像预处理及最核心的人脸特征提取环节,在这一部分主要给大家介绍人脸识别任务。
人脸特征提取
提取人脸512维特征值,用于后续人脸识别
获取人脸识别模型
FaceRecConfig config = new FaceRecConfig();config.setModelEnum(FaceModelEnum.FACENET_MODEL);//人脸识别模型config.setCropFace(true);config.setAlign(true);config.setDetectModel(getFaceDetModel());FaceRecModel faceRecModel = FaceRecModelFactory.getInstance().getModel(config);
FaceRecConfig参数说明
::: danger 注意事项:
1、如果输入的图片未经过人脸矫正,则请务必设置 align = true,否则特征提取结果可能不准确。
2、如果图片未经过人脸裁剪,则请务必设置 cropFace = true,否则特征提取结果可能不准确。
:::
人脸特征提取(多人脸场景)
下面的方法将提取图片中所有人脸特征
R<DetectionResponse> extractFeatures(String imagePath);R<DetectionResponse> extractFeatures(BufferedImage sourceImage);R<DetectionResponse> extractFeatures(byte[] imageData);
DetectionResponse转为json格式,如下所示:
{ \"detectionInfoList\": [ { \"detectionRectangle\": { \"height\": 328, \"width\": 307, \"x\": 157, \"y\": 288 }, \"faceInfo\": { \"feature\": [ // 人脸特征向量:不同模型返回的特征向量数量不同,可能是 512 或 1024。 //此处内容较多,省略 ], \"keyPoints\": [ { \"x\": 248.22177505493164, \"y\": 384.6785583496094 }, { \"x\": 374.57435607910156, \"y\": 374.8636550903321 }, { \"x\": 322.0528106689453, \"y\": 442.43547058105474 }, { \"x\": 267.237491607666, \"y\": 514.3596992492676 }, { \"x\": 380.99170684814453, \"y\": 506.0889015197754 } ] }, \"score\": 0.99999225 } ]}
人脸特征提取(单人脸场景)
提取图像中分数最高的人脸特征,适用于仅包含单张人脸的图像,或存在主次明显的人脸场景。
R<float[]> extractTopFaceFeature(String imagePath);R<float[]> extractTopFaceFeature(BufferedImage sourceImage);R<float[]> extractTopFaceFeature(byte[] imageData);
人脸比对(相似度计算)
- 参数为extractFeatures或extractTopFaceFeature的返回结果
/** * 计算相似度 * @param feature1 图1特征 * @param feature2 图2特征 * @return */float calculSimilar(float[] feature1, float[] feature2);
相似度阈值参考说明
人脸比对(1:1)
直接对两张图片进行比对。方法内部会自动提取每张图中分数最高的人脸特征,并进行相似度计算。
等价于先调用 extractTopFaceFeature
方法提取人脸特征,再使用 calculateSimilar
方法进行比对。
float featureComparison(String imagePath1, String imagePath2);float featureComparison(BufferedImage sourceImage1, BufferedImage sourceImag2);float featureComparison(byte[] imageData1, byte[] imageData2);
人脸库
人脸库相关功能(如人脸注册、人脸查询、人脸删除、清空人脸库等)都依赖于人脸库的支持。
SmartJavaAI 当前支持两种人脸库方案,分别适用于不同规模与性能需求的应用场景:
人脸特征与元信息保存在 SQLite 中,查询时将人脸特征加载至内存进行逐个比对。
部署简单、程序将自动创建 SQLite 数据库及相关数据表,无需用户手动配置。
缺点是查询性能有限,随着人脸数量增多,查询耗时显著增加。
Milvus 是一款高性能、专为向量检索设计的开源数据库,支持百万级甚至亿级人脸特征的高效检索。
使用前需要单独部署 Milvus 服务,详细安装及配置请参考 Milvus 官网。
如何选择?
-
如果你的人脸数据量较少、无需高并发查询,推荐使用 SQLite + 内存轮询 模式,部署简单,无需额外依赖。
-
如果你有较高的性能要求或数据规模较大(例如人脸库规模达数十万甚至百万级),推荐使用 Milvus 向量数据库,实现毫秒级检索能力。
人脸库配置
SmartJavaAI 支持两种人脸库方案:Milvus 和 SQLite。无论使用哪种方案,均需配置对应的人脸库参数。
MilvusConfig 和 SQLiteConfig 都继承自统一的父类:VectorDBConfig,在模型初始化阶段统一通过 FaceModelConfig 进行设置。
Milvus 配置说明
MilvusConfig 的所有字段都有默认值,但如果不显式创建该对象,SmartJavaAI 会默认认为不使用 Milvus,因此不会初始化向量库。
创建MilvusConfig示例:
MilvusConfig vectorDBConfig = new MilvusConfig();vectorDBConfig.setHost(\"127.0.0.1\");vectorDBConfig.setPort(19530);vectorDBConfig.setIdStrategy(IdStrategy.AUTO);vectorDBConfig.setMetricType(MetricType.IP);faceModelConfig.setVectorDBConfig(vectorDBConfig);
MilvusConfig字段说明
IdStrategy枚举说明
MetricType枚举说明:(来自 Milvus SDK)
其他枚举值较少使用,可参考 Milvus 官方文档 了解。
VectorDBType枚举说明
::: danger 注意事项:
1、相似度计算方式:MetricType 影响相似度结果,不建议随意更改。
(1)FaceNet 默认使用 内积(IP)。
(2)SeetaFace6 默认使用 余弦相似度(COSINE)。
2、向量维度(dimension):不建议用户手动修改,应使用模型默认值,否则可能导致搜索失败或精度下降。
3、无需手动设置类型字段(type),SmartJavaAI 会根据传入的配置对象类型(MilvusConfig 或 SQLiteConfig)自动判断所使用的人脸库类型。
:::
SQLite数据库配置如下:
SQLiteConfig 的所有字段都有默认值,但如果不显式创建该对象,SmartJavaAI 会默认认为不使用 SQLite,因此不会初始化数据库。
创建SQLiteConfig示例:
SQLiteConfig vectorDBConfig = new SQLiteConfig();vectorDBConfig.setDbPath(\"/Users/wenjie/Downloads/face.db\");vectorDBConfig.setSimilarityType(SimilarityType.IP);config.setVectorDBConfig(vectorDBConfig);
SQLiteConfig字段说明
SimilarityType枚举说明:
::: danger 注意事项:
1、相似度计算方式:SimilarityType 影响相似度结果,不建议随意更改。
(1)FaceNet 默认使用 内积(IP)。
(2)SeetaFace6 默认使用 余弦相似度(COSINE)。
2、SQLite数据库路径(dbPath),默认使用 SmartJavaAI 的缓存目录,文件名为 face.db
,缓存路径可参考:缓存使用。
如需自定义数据库路径,可通过如下方式手动设置:
vectorDBConfig.setDbPath(“/Users/xxx/Downloads/face.db”);
无需手动创建 face.db 文件,SmartJavaAI 会在首次使用时自动创建数据库并初始化所需表结构。
:::
人脸库初始化
当FaceModelConfig中的 isAutoLoadFace = true
(默认值)时,系统会在模型创建时异步加载人脸库数据到内存。
你可以通过 faceRecModel.isLoadFaceCompleted()
方法判断加载是否完成,仅在加载完成后才能调用人脸库相关功能。
如果希望手动控制加载时机,也可以将 isAutoLoadFace
设置为 false
,然后通过显式调用 loadFaceFeatures()
方法将人脸库数据加载到内存。
当然也可以调用 releaseFaceFeatures()
方法来释放内存
⚠️ 注意事项:
- SQLite 模式:必须加载至内存后,才能使用注册、查询等人脸库相关功能。
- Milvus 模式:是否加载数据到内存,并不会影响人脸库相关功能的使用。
人脸注册
支持通过图片直接完成注册,内部流程为:人脸检测 → 提取分数最高人脸特征 → 注册到人脸库。
R<String> register(FaceRegisterInfo faceRegisterInfo, String imagePath);R<String> register(FaceRegisterInfo faceRegisterInfo, BufferedImage sourceImage);R<String> register(FaceRegisterInfo faceRegisterInfo, byte[] imageData);
也支持使用已提取的人脸特征进行注册:
R<String> register(FaceRegisterInfo faceRegisterInfo, float[] feature);
FaceRegisterInfo字段说明
人脸注册 ID 策略说明
-
Milvus 模式:
- 当
IdStrategy = AUTO
(默认)时,无需手动设置 ID,系统将自动生成唯一的随机 ID,并返回给用户。 - 当
IdStrategy = CUSTOM
时,用户必须手动指定 ID,且需确保 ID 在人脸库中全局唯一(支持数字或字符串格式)。
- 当
-
SQLite 模式:
- 若用户未设置 ID,系统将自动生成随机 ID 并返回。
- 若用户手动设置了 ID,系统将使用该 ID 作为唯一标识。
-
metadata 建议:
建议将
metadata
字段设置为 JSON 格式的字符串,以便后续扩展或按需解析,例如:{ \"name\": \"张三\", \"group\": \"员工\", \"remark\": \"门禁系统白名单\"}
人脸更新
支持通过图片直接完成更新,内部流程为:人脸检测 → 提取分数最高人脸特征 → 更新人脸库。
void upsertFace(FaceRegisterInfo faceRegisterInfo, String imagePath);void upsertFace(FaceRegisterInfo faceRegisterInfo, BufferedImage sourceImage);void upsertFace(FaceRegisterInfo faceRegisterInfo, byte[] imageData);
也支持使用已提取的人脸特征进行更新:
void upsertFace(FaceRegisterInfo faceRegisterInfo, float[] feature);
FaceRegisterInfo可以查看人脸注册中的字段说明
::: danger 注意事项:
更新人脸时,FaceRegisterInfo 中的 id 不能为空,系统将根据该 id 查找已注册的人脸数据:
若该 id 已存在,则执行更新操作;
若该 id 不存在,则视为新注册,执行人脸注册流程。
⚠️ 请确保使用的 id 对应的人脸数据已注册,否则将不会进行更新,而是新增注册。
:::
人脸查询(1:N)
多人脸场景
当图片中存在多个人脸,需要同时查询图片中所有人脸,可以使用如下API:
支持通过图片直接完成查询,内部流程为:人脸检测 → 提取分数最高人脸特征 → 查询人脸库。
R<DetectionResponse> search(String imagePath, FaceSearchParams params);R<DetectionResponse> search(BufferedImage sourceImage, FaceSearchParams params);R<DetectionResponse> search(byte[] imageData, FaceSearchParams params);
FaceSearchParams字段说明:
DetectionResponse字段说明
- 返回并非json格式,仅用于字段讲解
{ \"code\": 0, \"data\": { \"detectionInfoList\": [ { \"detectionRectangle\": { \"height\": 290, \"width\": 272, \"x\": 299, \"y\": 430 }, \"faceInfo\": { \"faceSearchResults\": [ //查询结果 { \"id\": \"458520100632533898\", //人脸ID \"metadata\": \"{\\\"name\\\":\\\"kana\\\",\\\"age\\\":\\\"25\\\"}\", //人脸元数据 \"similarity\": 0.9391172 //人脸相似度 } ], \"feature\": [ ], \"keyPoints\": [ { \"x\": 398.610408782959, \"y\": 522.2400588989259 }, { \"x\": 504.46060943603516, \"y\": 519.7643661499025 }, { \"x\": 472.5443382263184, \"y\": 579.8505973815918 }, { \"x\": 412.2943332195282, \"y\": 640.1959800720215 }, { \"x\": 503.771484375, \"y\": 633.2885837554933 } ] }, \"score\": 0.9999331 } ] }, \"message\": \"成功\", \"success\": true}
单人脸场景
-
当仅需查询一张图片分数最高人脸,可以使用如下API:
-
适用于仅包含单张人脸的图像,或存在主次明显的人脸场景。
-
支持通过图片直接完成查询,内部流程为:人脸检测 → 提取分数最高人脸特征 → 查询人脸库。
R<List<FaceSearchResult>> searchByTopFace(String imagePath, FaceSearchParams params);R<List<FaceSearchResult>> searchByTopFace(BufferedImage sourceImage, FaceSearchParams params);R<List<FaceSearchResult>> searchByTopFace(byte[] imageData, FaceSearchParams params);
也支持使用已提取的人脸特征进行查询:
List<FaceSearchResult> search(float[] feature, FaceSearchParams params);
FaceSearchResult字段说明
- 返回并非json格式,仅用于字段讲解
{ \"id\": \"86dc0262-ea4f-4bff-b00e-b7b608afeb32\", //人脸ID \"metadata\": \"{\\\"name\\\":\\\"iu_update\\\",\\\"age\\\":\\\"25\\\"}\", //人脸元数据 \"similarity\": 0.9396009 //人脸相似度}
相似度阈值参考说明
-
Seetaface6 模型:
官方推荐相似度阈值(threshold
)为 0.62,大于此值通常可认为是同一个人。实际阈值可根据业务场景适当调整。 -
其他模型:
相似度一般会先归一化至 [0, 1] 区间,可参考以下经验值判断是否为同一个人:
📌 实际使用中建议根据业务容错性、识别场景(如门禁、人脸检索)灵活设置阈值。
人脸删除
- 参数为调用register方法时的id
void removeRegister(String... keys);
清空人脸库
long clearFace();
完整示例代码
示例代码
文档地址
开发文档
源码地址
码云:https://gitee.com/dengwenjie/SmartJavaAI
github:https://github.com/geekwenjie/SmartJavaAI
gitcode:https://gitcode.com/geekwenjie/SmartJavaAI