diff --git a/README.md b/README.md
index dcab9b4..5da7e3f 100644
--- a/README.md
+++ b/README.md
@@ -61,14 +61,16 @@
- **RetinaFace 模型**[[GitHub]](https://github.com/deepinsight/insightface/tree/master/detection/retinaface):一个高效的深度学习人脸检测模型,支持高精度的人脸检测,但目前不支持人脸比对
- **Ultra-Light-Fast-Generic-Face-Detector-1MB** [[GitHub\]](https://github.com/Linzaer/Ultra-Light-Fast-Generic-Face-Detector-1MB):一个轻量级的人脸检测模型,适用于需要较低延迟和较小模型尺寸的应用场景。
- **Seetaface6** [[GitHub\]](https://github.com/seetafaceengine/SeetaFace6):是中科视拓最新开放的商业正式级版本,支持人脸检测、关键点定位、人脸识别。同时增加了活体检测、质量评估、年龄性别估计。并且响应时事,开放了口罩检测以及戴口罩的人脸识别模型
+- **[facenet-pytorch](https://github.com/timesler/facenet-pytorch)** [[GitHub\]](https://github.com/seetafaceengine/SeetaFace6):这是 pytorch 中 Inception Resnet (V1) 模型的存储库,在 VGGFace2 和 CASIA-Webface 上进行了预训练。Pytorch 模型权重使用从 David Sandberg 的 [tensorflow Facenet repo](https://github.com/davidsandberg/facenet) 移植的参数进行初始化。该存储库中还包含 MTCNN 的高效 pytorch 实现,用于推理之前的人脸检测。这些模型也是经过预训练的。据我们所知,这是最快的 MTCNN 实现。
-### 模型对比及下载地址
+### 人脸模型对比及下载地址
| 模型名称 | 下载地址 | 文件大小 | 适用场景 | 兼容系统 |
| :-----------------------: | :----------------------------------------------------------: | :------: | :---------------: | ------------------- |
| retinaface | [下载](https://resources.djl.ai/test-models/pytorch/retinaface.zip) | 110MB | 高精度人脸检测 | Windows/Linux/MacOS |
-| ultralightfastgenericface | [下载](https://resources.djl.ai/test-models/pytorch/ultranet.zip) | 1.7MB | 高速人脸检测 | Windows/Linux |
-| seetaface6 | [下载](https://pan.baidu.com/s/1hfNacA8ISV2qHrycjOkgqA?pwd=1234) | 288MB | 人脸检测/人脸识别 | Windows/Linux |
+| ultralightfastgenericface | [下载](https://resources.djl.ai/test-models/pytorch/ultranet.zip) | 1.7MB | 高速人脸检测 | Windows/Linux/MacOS |
+| seetaface6 | [下载](https://pan.baidu.com/s/1hfNacA8ISV2qHrycjOkgqA?pwd=1234) | 288MB | 人脸检测/人脸识别 | Windows |
+| facenet-pytorch | [下载](https://resources.djl.ai/test-models/pytorch/face_feature.zip) | 104MB | 人脸识别 | Windows/Linux/MacOS |
## 环境要求
@@ -82,7 +84,7 @@
>
> (1)默认算法(RetinaFace)或轻量算法(Ultra-Light-Fast-Generic-Face-Detector )都为python算法,兼容 Windows、Linux、MacOS,Android 等系统,SmartJavaAI首次启动将自动下载模型到及依赖库到本地(.djl.ai隐藏文件夹),建议保持网络畅通。初始化完成后,后续启动可实现毫秒级响应。在无网络环境下,可指定本地模型路径(需提前下载模型包)。目前,这两种算法不支持人脸识别或人脸比对功能。
>
-> (2)Seetaface6 采用 C++ 编写,兼容 Windows、CentOS、Ubuntu 等系统。创建算法时,将自动加载对应系统的依赖库。Seetaface6 支持全功能人脸处理(人脸检测、人脸比对 1:1 或 1:N)。SmartJavaAI 通过 JNI 调用 C++ 接口,不支持在线下载模型,需手动下载并存储至本地。使用人脸比对等功能时,需要将项目中db/faces-data.db存放到您本地路径下并在config中指定人脸库路径。
+> (2)Seetaface6 采用 C++ 编写,兼容 Windows、CentOS、Ubuntu 等系统,虽然Seetaface6 支持linux,但是我们目前仅实现了windows,如果后续对linux需求多,我们将兼容linux。Seetaface6 支持全功能人脸处理(人脸检测、人脸比对 1:1 或 1:N)。SmartJavaAI 通过 JNI 调用 C++ 接口,不支持在线下载模型,需手动下载并存储至本地。使用人脸比对等功能时,需要将项目中db/faces-data.db存放到您本地路径下并在config中指定人脸库路径。
### 1. 安装人脸算法依赖
@@ -93,7 +95,7 @@
ink.numberone
smartjavaai-face
- 1.0.5
+ 1.0.6
```
@@ -150,7 +152,7 @@ log.info("相似度:{}", similar);
-### 6. 人脸特征提取及比对
+### 6. 人脸特征提取及比对(seetaface6)
```java
// 初始化配置
@@ -169,7 +171,24 @@ float similar = currentAlgorithm.calculSimilar(feature1, feature2);
log.info("相似度:{}", similar);
```
-### 7. 注册及搜索人脸(1:N)
+### 7. 人脸特征提取及比对(facenet-pytorch)
+
+```java
+//创建脸算法
+FaceAlgorithm featureAlgorithm = FaceAlgorithmFactory.createFaceFeatureAlgorithm();
+//提取身份证人脸特征
+float[] feature1 = featureAlgorithm.featureExtraction("src/main/resources/kana1.jpg");
+float[] feature2 = featureAlgorithm.featureExtraction("src/main/resources/kana2.jpg");
+if (feature1 != null && feature2 != null) {
+ //相似度在0.8至0.85及以上时,可判定为同一人,但具体阈值可能因图片而异,存在一定误差。
+ float similar = featureAlgorithm.calculSimilar(feature1, feature2);
+ log.info("相似度:{}", similar);
+} else {
+ log.warn("人脸特征提取失败");
+}
+```
+
+### 8. 注册及搜索人脸(1:N)
```java
// 初始化配置
@@ -195,7 +214,7 @@ if(faceResult != null){
}
```
-### 8. 人脸检测(离线下载模型)
+### 9. 人脸检测(离线下载模型)
```java
// 初始化配置
@@ -250,7 +269,16 @@ ImageUtils.drawBoundingBoxes(image, result, imagePath.toAbsolutePath().toString(
- **微信**: deng775747758 (请备注:SmartJavaAI)
- **Email**: 775747758@qq.com
-
-
🚀 **如果这个项目对你有帮助,别忘了点个 Star ⭐!你的支持是我持续优化升级的动力!** ❤️
+
+
+
+## 更新日志
+
+## [v1.0.6] - 2025-04-01
+- 修复人脸识别算法facenet-pytorch实现方式
+- 优化Seetaface6算法,兼容jdk高版本
+
+
+
diff --git a/examples/pom.xml b/examples/pom.xml
index 1fab46c..ea30c65 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -43,7 +43,7 @@
ink.numberone
smartjavaai-face
- 1.0.5
+ 1.0.6
diff --git a/examples/src/main/java/smartai/examples/face/FaceDemo.java b/examples/src/main/java/smartai/examples/face/FaceDemo.java
index c0897d2..431344d 100644
--- a/examples/src/main/java/smartai/examples/face/FaceDemo.java
+++ b/examples/src/main/java/smartai/examples/face/FaceDemo.java
@@ -13,8 +13,10 @@ import smartai.examples.utils.ImageUtils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
+import java.awt.image.RasterFormatException;
import java.io.File;
import java.io.FileInputStream;
+import java.io.IOException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.LinkOption;
@@ -30,7 +32,7 @@ public class FaceDemo {
public static void main(String[] args) {
try {
- featureComparison();
+ featureExtractionAndCompare2();
//detectFace2();
//verifyIDCard();
} catch (Exception e) {
@@ -44,29 +46,26 @@ public class FaceDemo {
* 特点:识别精度高,高速
* 应用场景:如监控摄像头、智能安防系统等需要高精度检测的场合
*/
- public static void detectFace() throws Exception {
- // 创建并启动计时器
- StopWatch sw = StopWatch.createStarted();
- //创建人脸算法
- FaceAlgorithm currentAlgorithm = FaceAlgorithmFactory.createFaceAlgorithm();
- sw.stop();
- log.info("创建人脸算法耗时:" + sw.getTime() + "ms");
- sw.reset();
- sw.start();
- //使用图片路径检测
- FaceDetectedResult result = currentAlgorithm.detect("src/main/resources/largest_selfie.jpg");
- sw.stop();
- log.info("人脸检测耗时:" + sw.getTime() + "ms");
- log.info("人脸检测结果:{}", JSONObject.toJSONString(result));
- //使用图片流检测
- File input = new File("src/main/resources/largest_selfie.jpg");
- //FaceDetectedResult result = currentAlgorithm.detect(new FileInputStream(input));
- //log.info("人脸检测结果:{}", JSONObject.toJSONString(result));
- BufferedImage image = ImageIO.read(input);
- //创建保存路径
- Path imagePath = Paths.get("output").resolve("retinaface_detected.jpg");
- //绘制人脸框
- ImageUtils.drawBoundingBoxes(image, result, imagePath.toAbsolutePath().toString());
+ public static void detectFace(){
+ try {
+ //创建人脸算法
+ FaceAlgorithm currentAlgorithm = FaceAlgorithmFactory.createFaceAlgorithm();
+ //使用图片路径检测
+ FaceDetectedResult result = currentAlgorithm.detect("src/main/resources/largest_selfie.jpg");
+ log.info("人脸检测结果:{}", JSONObject.toJSONString(result));
+ //使用图片流检测
+ File input = new File("src/main/resources/largest_selfie.jpg");
+ //FaceDetectedResult result = currentAlgorithm.detect(new FileInputStream(input));
+ //log.info("人脸检测结果:{}", JSONObject.toJSONString(result));
+ BufferedImage image = ImageIO.read(input);
+ //创建保存路径
+ Path imagePath = Paths.get("output").resolve("retinaface_detected.jpg");
+ //绘制人脸框
+ ImageUtils.drawBoundingBoxes(image, result, imagePath.toAbsolutePath().toString());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
}
@@ -76,29 +75,25 @@ public class FaceDemo {
* 特点:高速,准确率略低
* 应用场景:如监控摄像头、智能安防系统等需要高精度检测的场合
*/
- public static void detectFace2() throws Exception {
- // 创建并启动计时器
- StopWatch sw = StopWatch.createStarted();
- //创建轻量人脸算法
- FaceAlgorithm currentAlgorithm = FaceAlgorithmFactory.createLightFaceAlgorithm();
- sw.stop();
- log.info("创建人脸算法耗时:" + sw.getTime() + "ms");
- sw.reset();
- sw.start();
- //使用图片路径检测
- FaceDetectedResult result = currentAlgorithm.detect("src/main/resources/largest_selfie.jpg");
- sw.stop();
- log.info("人脸检测耗时:" + sw.getTime() + "ms");
- log.info("轻量人脸检测结果:{}", JSONObject.toJSONString(result));
- //使用图片流检测
- //File imageFile = new File("/Users/wenjie/Downloads/djl-master/examples/src/test/resources/largest_selfie.jpg");
- //FaceDetectedResult result = currentAlgorithm.detect(new FileInputStream(imageFile));
- File input = new File("src/main/resources/largest_selfie.jpg");
- BufferedImage image = ImageIO.read(input);
- //创建保存路径
- Path imagePath = Paths.get("output").resolve("retinaface_detected.jpg");
- //绘制人脸框
- ImageUtils.drawBoundingBoxes(image, result, imagePath.toAbsolutePath().toString());
+ public static void detectFace2(){
+ try {
+ //创建轻量人脸算法
+ FaceAlgorithm currentAlgorithm = FaceAlgorithmFactory.createLightFaceAlgorithm();
+ //使用图片路径检测
+ FaceDetectedResult result = currentAlgorithm.detect("src/main/resources/largest_selfie.jpg");
+ log.info("轻量人脸检测结果:{}", JSONObject.toJSONString(result));
+ //使用图片流检测
+ //File imageFile = new File("/Users/wenjie/Downloads/djl-master/examples/src/test/resources/largest_selfie.jpg");
+ //FaceDetectedResult result = currentAlgorithm.detect(new FileInputStream(imageFile));
+ File input = new File("src/main/resources/largest_selfie.jpg");
+ BufferedImage image = ImageIO.read(input);
+ //创建保存路径
+ Path imagePath = Paths.get("output").resolve("retinaface_detected.jpg");
+ //绘制人脸框
+ ImageUtils.drawBoundingBoxes(image, result, imagePath.toAbsolutePath().toString());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
@@ -109,34 +104,38 @@ public class FaceDemo {
* 特点:识别精度高,高速
* 应用场景:如监控摄像头、智能安防系统等需要高精度检测的场合
*/
- public static void detectFaceOffine() throws Exception {
- // 初始化配置
- ModelConfig config = new ModelConfig();
- config.setAlgorithmName("retinaface");//人脸算法模型,目前支持:retinaface/ultralightfastgenericface/seetaface6
- //config.setAlgorithmName("ultralightfastgenericface");//轻量模型
- config.setConfidenceThreshold(FaceConfig.DEFAULT_CONFIDENCE_THRESHOLD);//置信度阈值
- config.setMaxFaceCount(FaceConfig.MAX_FACE_LIMIT);//每张特征图保留的最大候选框数量
- //nms阈值:控制重叠框的合并程度,取值越低,合并越多重叠框(减少误检但可能漏检);取值越高,保留更多框(增加检出但可能引入冗余)
- config.setNmsThresh(FaceConfig.NMS_THRESHOLD);
- //模型下载地址:
- //retinaface: https://resources.djl.ai/test-models/pytorch/retinaface.zip
- //ultralightfastgenericface: https://resources.djl.ai/test-models/pytorch/ultranet.zip
- //改为模型存放路径
- config.setModelPath("/Users/wenjie/Documents/develop/face_model/retinaface.pt");
- //创建人脸算法
- FaceAlgorithm currentAlgorithm = FaceAlgorithmFactory.createFaceAlgorithm(config);
- //使用图片路径检测
- FaceDetectedResult result = currentAlgorithm.detect("src/main/resources/largest_selfie.jpg");
- log.info("人脸检测结果:{}", JSONObject.toJSONString(result));
- //使用图片流检测
- File input = new File("src/main/resources/largest_selfie.jpg");
- //FaceDetectedResult result = currentAlgorithm.detect(new FileInputStream(input));
- //logger.info("人脸检测结果:{}", JSONObject.toJSONString(result));
- BufferedImage image = ImageIO.read(input);
- //创建保存路径
- Path imagePath = Paths.get("output").resolve("retinaface_detected.jpg");
- //绘制人脸框
- ImageUtils.drawBoundingBoxes(image, result, imagePath.toAbsolutePath().toString());
+ public static void detectFaceOffine(){
+ try {
+ // 初始化配置
+ ModelConfig config = new ModelConfig();
+ config.setAlgorithmName("retinaface");//人脸算法模型,目前支持:retinaface/ultralightfastgenericface/seetaface6
+ //config.setAlgorithmName("ultralightfastgenericface");//轻量模型
+ config.setConfidenceThreshold(FaceConfig.DEFAULT_CONFIDENCE_THRESHOLD);//置信度阈值
+ config.setMaxFaceCount(FaceConfig.MAX_FACE_LIMIT);//每张特征图保留的最大候选框数量
+ //nms阈值:控制重叠框的合并程度,取值越低,合并越多重叠框(减少误检但可能漏检);取值越高,保留更多框(增加检出但可能引入冗余)
+ config.setNmsThresh(FaceConfig.NMS_THRESHOLD);
+ //模型下载地址:
+ //retinaface: https://resources.djl.ai/test-models/pytorch/retinaface.zip
+ //ultralightfastgenericface: https://resources.djl.ai/test-models/pytorch/ultranet.zip
+ //改为模型存放路径
+ config.setModelPath("/Users/wenjie/Documents/develop/face_model/retinaface.pt");
+ //创建人脸算法
+ FaceAlgorithm currentAlgorithm = FaceAlgorithmFactory.createFaceAlgorithm(config);
+ //使用图片路径检测
+ FaceDetectedResult result = currentAlgorithm.detect("src/main/resources/largest_selfie.jpg");
+ log.info("人脸检测结果:{}", JSONObject.toJSONString(result));
+ //使用图片流检测
+ File input = new File("src/main/resources/largest_selfie.jpg");
+ //FaceDetectedResult result = currentAlgorithm.detect(new FileInputStream(input));
+ //logger.info("人脸检测结果:{}", JSONObject.toJSONString(result));
+ BufferedImage image = ImageIO.read(input);
+ //创建保存路径
+ Path imagePath = Paths.get("output").resolve("retinaface_detected.jpg");
+ //绘制人脸框
+ ImageUtils.drawBoundingBoxes(image, result, imagePath.toAbsolutePath().toString());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
/**
@@ -164,7 +163,8 @@ public class FaceDemo {
}
/**
- * 人脸特征提取及比对
+ * seetaface6人脸特征提取及比对(可人证核验)
+ * 目前仅支持windows 64位系统,如需支持其他操作系统可参考方法:featureExtractionAndCompare2
*/
public static void featureExtractionAndCompare(){
try {
@@ -180,8 +180,12 @@ public class FaceDemo {
//提取图像中最大人脸的特征
float[] feature1 = currentAlgorithm.featureExtraction("src/main/resources/kana1.jpg");
float[] feature2 = currentAlgorithm.featureExtraction("src/main/resources/kana2.jpg");
- float similar = currentAlgorithm.calculSimilar(feature1, feature2);
- log.info("相似度:{}", similar);
+ if(feature1 != null && feature2 != null){
+ float similar = currentAlgorithm.calculSimilar(feature1, feature2);
+ log.info("相似度:{}", similar);
+ }else{
+ log.warn("人脸特征提取失败");
+ }
}
catch (Exception e){
e.printStackTrace();
@@ -189,8 +193,31 @@ public class FaceDemo {
}
/**
- * 注册人脸及搜索人脸(1:N)
+ * facenet-pytorch 人脸特征提取及比对(可人证核验)
+ * 支持windows,linux,macos
*/
+ public static void featureExtractionAndCompare2(){
+ try {
+ //创建脸算法
+ FaceAlgorithm featureAlgorithm = FaceAlgorithmFactory.createFaceFeatureAlgorithm();
+ //提取身份证人脸特征
+ float[] feature1 = featureAlgorithm.featureExtraction("src/main/resources/kana1.jpg");
+ float[] feature2 = featureAlgorithm.featureExtraction("src/main/resources/kana2.jpg");
+ if (feature1 != null && feature2 != null) {
+ //相似度在0.8至0.85及以上时,可判定为同一人,但具体阈值可能因图片而异,存在一定误差。
+ float similar = featureAlgorithm.calculSimilar(feature1, feature2);
+ log.info("相似度:{}", similar);
+ } else {
+ log.warn("人脸特征提取失败");
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * 注册人脸及搜索人脸(1:N)
+ */
public static void registerAndSearchFace(){
try {
// 初始化配置
@@ -248,5 +275,4 @@ public class FaceDemo {
}
}
-
}
diff --git a/pom.xml b/pom.xml
index 6b8c658..97803f1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
ink.numberone
smartjavaai-parent
- 1.0.5
+ 1.0.6
pom
SmartJavaAI
@@ -35,13 +35,13 @@
ink.numberone
smartjavaai-common
- 1.0.5
+ 1.0.6
ink.numberone
smartjavaai-face
- 1.0.5
+ 1.0.6
diff --git a/smartjavaai-common/pom.xml b/smartjavaai-common/pom.xml
index 8bcfa07..bffeb9b 100644
--- a/smartjavaai-common/pom.xml
+++ b/smartjavaai-common/pom.xml
@@ -6,7 +6,7 @@
ink.numberone
smartjavaai-parent
- 1.0.5
+ 1.0.6
smartjavaai-common
diff --git a/smartjavaai-face/pom.xml b/smartjavaai-face/pom.xml
index cb1e0d2..0f22a62 100644
--- a/smartjavaai-face/pom.xml
+++ b/smartjavaai-face/pom.xml
@@ -6,11 +6,11 @@
ink.numberone
smartjavaai-parent
- 1.0.5
+ 1.0.6
smartjavaai-face
- 1.0.5
+ 1.0.6
smartjavaai-face
SmartJavaAI
https://github.com/geekwenjie/SmartJavaAI
diff --git a/smartjavaai-face/src/main/java/cn/smartjavaai/face/algo/FeatureExtractionAlgo.java b/smartjavaai-face/src/main/java/cn/smartjavaai/face/algo/FeatureExtractionAlgo.java
index 9b10373..734474c 100644
--- a/smartjavaai-face/src/main/java/cn/smartjavaai/face/algo/FeatureExtractionAlgo.java
+++ b/smartjavaai-face/src/main/java/cn/smartjavaai/face/algo/FeatureExtractionAlgo.java
@@ -1,5 +1,6 @@
package cn.smartjavaai.face.algo;
+import ai.djl.Device;
import ai.djl.inference.Predictor;
import ai.djl.modality.cv.Image;
import ai.djl.modality.cv.ImageFactory;
@@ -14,6 +15,7 @@ import cn.smartjavaai.face.AbstractFaceAlgorithm;
import cn.smartjavaai.face.FaceDetectedResult;
import cn.smartjavaai.face.FaceDetectionTranslator;
import cn.smartjavaai.face.ModelConfig;
+import cn.smartjavaai.face.translator.FaceFeatureTranslator;
import org.apache.commons.lang3.StringUtils;
import java.io.InputStream;
@@ -50,32 +52,34 @@ public class FeatureExtractionAlgo extends AbstractFaceAlgorithm {
* 加载人脸特征提取模型
* @param config
* @throws Exception
- *//*
+ */
@Override
public void loadFaceFeatureModel(ModelConfig config) throws Exception {
String normalize = mean.stream().map(Object::toString).collect(Collectors.joining(","));
- faceFeatureCriteria = Criteria.builder()
+ faceFeatureCriteria =
+ Criteria.builder()
.setTypes(Image.class, float[].class)
+ .optModelName("face_feature") // specify model file prefix
.optModelUrls(StringUtils.isNotBlank(config.getModelPath()) ? null :
"https://resources.djl.ai/test-models/pytorch/face_feature.zip")
.optModelPath(StringUtils.isNotBlank(config.getModelPath()) ? Paths.get(config.getModelPath()) : null)
- .optModelName("face_feature") // specify model file prefix
+ .optTranslator(new FaceFeatureTranslator())
.optArgument("normalize", normalize)
- .optTranslatorFactory(new ImageFeatureExtractorFactory())
- .optProgress(new ProgressBar())
.optEngine("PyTorch") // Use PyTorch engine
+ .optProgress(new ProgressBar())
.build();
+
model = faceFeatureCriteria.loadModel();
predictor = model.newPredictor();
}
- *//**
+ /**
* 特征提取
* @param imagePath 图片路径
* @return
* @throws Exception
- *//*
+ */
@Override
public float[] featureExtraction(String imagePath) throws Exception {
Path imageFile = Paths.get(imagePath);
@@ -84,12 +88,12 @@ public class FeatureExtractionAlgo extends AbstractFaceAlgorithm {
return predictor.predict(img);
}
- *//**
+ /**
* 特征提取
* @param inputStream 输入流
* @return
* @throws Exception
- *//*
+ */
@Override
public float[] featureExtraction(InputStream inputStream) throws Exception {
Image img = ImageFactory.getInstance().fromInputStream(inputStream);
@@ -97,13 +101,13 @@ public class FeatureExtractionAlgo extends AbstractFaceAlgorithm {
return predictor.predict(img);
}
- *//**
+ /**
* 计算相似度
* @param feature1 图1特征
* @param feature2 图2特征
* @return
* @throws Exception
- *//*
+ */
@Override
public float calculSimilar(float[] feature1, float[] feature2) throws Exception {
float ret = 0.0f;
@@ -118,13 +122,13 @@ public class FeatureExtractionAlgo extends AbstractFaceAlgorithm {
return (float) ((ret / Math.sqrt(mod1) / Math.sqrt(mod2) + 1) / 2.0f);
}
- *//**
+ /**
* 特征比较
* @param imagePath1 图1路径
* @param imagePath2 图2路径
* @return
* @throws Exception
- *//*
+ */
@Override
public float featureComparison(String imagePath1, String imagePath2) throws Exception {
float[] feature1 = featureExtraction(imagePath1);
@@ -132,19 +136,19 @@ public class FeatureExtractionAlgo extends AbstractFaceAlgorithm {
return calculSimilar(feature1, feature2);
}
- *//**
+ /**
* 特征比较
* @param inputStream1 图1输入流
* @param inputStream2 图2输入流
* @return
* @throws Exception
- *//*
+ */
@Override
public float featureComparison(InputStream inputStream1, InputStream inputStream2) throws Exception {
float[] feature1 = featureExtraction(inputStream1);
float[] feature2 = featureExtraction(inputStream2);
return calculSimilar(feature1, feature2);
- }*/
+ }
/*@Override
public float[] recognize(FaceRegion region) {
diff --git a/smartjavaai-face/src/main/java/cn/smartjavaai/face/translator/FaceFeatureTranslator.java b/smartjavaai-face/src/main/java/cn/smartjavaai/face/translator/FaceFeatureTranslator.java
new file mode 100644
index 0000000..ec2d430
--- /dev/null
+++ b/smartjavaai-face/src/main/java/cn/smartjavaai/face/translator/FaceFeatureTranslator.java
@@ -0,0 +1,52 @@
+package cn.smartjavaai.face.translator;
+
+import ai.djl.modality.cv.Image;
+import ai.djl.modality.cv.transform.Normalize;
+import ai.djl.modality.cv.transform.Resize;
+import ai.djl.modality.cv.transform.ToTensor;
+import ai.djl.ndarray.NDArray;
+import ai.djl.ndarray.NDList;
+import ai.djl.translate.Batchifier;
+import ai.djl.translate.Pipeline;
+import ai.djl.translate.Translator;
+import ai.djl.translate.TranslatorContext;
+
+/**
+ * @author 邓文杰
+ * @date 2025/3/31
+ */
+public final class FaceFeatureTranslator implements Translator {
+
+ public FaceFeatureTranslator() {
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public NDList processInput(TranslatorContext ctx, Image input) {
+ NDArray array = input.toNDArray(ctx.getNDManager(), Image.Flag.COLOR);
+ Pipeline pipeline = new Pipeline();
+ pipeline
+ .add(new Resize(180))
+ .add(new ToTensor())
+ .add(new Normalize(
+ new float[]{127.5f / 255.0f, 127.5f / 255.0f, 127.5f / 255.0f},
+ new float[]{128.0f / 255.0f, 128.0f / 255.0f, 128.0f / 255.0f}));
+
+ return pipeline.transform(new NDList(array));
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public float[] processOutput(TranslatorContext ctx, NDList list) {
+ return list.singletonOrThrow().toFloatArray();
+ }
+
+ @Override
+ public Batchifier getBatchifier() {
+ return Batchifier.STACK;
+ }
+}
diff --git a/smartjavaai-face/src/main/java/com/seetaface/NativeLoader.java b/smartjavaai-face/src/main/java/com/seetaface/NativeLoader.java
index ad2d7dc..0e60b46 100644
--- a/smartjavaai-face/src/main/java/com/seetaface/NativeLoader.java
+++ b/smartjavaai-face/src/main/java/com/seetaface/NativeLoader.java
@@ -1,11 +1,15 @@
package com.seetaface;
+import jdk.dynalink.linker.support.Lookup;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.io.*;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.VarHandle;
import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
@@ -19,9 +23,10 @@ public class NativeLoader {
private static Path tempNativeDir;
- private static final String[] WIN_LIBS = {"tennis","tennis_haswell","tennis_pentium","tennis_sandy_bridge","SeetaAuthorize","SeetaFaceAntiSpoofingX600","SeetaFaceDetector600","SeetaFaceLandmarker600","SeetaFaceRecognizer610","SeetaFace6JNI"};
- private static final String[] LINUX_CENTOS_LIBS = {"libmain.so"};
- private static final String[] LINUX_UBUNTU_LIBS = {"libdependency1.so", "libdependency2.so", "libmain.so"};
+ private static final String[] WIN_LIBS = {"tennis.dll","tennis_haswell.dll","tennis_pentium.dll","tennis_sandy_bridge.dll","SeetaAuthorize.dll","SeetaFaceAntiSpoofingX600.dll","SeetaFaceDetector600.dll","SeetaFaceLandmarker600.dll","SeetaFaceRecognizer610.dll","SeetaFace6JNI.dll"};
+ //private static final String[] WIN_LIBS = {"tennis","tennis_haswell","tennis_pentium","tennis_sandy_bridge","SeetaAuthorize","SeetaFaceAntiSpoofingX600","SeetaFaceDetector600","SeetaFaceLandmarker600","SeetaFaceRecognizer610","SeetaFace6JNI"};
+ private static final String[] LINUX_CENTOS_LIBS = {"libSeetaAuthorize.so","libtennis.so","libtennis_haswell.so","libtennis_pentium.so","libtennis_sandy_bridge.so","libSeetaFaceDetector600.so","libSeetaAgePredictor600.so","libSeetaEyeStateDetector200.so","libSeetaFaceAntiSpoofingX600.so","libSeetaFaceLandmarker600.so","libSeetaFaceRecognizer610.so","libSeetaGenderPredictor600.so","libSeetaMaskDetector200.so","libSeetaPoseEstimation600.so","libSeetaFaceTracking600.so","libSeetaQualityAssessor300.so"};
+ private static final String[] LINUX_UBUNTU_LIBS = {"libSeetaAuthorize.so","libtennis.so","libtennis_haswell.so","libtennis_pentium.so","libtennis_sandy_bridge.so","libSeetaFaceDetector600.so","libSeetaAgePredictor600.so","libSeetaEyeStateDetector200.so","libSeetaFaceAntiSpoofingX600.so","libSeetaFaceLandmarker600.so","libSeetaFaceRecognizer610.so","libSeetaGenderPredictor600.so","libSeetaMaskDetector200.so","libSeetaPoseEstimation600.so","libSeetaFaceTracking600.so","libSeetaQualityAssessor300.so"};
private static final String TEMP_DIR = "smartjavaai-native-libs";
@@ -51,18 +56,12 @@ public class NativeLoader {
} else {
System.setProperty("java.library.path", sysLib + separator + tempNativeDir);
}
- try {
- //使java.library.path生效
- Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
- sysPathsField.setAccessible(true);
- sysPathsField.set(null, null);
- } catch (NoSuchFieldException | IllegalAccessException e) {
- e.printStackTrace();
- }
+
// 按顺序加载库(确保依赖关系)
for (String libName : libNames) {
- System.loadLibrary(libName);
+ log.info("Loading library: " + tempNativeDir + File.separator + libName);
+ System.load(tempNativeDir + File.separator + libName);
}
} catch (Exception e) {
throw new RuntimeException("Native library loading failed", e);
@@ -84,7 +83,7 @@ public class NativeLoader {
* @throws IOException
*/
private static void extractLibrary(String libName,String libDir) throws IOException {
- String resourcePath = "/native" + libDir + "/" + libName + ".dll";
+ String resourcePath = "/native" + libDir + "/" + libName;
try (InputStream in = NativeLoader.class.getResourceAsStream(resourcePath)) {
if (in == null) throw new FileNotFoundException(resourcePath);
@@ -107,7 +106,7 @@ public class NativeLoader {
String osName = System.getProperty("os.name").toLowerCase();
if (osName.contains("win")) {
return "/windows";
- } else if (osName.contains("linux")) {
+ } /*else if (osName.contains("linux")) {
String linuxOsName = getLinuxOsName();
if(StringUtils.isBlank(linuxOsName)){
throw new UnsupportedOperationException("Unsupported platform");
@@ -117,7 +116,7 @@ public class NativeLoader {
}else if(linuxOsName.contains("centos")){
return "/linux/centos";
}
- }
+ }*/
throw new UnsupportedOperationException("Unsupported platform");
}
diff --git a/smartjavaai-seetaface6-lib/pom.xml b/smartjavaai-seetaface6-lib/pom.xml
index 369977a..de5d13e 100644
--- a/smartjavaai-seetaface6-lib/pom.xml
+++ b/smartjavaai-seetaface6-lib/pom.xml
@@ -6,7 +6,7 @@
ink.numberone
smartjavaai-parent
- 1.0.5
+ 1.0.6
smartjavaai-seetaface6-lib
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaAgePredictor600.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaAgePredictor600.so
deleted file mode 100644
index cee2324..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaAgePredictor600.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaAuthorize.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaAuthorize.so
deleted file mode 100644
index 2560a78..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaAuthorize.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaEyeStateDetector200.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaEyeStateDetector200.so
deleted file mode 100644
index 862b21a..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaEyeStateDetector200.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaFaceAntiSpoofingX600.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaFaceAntiSpoofingX600.so
deleted file mode 100644
index da0d784..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaFaceAntiSpoofingX600.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaFaceDetector600.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaFaceDetector600.so
deleted file mode 100644
index 501087e..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaFaceDetector600.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaFaceLandmarker600.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaFaceLandmarker600.so
deleted file mode 100644
index e3263c7..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaFaceLandmarker600.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaFaceRecognizer610.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaFaceRecognizer610.so
deleted file mode 100644
index c023622..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaFaceRecognizer610.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaFaceTracking600.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaFaceTracking600.so
deleted file mode 100644
index 93265fa..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaFaceTracking600.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaGenderPredictor600.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaGenderPredictor600.so
deleted file mode 100644
index e23969f..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaGenderPredictor600.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaMaskDetector200.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaMaskDetector200.so
deleted file mode 100644
index dce9f73..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaMaskDetector200.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaPoseEstimation600.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaPoseEstimation600.so
deleted file mode 100644
index bd17c6d..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaPoseEstimation600.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaQualityAssessor300.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaQualityAssessor300.so
deleted file mode 100644
index 6a1f8a0..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libSeetaQualityAssessor300.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libtennis.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libtennis.so
deleted file mode 100644
index 06fee2b..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libtennis.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libtennis_haswell.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libtennis_haswell.so
deleted file mode 100644
index 3e357d0..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libtennis_haswell.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libtennis_pentium.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libtennis_pentium.so
deleted file mode 100644
index f60e405..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libtennis_pentium.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libtennis_sandy_bridge.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libtennis_sandy_bridge.so
deleted file mode 100644
index 3a0474d..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/centos/libtennis_sandy_bridge.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaAgePredictor600.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaAgePredictor600.so
deleted file mode 100644
index 0e489bd..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaAgePredictor600.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaAuthorize.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaAuthorize.so
deleted file mode 100644
index 446a8ad..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaAuthorize.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaEyeStateDetector200.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaEyeStateDetector200.so
deleted file mode 100644
index 7d74b9e..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaEyeStateDetector200.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaFaceAntiSpoofingX600.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaFaceAntiSpoofingX600.so
deleted file mode 100644
index 128751e..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaFaceAntiSpoofingX600.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaFaceDetector600.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaFaceDetector600.so
deleted file mode 100644
index 52307f0..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaFaceDetector600.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaFaceLandmarker600.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaFaceLandmarker600.so
deleted file mode 100644
index 92f230e..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaFaceLandmarker600.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaFaceRecognizer610.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaFaceRecognizer610.so
deleted file mode 100644
index d967d29..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaFaceRecognizer610.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaFaceTracking600.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaFaceTracking600.so
deleted file mode 100644
index bc647bf..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaFaceTracking600.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaGenderPredictor600.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaGenderPredictor600.so
deleted file mode 100644
index 9a26839..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaGenderPredictor600.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaMaskDetector200.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaMaskDetector200.so
deleted file mode 100644
index a894911..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaMaskDetector200.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaPoseEstimation600.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaPoseEstimation600.so
deleted file mode 100644
index 0730ebf..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaPoseEstimation600.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaQualityAssessor300.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaQualityAssessor300.so
deleted file mode 100644
index 0e6b50d..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libSeetaQualityAssessor300.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libtennis.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libtennis.so
deleted file mode 100644
index 37c2c3e..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libtennis.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libtennis_haswell.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libtennis_haswell.so
deleted file mode 100644
index 4a7c4d3..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libtennis_haswell.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libtennis_pentium.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libtennis_pentium.so
deleted file mode 100644
index 6bab905..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libtennis_pentium.so and /dev/null differ
diff --git a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libtennis_sandy_bridge.so b/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libtennis_sandy_bridge.so
deleted file mode 100644
index 3fcc830..0000000
Binary files a/smartjavaai-seetaface6-lib/src/main/resources/native/linux/ubuntu/libtennis_sandy_bridge.so and /dev/null differ