This commit is contained in:
dengwenjie
2025-05-10 07:33:15 +08:00
parent bef574cb91
commit 7327d80209
21 changed files with 1489 additions and 0 deletions

7
examples/.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
.idea
.idea/
target
log
*.iml
/.settings/
/logging.file_IS_UNDEFINED/

BIN
examples/db/faces-data.db Normal file

Binary file not shown.

287
examples/pom.xml Normal file
View File

@@ -0,0 +1,287 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cn.smartjavaai</groupId>
<artifactId>examples</artifactId>
<version>1.0.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<smartjavaai.version>1.0.12</smartjavaai.version>
<exec.mainClass>smartai.examples.face.FaceDemo2</exec.mainClass>
<javacv.version>1.5.10</javacv.version>
<javacv.platform.macosx-arm64>macosx-arm64</javacv.platform.macosx-arm64>
<javacv.platform.linux-x86_64>linux-x86_64</javacv.platform.linux-x86_64>
<javacv.platform.linux-arm64>linux-arm64</javacv.platform.linux-arm64>
<javacv.platform.windows-x86_64>windows-x86_64</javacv.platform.windows-x86_64>
<djl.platform.windows-x86_64>win-x86_64</djl.platform.windows-x86_64>
<djl.platform.linux-x86_64>linux-x86_64</djl.platform.linux-x86_64>
<djl.platform.linux-aarch64>linux-aarch64</djl.platform.linux-aarch64>
<djl.platform.osx-aarch64>osx-aarch64</djl.platform.osx-aarch64>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>cn.smartjavaai</groupId>
<artifactId>smartjavaai-bom</artifactId>
<version>${smartjavaai.version}</version>
<type>pom</type>
<!-- 注意这里是import -->
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.9.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.17.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j2-impl</artifactId>
<version>2.24.1</version>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.10.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.30</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.83</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.2</version>
</dependency>
<!--人脸识别模块-->
<dependency>
<groupId>cn.smartjavaai</groupId>
<artifactId>smartjavaai-face</artifactId>
</dependency>
<!--目标检测模块-->
<dependency>
<groupId>cn.smartjavaai</groupId>
<artifactId>smartjavaai-objectdetection</artifactId>
</dependency>
<!-- windows平台 (保留对应平台的配置,可以减小包大小)-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>${javacv.version}</version>
<classifier>${javacv.platform.windows-x86_64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>6.1.1-1.5.10</version>
<classifier>${javacv.platform.windows-x86_64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.26-1.5.10</version>
<classifier>${javacv.platform.windows-x86_64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.9.0-1.5.10</version>
<classifier>${javacv.platform.windows-x86_64}</classifier>
</dependency>
<!-- linux x86 平台 (保留对应平台的配置,可以减小包大小)-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>${javacv.version}</version>
<classifier>${javacv.platform.linux-x86_64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>6.1.1-1.5.10</version>
<classifier>${javacv.platform.linux-x86_64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.26-1.5.10</version>
<classifier>${javacv.platform.linux-x86_64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.9.0-1.5.10</version>
<classifier>${javacv.platform.linux-x86_64}</classifier>
</dependency>
<!-- macOS M系列 平台 (保留对应平台的配置,可以减小包大小)-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>${javacv.version}</version>
<classifier>${javacv.platform.macosx-arm64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>6.1.1-1.5.10</version>
<classifier>${javacv.platform.macosx-arm64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.26-1.5.10</version>
<classifier>${javacv.platform.macosx-arm64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.9.0-1.5.10</version>
<classifier>${javacv.platform.macosx-arm64}</classifier>
</dependency>
<!-- linux aarch64 平台 (保留对应平台的配置,可以减小包大小)-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>${javacv.version}</version>
<classifier>${javacv.platform.linux-arm64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>6.1.1-1.5.10</version>
<classifier>${javacv.platform.linux-arm64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.26-1.5.10</version>
<classifier>${javacv.platform.linux-arm64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.9.0-1.5.10</version>
<classifier>${javacv.platform.linux-arm64}</classifier>
</dependency>
</dependencies>
<build>
<finalName>example</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.3</version>
<configuration>
<!--如果不想在打包的后缀加上assembly.xml中设置的id可以加上下面的配置-->
<appendAssemblyId>false</appendAssemblyId>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<!-- 是否绑定依赖将外部jar包依赖加入到classPath中 -->
<addClasspath>true</addClasspath>
<!-- 依赖前缀,与之前设置的文件夹路径要匹配 -->
<classpathPrefix>lib/</classpathPrefix>
<!-- 执行的主程序入口 -->
<mainClass>smartai.examples.face.FaceDemo2</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!--绑定的maven操作-->
<phase>package</phase>
<goals>
<goal>assembly</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>aliyunmaven</id>
<name>阿里云公共仓库</name>
<url>https://maven.aliyun.com/repository/public</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
</project>

View File

@@ -0,0 +1,135 @@
package smartai.examples.face.attribute;
import cn.smartjavaai.common.entity.*;
import cn.smartjavaai.face.config.FaceModelConfig;
import cn.smartjavaai.face.config.FaceAttributeConfig;
import cn.smartjavaai.face.constant.LivenessConstant;
import cn.smartjavaai.face.enums.FaceModelEnum;
import cn.smartjavaai.face.enums.FaceAttributeModelEnum;
import cn.smartjavaai.face.exception.FaceException;
import cn.smartjavaai.face.factory.FaceModelFactory;
import cn.smartjavaai.face.factory.FaceAttributeModelFactory;
import cn.smartjavaai.face.model.attribute.FaceAttributeModel;
import cn.smartjavaai.face.model.facerec.FaceModel;
import cn.smartjavaai.face.utils.FaceUtils;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameUtils;
import org.junit.Test;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.List;
/**
* 人脸属性检测demo
* @author dwj
* @date 2025/5/1
*/
@Slf4j
public class FaceAttributeDetDemo {
/**
* 人脸属性检测(多人脸)
*/
@Test
public void testFaceAttributeDetect(){
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);
DetectionResponse detectionResponse = faceAttributeModel.detect("src/main/resources/double_person.png");
try {
//绘制并导出人脸属性图片,小人脸仅有人脸框
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/double_person.png").toAbsolutePath().toString()));
FaceUtils.drawBoxesWithFaceAttribute(image, detectionResponse,"C:/Users/Administrator/Downloads/double_person_.png");
} catch (IOException e) {
e.printStackTrace();
}
log.info("人脸属性检测结果:{}", JSONObject.toJSONString(detectionResponse));
}
/**
* 图片人脸属性检测(分数最高人脸)
*/
@Test
public void testFaceAttributeDetect2(){
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);
FaceAttribute faceAttribute = faceAttributeModel.detectTopFace("src/main/resources/double_person.png");
log.info("人脸属性检测结果:{}", JSONObject.toJSONString(faceAttribute));
}
/**
* 图片多人脸属性检测(基于已检测出的人脸区域和关键点)
*/
@Test
public void testFaceAttributeDetect3(){
//人脸检测
//需替换为实际模型存储路径
String modelPath = "C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models";
FaceModelConfig faceDetectModelConfig = new FaceModelConfig();
faceDetectModelConfig.setModelEnum(FaceModelEnum.SEETA_FACE6_MODEL);
faceDetectModelConfig.setModelPath(modelPath);
FaceModel faceDetectModel = FaceModelFactory.getInstance().getModel(faceDetectModelConfig);
DetectionResponse detectionResponse = faceDetectModel.detect("src/main/resources/double_person.png");
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectionResponse));
//检测到人脸
if(detectionResponse != null && detectionResponse.getDetectionInfoList() != null && detectionResponse.getDetectionInfoList().size() > 0){
//人脸属性检测
FaceAttributeConfig config = new FaceAttributeConfig();
config.setModelEnum(FaceAttributeModelEnum.SEETA_FACE6_MODEL);
config.setModelPath(modelPath);
FaceAttributeModel faceAttributeModel = FaceAttributeModelFactory.getInstance().getModel(config);
List<FaceAttribute> livenessStatusList = faceAttributeModel.detect("src/main/resources/double_person.png",detectionResponse);
log.info("人脸属性检测结果:{}", JSONObject.toJSONString(livenessStatusList));
}
}
/**
* 图片单人脸人脸属性检测(基于已检测出的人脸区域和关键点)
*/
@Test
public void testFaceAttributeDetect4(){
try {
//人脸检测
//需替换为实际模型存储路径
String modelPath = "C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models";
String imagePath = "src/main/resources/double_person.png";
FaceModelConfig faceDetectModelConfig = new FaceModelConfig();
faceDetectModelConfig.setModelEnum(FaceModelEnum.SEETA_FACE6_MODEL);
faceDetectModelConfig.setModelPath(modelPath);
FaceModel faceDetectModel = FaceModelFactory.getInstance().getModel(faceDetectModelConfig);
DetectionResponse detectionResponse = faceDetectModel.detect(imagePath);
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectionResponse));
//检测到人脸
if(detectionResponse != null && detectionResponse.getDetectionInfoList() != null && detectionResponse.getDetectionInfoList().size() > 0){
//人脸属性检测
FaceAttributeConfig config = new FaceAttributeConfig();
config.setModelEnum(FaceAttributeModelEnum.SEETA_FACE6_MODEL);
config.setModelPath(modelPath);
FaceAttributeModel faceAttributeModel = FaceAttributeModelFactory.getInstance().getModel(config);
BufferedImage image = ImageIO.read(new File(Paths.get(imagePath).toAbsolutePath().toString()));
for (DetectionInfo detectionInfo : detectionResponse.getDetectionInfoList()){
FaceInfo faceInfo = detectionInfo.getFaceInfo();
FaceAttribute faceAttribute = faceAttributeModel.detect(image, detectionInfo.getDetectionRectangle(), faceInfo.getKeyPoints());
log.info("人脸属性检测结果:{}", JSONObject.toJSONString(faceAttribute));
}
}
} catch (Exception e){
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,155 @@
package smartai.examples.face.facerec;
import cn.smartjavaai.face.config.FaceExtractConfig;
import cn.smartjavaai.face.config.FaceModelConfig;
import cn.smartjavaai.face.entity.FaceResult;
import cn.smartjavaai.face.enums.FaceModelEnum;
import cn.smartjavaai.face.factory.FaceModelFactory;
import cn.smartjavaai.face.model.facerec.FaceModel;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Test;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
/**
* FaceNet人脸算法模型demo
* 支持功能人脸特征提取、人脸比对11
* @author dwj
* @date 2025/4/11
*/
@Slf4j
public class FaceNetDemo {
/**
* 提取人脸特征(支持多人脸)
* 默认使用检测模型FACENET_FEATURE_EXTRACTION
* 自动裁剪人脸 + 人脸对齐
*/
@Test
public void testExtractFeatures(){
try {
//人脸特征提取模型
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.FACENET_FEATURE_EXTRACTION);
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
List<float[]> faceResult = faceModel.extractFeatures("src/main/resources/kana1.jpg");
log.info("人脸特征提取结果:{}", JSONObject.toJSONString(faceResult));
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 提取人脸特征(支持多人脸,自定义配置)
* 自动裁剪人脸 + 人脸对齐
*/
@Test
public void testExtractFeaturesWithCustomConfig(){
try {
//人脸特征提取模型
FaceModel faceModel = FaceModelFactory.getInstance().getModel(
new FaceModelConfig(FaceModelEnum.FACENET_FEATURE_EXTRACTION));
//人脸特征提取参数
FaceExtractConfig extractConfig = new FaceExtractConfig();
//人脸检测模型配置
extractConfig.setDetectModelConfig(new FaceModelConfig(FaceModelEnum.ULTRA_LIGHT_FAST_GENERIC_FACE));
List<float[]> faceResult = faceModel.extractFeatures("src/main/resources/kana1.jpg",extractConfig);
log.info("人脸特征提取结果:{}", JSONObject.toJSONString(faceResult));
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 提取人脸特征(分数最高人脸)
* 默认使用检测模型FACENET_FEATURE_EXTRACTION
* 自动裁剪人脸 + 人脸对齐
*/
@Test
public void testExtractTopFaceFeature(){
try {
//人脸特征提取模型
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.FACENET_FEATURE_EXTRACTION);
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
float[] faceResult = faceModel.extractTopFaceFeature("src/main/resources/kana1.jpg");
log.info("人脸特征提取结果:{}", JSONObject.toJSONString(faceResult));
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 提取人脸特征(分数最高人脸,自定义配置)
* 自动裁剪人脸 + 人脸对齐
*/
@Test
public void testExtractTopFaceFeatureWithCustomConfig(){
try {
//人脸特征提取模型
FaceModel faceModel = FaceModelFactory.getInstance().getModel(
new FaceModelConfig(FaceModelEnum.FACENET_FEATURE_EXTRACTION));
//人脸特征提取参数
FaceExtractConfig extractConfig = new FaceExtractConfig();
//人脸检测模型配置
extractConfig.setDetectModelConfig(new FaceModelConfig(FaceModelEnum.ULTRA_LIGHT_FAST_GENERIC_FACE));
float[] faceResult = faceModel.extractTopFaceFeature("src/main/resources/kana1.jpg");
log.info("人脸特征提取结果:{}", JSONObject.toJSONString(faceResult));
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 人脸比对11-在线模型
* 图片参数:图片路径
* @throws Exception
*/
@Test
public void featureComparison(){
try {
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.FACENET_FEATURE_EXTRACTION);//人脸模型
//config.setModelPath("/Users/xxx/Documents/develop/face_model/model_ir_se50.pth");
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
//自动裁剪人脸并比对人脸特征
float similar = faceModel.featureComparison("src/main/resources/kana1.jpg","src/main/resources/kana2.jpg");
log.info("相似度:{}", similar);
}
catch (Exception e){
e.printStackTrace();
}
}
/**
* 人脸比对11- 使用离线模型
* 图片参数:图片路径
* @throws Exception
*/
@Test
public void featureComparisonOffline(){
try {
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.FACENET_FEATURE_EXTRACTION);//人脸模型
config.setModelPath("/Users/xxx/Documents/develop/face_model/face_feature.pt");
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
//自动裁剪人脸并比对人脸特征
float similar = faceModel.featureComparison("src/main/resources/kana1.jpg","src/main/resources/kana2.jpg");
log.info("相似度:{}", similar);
}
catch (Exception e){
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,35 @@
package smartai.examples.face.facerec;
import cn.smartjavaai.common.entity.DetectionResponse;
import cn.smartjavaai.common.enums.DeviceEnum;
import cn.smartjavaai.face.config.FaceModelConfig;
import cn.smartjavaai.face.enums.FaceModelEnum;
import cn.smartjavaai.face.factory.FaceModelFactory;
import cn.smartjavaai.face.model.facerec.FaceModel;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
/**
* GPU 人脸检测
* @author dwj
* @date 2025/4/14
*/
@Slf4j
public class GpuFaceDemo {
/**
* 人脸检测(GPU)
* 图片参数:图片路径
*/
@Test
public void testFaceGpu(){
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.RETINA_FACE);//人脸模型
config.setDevice(DeviceEnum.GPU);
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
DetectionResponse detectedResult = faceModel.detect("src/main/resources/largest_selfie.jpg");
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectedResult));
}
}

View File

@@ -0,0 +1,98 @@
package smartai.examples.face.facerec;
import cn.smartjavaai.common.entity.DetectionResponse;
import cn.smartjavaai.face.config.FaceModelConfig;
import cn.smartjavaai.face.enums.FaceModelEnum;
import cn.smartjavaai.face.factory.FaceModelFactory;
import cn.smartjavaai.face.model.facerec.FaceModel;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Test;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
/**
* UltraLightFastGenericFaceModel 轻量人脸算法模型demo
* 支持功能:人脸检测(不支持人脸特征提取)
* @author dwj
* @date 2025/4/11
*/
@Slf4j
public class LightFaceDemo {
/**
* 人脸检测-自定义参数
* 图片参数:图片路径
*/
@Test
public void testFaceDetectCustomConfig(){
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.ULTRA_LIGHT_FAST_GENERIC_FACE);//人脸模型
//config.setConfidenceThreshold(FaceConfig.DEFAULT_CONFIDENCE_THRESHOLD);//只返回相似度大于该值的人脸
//config.setNmsThresh(FaceConfig.NMS_THRESHOLD);//用于去除重复的人脸框,当两个框的重叠度超过该值时,只保留一个
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
DetectionResponse detectedResult = faceModel.detect("src/main/resources/largest_selfie.jpg");
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectedResult));
}
/**
* 人脸检测并绘制人脸框
*/
@Test
public void testFaceDetectAndDraw(){
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.ULTRA_LIGHT_FAST_GENERIC_FACE);//人脸模型
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
faceModel.detectAndDraw("src/main/resources/largest_selfie.jpg","output/largest_selfie_detected.png");
}
/**
* 人脸检测并绘制人脸框,返回BufferedImage
*
*/
@Test
public void testFaceDetectAndDraw2(){
try {
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.ULTRA_LIGHT_FAST_GENERIC_FACE);//人脸模型
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
BufferedImage image = null;
String imagePath = "src/main/resources/largest_selfie.jpg";
image = ImageIO.read(new File(Paths.get(imagePath).toAbsolutePath().toString()));
//可以根据后续业务场景使用detectedImage
BufferedImage detectedImage = faceModel.detectAndDraw(image);
Assert.assertNotNull("detectedImage null", detectedImage);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 人脸检测(离线模型)
*/
@Test
public void testDetectFaceOffine(){
try {
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.ULTRA_LIGHT_FAST_GENERIC_FACE);//人脸模型
//模型路径,不同模型下载路径请参看文档
config.setModelPath("/Users/xxx/Documents/develop/face_model/ultranet.pt");
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
DetectionResponse detectedResult = faceModel.detect("src/main/resources/largest_selfie.jpg");
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectedResult));
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,107 @@
package smartai.examples.face.facerec;
import cn.smartjavaai.common.entity.DetectionResponse;
import cn.smartjavaai.face.config.FaceModelConfig;
import cn.smartjavaai.face.constant.FaceDetectConstant;
import cn.smartjavaai.face.enums.FaceModelEnum;
import cn.smartjavaai.face.exception.FaceException;
import cn.smartjavaai.face.factory.FaceModelFactory;
import cn.smartjavaai.face.model.facerec.FaceModel;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Test;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
/**
* RetinaFace人脸算法模型demo
* 支持功能:人脸检测(不支持人脸特征提取)
* @author dwj
* @date 2025/4/11
*/
@Slf4j
public class RetinaFaceDemo {
/**
* 人脸检测(默认配置)
* 使用默认模型参数检测默认模型retinaface需联网会自动下载模型
* 图片参数:图片路径
*/
@Test
public void testFaceDetect(){
FaceModel faceModel = FaceModelFactory.getInstance().getModel();
DetectionResponse detectedResult = faceModel.detect("src/main/resources/largest_selfie.jpg");
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectedResult));
}
/**
* 人脸检测(自定义模型参数)
* 图片参数:图片路径
*/
@Test
public void testFaceDetectCustomConfig(){
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.RETINA_FACE);//人脸模型
config.setConfidenceThreshold(FaceDetectConstant.DEFAULT_CONFIDENCE_THRESHOLD);//只返回相似度大于该值的人脸
config.setNmsThresh(FaceDetectConstant.NMS_THRESHOLD);//用于去除重复的人脸框,当两个框的重叠度超过该值时,只保留一个
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
DetectionResponse detectedResult = faceModel.detect("src/main/resources/largest_selfie.jpg");
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectedResult));
}
/**
* 人脸检测并绘制人脸框
*/
@Test
public void testFaceDetectAndDraw(){
FaceModel faceModel = FaceModelFactory.getInstance().getModel();
faceModel.detectAndDraw("src/main/resources/largest_selfie.jpg","output/largest_selfie_detected.png");
}
/**
* 人脸检测并绘制人脸框,返回BufferedImage
*
*/
@Test
public void testFaceDetectAndDraw2(){
try {
FaceModel faceModel = FaceModelFactory.getInstance().getModel();
BufferedImage image = null;
String imagePath = "src/main/resources/largest_selfie.jpg";
image = ImageIO.read(new File(Paths.get(imagePath).toAbsolutePath().toString()));
//可以根据后续业务场景使用detectedImage
BufferedImage detectedImage = faceModel.detectAndDraw(image);
Assert.assertNotNull("detectedImage null", detectedImage);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 人脸检测(离线模型)
*/
@Test
public void testDetectFaceOffine(){
try {
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.RETINA_FACE);//人脸模型
//模型路径,不同模型下载路径请参看文档
config.setModelPath("/Users/xxx/Documents/develop/face_model/retinaface.pt");
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
DetectionResponse detectedResult = faceModel.detect("src/main/resources/largest_selfie.jpg");
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectedResult));
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,251 @@
package smartai.examples.face.facerec;
import cn.smartjavaai.common.entity.DetectionResponse;
import cn.smartjavaai.face.config.FaceModelConfig;
import cn.smartjavaai.face.entity.FaceResult;
import cn.smartjavaai.face.enums.FaceModelEnum;
import cn.smartjavaai.face.factory.FaceModelFactory;
import cn.smartjavaai.face.model.facerec.FaceModel;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Test;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
/**
* SeetaFace6人脸算法模型demo
* 支持系统windows 64位
* 支持功能人脸检测、人脸特征提取、人脸比对11、人脸比对1N、人脸注册
* @author dwj
* @date 2025/4/11
*/
@Slf4j
public class SeetaFace6Demo {
/**
* 人脸检测(自定义模型参数)
* 图片参数:图片路径
*/
@Test
public void testFaceDetectCustomConfig(){
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.SEETA_FACE6_MODEL);//人脸模型
config.setModelPath("C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models");
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
DetectionResponse detectedResult = faceModel.detect("src/main/resources/largest_selfie.jpg");
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectedResult));
}
/**
* 人脸检测并绘制人脸框
*/
@Test
public void testFaceDetectAndDraw(){
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.SEETA_FACE6_MODEL);//人脸模型
config.setModelPath("C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models");
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
faceModel.detectAndDraw("src/main/resources/largest_selfie.jpg","output/largest_selfie_detected.png");
}
/**
* 人脸检测并绘制人脸框,返回BufferedImage
*
*/
@Test
public void testFaceDetectAndDraw2(){
try {
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.SEETA_FACE6_MODEL);//人脸模型
config.setModelPath("C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models");
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
BufferedImage image = null;
String imagePath = "src/main/resources/largest_selfie.jpg";
image = ImageIO.read(new File(Paths.get(imagePath).toAbsolutePath().toString()));
//可以根据后续业务场景使用detectedImage
BufferedImage detectedImage = faceModel.detectAndDraw(image);
Assert.assertNotNull("detectedImage null", detectedImage);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 提取人脸特征(支持多人脸)
* 自动裁剪人脸 + 人脸对齐
*/
@Test
public void testExtractFeatures(){
try {
FaceModel faceModel = FaceModelFactory.getInstance().getModel(new FaceModelConfig(FaceModelEnum.SEETA_FACE6_MODEL,
"C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models"));
List<float[]> faceResult = faceModel.extractFeatures("src/main/resources/kana1.jpg");
log.info("人脸特征提取结果:{}", JSONObject.toJSONString(faceResult));
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 提取人脸特征(分数最高人脸)
* 自动裁剪人脸 + 人脸对齐
*/
@Test
public void testExtractTopFaceFeature(){
try {
FaceModel faceModel = FaceModelFactory.getInstance().getModel(new FaceModelConfig(FaceModelEnum.SEETA_FACE6_MODEL,
"C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models"));
float[] faceResult = faceModel.extractTopFaceFeature("src/main/resources/kana1.jpg");
log.info("人脸特征提取结果:{}", JSONObject.toJSONString(faceResult));
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 人脸比对11
* 图片参数:图片路径
* @throws Exception
*/
@Test
public void featureComparison(){
try {
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.SEETA_FACE6_MODEL);//人脸模型
config.setModelPath("C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models");
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
//自动裁剪人脸并比对人脸特征
float similar = faceModel.featureComparison("src/main/resources/kana1.jpg","src/main/resources/kana2.jpg");
log.info("相似度:{}", similar);
}
catch (Exception e){
e.printStackTrace();
}
}
/**
* 人脸比对11
* 先特征提取,后比对人脸特征
* 提取人脸特征图片参数:图片路径
*/
@Test
public void featureExtractionAndCompare(){
try {
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.SEETA_FACE6_MODEL);//人脸模型
config.setModelPath("C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models");
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
//提取图像中最大人脸的特征
float[] feature1 = faceModel.extractTopFaceFeature("src/main/resources/kana1.jpg");
float[] feature2 = faceModel.extractTopFaceFeature("src/main/resources/kana2.jpg");
if(feature1 != null && feature2 != null){
float similar = faceModel.calculSimilar(feature1, feature2);
log.info("相似度:{}", similar);
}else{
log.warn("人脸特征提取失败");
}
}
catch (Exception e){
e.printStackTrace();
}
}
/**
* 注册人脸
* 图片参数:图片路径
*/
@Test
public void registerFace(){
try {
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.SEETA_FACE6_MODEL);//人脸模型
//人脸库路径,从项目中 db/faces-data.db下载到本地
config.setFaceDbPath("C:/Users/Administrator/Downloads/faces-data.db");
config.setModelPath("C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models");
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
//等待人脸库加载完毕
Thread.sleep(1000);
//注册kana1人脸参数key建议设置为人名
boolean isSuccss = faceModel.register("kana1","src/main/resources/kana1.jpg");
log.info("注册结果:{}", isSuccss);
}
catch (Exception e){
e.printStackTrace();
}
}
/**
* 搜索人脸1N
* 图片参数:图片路径
* 注意事项:请先注册人脸
*/
@Test
public void searchFace(){
try {
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.SEETA_FACE6_MODEL);//人脸模型
//人脸库路径,从项目中 db/faces-data.db下载到本地
config.setFaceDbPath("C:/Users/Administrator/Downloads/faces-data.db");
config.setModelPath("C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models");
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
//等待人脸库加载完毕
Thread.sleep(1000);
FaceResult faceResult = faceModel.search("src/main/resources/kana1.jpg");
if(faceResult != null){
log.info("查询到人脸:{}", faceResult.toString());
}else{
log.info("未查询到人脸");
}
}
catch (Exception e){
e.printStackTrace();
}
}
/**
* 删除已注册人脸
* 注意事项:请先注册人脸
*/
@Test
public void removeRegisterFace(){
try {
FaceModelConfig config = new FaceModelConfig();
config.setModelEnum(FaceModelEnum.SEETA_FACE6_MODEL);//人脸模型
//人脸库路径,从项目中 db/faces-data.db下载到本地
config.setFaceDbPath("C:/Users/Administrator/Downloads/faces-data.db");
config.setModelPath("C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models");
FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
//等待人脸库加载完毕
Thread.sleep(1000);
//使用注册人脸时的key值删除可一次性删除单个
long num = faceModel.removeRegister("kana1");
//删除全部人脸
//long num = currentAlgorithm.clearFace();
log.info("删除成功数量:" + num);
}
catch (Exception e){
e.printStackTrace();
}
}
}

View File

@@ -0,0 +1,283 @@
package smartai.examples.face.liveness;
import cn.smartjavaai.common.entity.DetectionInfo;
import cn.smartjavaai.common.entity.DetectionRectangle;
import cn.smartjavaai.common.entity.DetectionResponse;
import cn.smartjavaai.common.entity.FaceInfo;
import cn.smartjavaai.common.enums.DeviceEnum;
import cn.smartjavaai.common.enums.LivenessStatus;
import cn.smartjavaai.face.config.FaceModelConfig;
import cn.smartjavaai.face.config.LivenessConfig;
import cn.smartjavaai.face.constant.LivenessConstant;
import cn.smartjavaai.face.enums.FaceModelEnum;
import cn.smartjavaai.face.enums.LivenessModelEnum;
import cn.smartjavaai.face.exception.FaceException;
import cn.smartjavaai.face.factory.FaceModelFactory;
import cn.smartjavaai.face.factory.LivenessModelFactory;
import cn.smartjavaai.face.model.facerec.FaceModel;
import cn.smartjavaai.face.model.liveness.LivenessDetModel;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.Frame;
import org.bytedeco.javacv.Java2DFrameUtils;
import org.junit.Test;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.nio.file.Paths;
import java.util.List;
/**
* 静态活体检测demo
* @author dwj
* @date 2025/5/1
*/
@Slf4j
public class LivenessDetDemo {
/**
* 图片活体检测(多人脸)
*/
@Test
public void testLivenessDetect(){
LivenessConfig config = new LivenessConfig();
config.setModelEnum(LivenessModelEnum.SEETA_FACE6_MODEL);
config.setDevice(DeviceEnum.GPU);
//需替换为实际模型存储路径
config.setModelPath("C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models");
//人脸清晰度阈值,可选,默认0.3活体识别时如果清晰度低的话就会直接返回FUZZY清晰度满足阈值则判断真实度
config.setFaceClarityThreshold(LivenessConstant.DEFAULT_FACE_CLARITY_THRESHOLD);
//人脸活体阈值,可选,默认0.8,超过阈值则认为是真人,低于阈值是非活体
config.setRealityThreshold(LivenessConstant.DEFAULT_REALITY_THRESHOLD);
LivenessDetModel livenessDetModel = LivenessModelFactory.getInstance().getModel(config);
DetectionResponse livenessStatusList = livenessDetModel.detect("src/main/resources/double_person.png");
log.info("活体检测结果:{}", JSONObject.toJSONString(livenessStatusList));
}
/**
* 图片活体检测(分数最高人脸)
*/
@Test
public void testLivenessDetect2(){
LivenessConfig config = new LivenessConfig();
config.setModelEnum(LivenessModelEnum.SEETA_FACE6_MODEL);
//需替换为实际模型存储路径
config.setModelPath("C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models");
//人脸清晰度阈值,可选,默认0.3活体识别时如果清晰度低的话就会直接返回FUZZY清晰度满足阈值则判断真实度
config.setFaceClarityThreshold(LivenessConstant.DEFAULT_FACE_CLARITY_THRESHOLD);
//人脸活体阈值,可选,默认0.8,超过阈值则认为是真人,低于阈值是非活体
config.setRealityThreshold(LivenessConstant.DEFAULT_REALITY_THRESHOLD);
LivenessDetModel livenessDetModel = LivenessModelFactory.getInstance().getModel(config);
LivenessStatus livenessStatus = livenessDetModel.detectTopFace("src/main/resources/double_person.png");
log.info("活体检测结果:{}", JSONObject.toJSONString(livenessStatus));
}
/**
* 图片多人脸活体检测(基于已检测出的人脸区域和关键点)
*/
@Test
public void testLivenessDetect3(){
//人脸检测
//需替换为实际模型存储路径
String modelPath = "C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models";
FaceModelConfig faceDetectModelConfig = new FaceModelConfig();
faceDetectModelConfig.setModelEnum(FaceModelEnum.SEETA_FACE6_MODEL);
faceDetectModelConfig.setModelPath(modelPath);
FaceModel faceDetectModel = FaceModelFactory.getInstance().getModel(faceDetectModelConfig);
DetectionResponse detectionResponse = faceDetectModel.detect("src/main/resources/double_person.png");
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectionResponse));
//检测到人脸
if(detectionResponse != null && detectionResponse.getDetectionInfoList() != null && detectionResponse.getDetectionInfoList().size() > 0){
//活体检测
LivenessConfig config = new LivenessConfig();
config.setModelEnum(LivenessModelEnum.SEETA_FACE6_MODEL);
config.setModelPath(modelPath);
//人脸清晰度阈值,可选,默认0.3活体识别时如果清晰度低的话就会直接返回FUZZY清晰度满足阈值则判断真实度
config.setFaceClarityThreshold(LivenessConstant.DEFAULT_FACE_CLARITY_THRESHOLD);
//人脸活体阈值,可选,默认0.8,超过阈值则认为是真人,低于阈值是非活体
config.setRealityThreshold(LivenessConstant.DEFAULT_REALITY_THRESHOLD);
LivenessDetModel livenessDetModel = LivenessModelFactory.getInstance().getModel(config);
List<LivenessStatus> livenessStatusList = livenessDetModel.detect("src/main/resources/double_person.png",detectionResponse);
log.info("活体检测结果:{}", JSONObject.toJSONString(livenessStatusList));
}
}
/**
* 图片单人脸活体检测(基于已检测出的人脸区域和关键点)
*/
@Test
public void testLivenessDetect4(){
try {
//人脸检测
//需替换为实际模型存储路径
String modelPath = "C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models";
String imagePath = "src/main/resources/double_person.png";
FaceModelConfig faceDetectModelConfig = new FaceModelConfig();
faceDetectModelConfig.setModelEnum(FaceModelEnum.SEETA_FACE6_MODEL);
faceDetectModelConfig.setModelPath(modelPath);
FaceModel faceDetectModel = FaceModelFactory.getInstance().getModel(faceDetectModelConfig);
DetectionResponse detectionResponse = faceDetectModel.detect(imagePath);
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectionResponse));
//检测到人脸
if(detectionResponse != null && detectionResponse.getDetectionInfoList() != null && detectionResponse.getDetectionInfoList().size() > 0){
//活体检测
LivenessConfig config = new LivenessConfig();
config.setModelEnum(LivenessModelEnum.SEETA_FACE6_MODEL);
config.setModelPath(modelPath);
//人脸清晰度阈值,可选,默认0.3活体识别时如果清晰度低的话就会直接返回FUZZY清晰度满足阈值则判断真实度
config.setFaceClarityThreshold(LivenessConstant.DEFAULT_FACE_CLARITY_THRESHOLD);
//人脸活体阈值,可选,默认0.8,超过阈值则认为是真人,低于阈值是非活体
config.setRealityThreshold(LivenessConstant.DEFAULT_REALITY_THRESHOLD);
LivenessDetModel livenessDetModel = LivenessModelFactory.getInstance().getModel(config);
BufferedImage image = ImageIO.read(new File(Paths.get(imagePath).toAbsolutePath().toString()));
for (DetectionInfo detectionInfo : detectionResponse.getDetectionInfoList()){
FaceInfo faceInfo = detectionInfo.getFaceInfo();
LivenessStatus livenessStatus = livenessDetModel.detect(image, detectionInfo.getDetectionRectangle(), faceInfo.getKeyPoints());
log.info("活体检测结果:{}", JSONObject.toJSONString(livenessStatus));
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 视频活体检测
*/
@Test
public void testLivenessDetectVideo(){
LivenessConfig config = new LivenessConfig();
config.setModelEnum(LivenessModelEnum.SEETA_FACE6_MODEL);
//需替换为实际模型存储路径
config.setModelPath("C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models");
//人脸清晰度阈值,可选,默认0.3活体识别时如果清晰度低的话就会直接返回FUZZY清晰度满足阈值则判断真实度
config.setFaceClarityThreshold(LivenessConstant.DEFAULT_FACE_CLARITY_THRESHOLD);
//人脸活体阈值,可选,默认0.8,超过阈值则认为是真人,低于阈值是非活体
config.setRealityThreshold(LivenessConstant.DEFAULT_REALITY_THRESHOLD);
/*视频检测帧数可选默认10输出帧数超过这个number之后就可以输出识别结果。
这个数量相当于多帧识别结果融合的融合的帧数。当输入的帧数超过设定帧数的时候,会采用滑动窗口的方式,返回融合的最近输入的帧融合的识别结果。
一般来说在10以内帧数越多结果越稳定相对性能越好但是得到结果的延时越高。*/
config.setFrameCount(LivenessConstant.DEFAULT_FRAME_COUNT);
LivenessDetModel livenessDetModel = LivenessModelFactory.getInstance().getModel(config);
LivenessStatus livenessStatus = livenessDetModel.detectVideo("src/main/resources/girl.mp4");
log.info("视频活体检测结果:{}", JSONObject.toJSONString(livenessStatus));
}
/**
* 视频活体检测(逐帧检测,基于已检测出的人脸区域和关键点)
*/
@Test
public void testLivenessDetectVideo2(){
LivenessConfig config = new LivenessConfig();
config.setModelEnum(LivenessModelEnum.SEETA_FACE6_MODEL);
//需替换为实际模型存储路径
config.setModelPath("C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models");
//人脸清晰度阈值,可选,默认0.3活体识别时如果清晰度低的话就会直接返回FUZZY清晰度满足阈值则判断真实度
config.setFaceClarityThreshold(LivenessConstant.DEFAULT_FACE_CLARITY_THRESHOLD);
//人脸活体阈值,可选,默认0.8,超过阈值则认为是真人,低于阈值是非活体
config.setRealityThreshold(LivenessConstant.DEFAULT_REALITY_THRESHOLD);
/* 视频检测帧数可选默认10输出帧数超过这个number之后就可以输出识别结果。
这个数量相当于多帧识别结果融合的融合的帧数。当输入的帧数超过设定帧数的时候,会采用滑动窗口的方式,返回融合的最近输入的帧融合的识别结果。
一般来说在10以内帧数越多结果越稳定相对性能越好但是得到结果的延时越高。*/
config.setFrameCount(LivenessConstant.DEFAULT_FRAME_COUNT);
LivenessDetModel livenessDetModel = LivenessModelFactory.getInstance().getModel(config);
try {
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber("src/main/resources/girl.mp4");
grabber.start();
// 获取视频总帧数
int totalFrames = grabber.getLengthInFrames();
log.info("视频总帧数:{},检测帧数:{}", totalFrames, config.getFrameCount());
//活体检测结果
LivenessStatus livenessStatus = LivenessStatus.UNKNOWN;
// 逐帧处理视频
for (int frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
// 获取当前帧
Frame frame = grabber.grabImage();
if (frame != null) {
BufferedImage bufferedImage = Java2DFrameUtils.toBufferedImage(frame);
LivenessStatus livenessStatusFrame = livenessDetModel.detectVideoByFrame(bufferedImage);
//满足检测帧数之后停止检测
if(livenessStatusFrame != LivenessStatus.DETECTING){
livenessStatus = livenessStatusFrame;
}
}
}
log.info("视频活体检测结果:{}", JSONObject.toJSONString(livenessStatus));
grabber.stop();
} catch (FFmpegFrameGrabber.Exception e) {
throw new FaceException(e);
}
}
/**
* 视频活体检测(逐帧检测)
*/
@Test
public void testLivenessDetectVideo3(){
//获取活体检测模型
//需替换为实际模型存储路径
String modelPath = "C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models";
LivenessConfig config = new LivenessConfig();
config.setModelEnum(LivenessModelEnum.SEETA_FACE6_MODEL);
config.setModelPath(modelPath);
//人脸清晰度阈值,可选,默认0.3活体识别时如果清晰度低的话就会直接返回FUZZY清晰度满足阈值则判断真实度
config.setFaceClarityThreshold(LivenessConstant.DEFAULT_FACE_CLARITY_THRESHOLD);
//人脸活体阈值,可选,默认0.8,超过阈值则认为是真人,低于阈值是非活体
config.setRealityThreshold(LivenessConstant.DEFAULT_REALITY_THRESHOLD);
/* 视频检测帧数可选默认10输出帧数超过这个number之后就可以输出识别结果。
这个数量相当于多帧识别结果融合的融合的帧数。当输入的帧数超过设定帧数的时候,会采用滑动窗口的方式,返回融合的最近输入的帧融合的识别结果。
一般来说在10以内帧数越多结果越稳定相对性能越好但是得到结果的延时越高。*/
config.setFrameCount(LivenessConstant.DEFAULT_FRAME_COUNT);
LivenessDetModel livenessDetModel = LivenessModelFactory.getInstance().getModel(config);
//获取人脸检测模型
FaceModelConfig faceDetectModelConfig = new FaceModelConfig();
faceDetectModelConfig.setModelEnum(FaceModelEnum.SEETA_FACE6_MODEL);
faceDetectModelConfig.setModelPath(modelPath);
FaceModel faceDetectModel = FaceModelFactory.getInstance().getModel(faceDetectModelConfig);
try {
FFmpegFrameGrabber grabber = new FFmpegFrameGrabber("src/main/resources/girl.mp4");
grabber.start();
// 获取视频总帧数
int totalFrames = grabber.getLengthInFrames();
log.info("视频总帧数:{},检测帧数:{}", totalFrames, config.getFrameCount());
//活体检测结果
LivenessStatus livenessStatus = LivenessStatus.UNKNOWN;
// 逐帧处理视频
for (int frameIndex = 0; frameIndex < totalFrames; frameIndex++) {
// 获取当前帧
Frame frame = grabber.grabImage();
if (frame != null) {
BufferedImage bufferedImage = Java2DFrameUtils.toBufferedImage(frame);
//检测视频帧人脸
DetectionResponse detectionResponse = faceDetectModel.detect(bufferedImage);
//检测到人脸
if(detectionResponse != null && detectionResponse.getDetectionInfoList() != null && detectionResponse.getDetectionInfoList().size() > 0){
DetectionRectangle detectionRectangle = detectionResponse.getDetectionInfoList().get(0).getDetectionRectangle();
FaceInfo faceInfo = detectionResponse.getDetectionInfoList().get(0).getFaceInfo();
//使用人脸检测结果 活体检测
LivenessStatus livenessStatusFrame = livenessDetModel.detectVideoByFrame(bufferedImage, detectionRectangle, faceInfo.getKeyPoints());
//满足检测帧数之后停止检测
if(livenessStatusFrame != LivenessStatus.DETECTING){
livenessStatus = livenessStatusFrame;
}
}else{
log.info("未检测到人脸");
}
}
}
log.info("视频活体检测结果:{}", JSONObject.toJSONString(livenessStatus));
grabber.stop();
} catch (FFmpegFrameGrabber.Exception e) {
throw new FaceException(e);
}
}
}

View File

@@ -0,0 +1,114 @@
package smartai.examples.objectdetection;
import ai.djl.Application;
import ai.djl.MalformedModelException;
import ai.djl.modality.cv.Image;
import ai.djl.modality.cv.ImageFactory;
import ai.djl.modality.cv.output.*;
import ai.djl.modality.cv.output.Rectangle;
import ai.djl.repository.zoo.Criteria;
import ai.djl.repository.zoo.ModelNotFoundException;
import ai.djl.repository.zoo.ModelZoo;
import ai.djl.repository.zoo.ZooModel;
import ai.djl.training.util.ProgressBar;
import cn.smartjavaai.common.entity.DetectionResponse;
import cn.smartjavaai.common.enums.DeviceEnum;
import cn.smartjavaai.objectdetection.DetectorModelConfig;
import cn.smartjavaai.objectdetection.DetectorModelEnum;
import cn.smartjavaai.objectdetection.exception.DetectionException;
import cn.smartjavaai.objectdetection.model.DetectorModel;
import cn.smartjavaai.objectdetection.model.ObjectDetectionModelFactory;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.junit.Assert;
import org.junit.Test;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
/**
* 目标检测模型demo
* 支持功能:目标检测
* @author dwj
* @date 2025/4/11
*/
@Slf4j
public class ObjectDetection {
/**
* 使用默认模型检测YOLO11N
*/
@Test
public void objectDetection(){
DetectorModel detectorModel = ObjectDetectionModelFactory.getInstance().getModel();
DetectionResponse detectionResponse = detectorModel.detect("src/main/resources/object_detection.jpg");
log.info("目标检测结果:{}", JSONObject.toJSONString(detectionResponse));
}
/**
* 指定模型检测(19种模型可选)
*/
@Test
public void objectDetection2(){
DetectorModelConfig config = new DetectorModelConfig();
config.setModelEnum(DetectorModelEnum.SSD_300_RESNET50);//检测模型目前支持19种模型
DetectorModel detectorModel = ObjectDetectionModelFactory.getInstance().getModel(config);
DetectionResponse detectionResponse = detectorModel.detect("src/main/resources/dog_bike_car.jpg");
log.info("目标检测结果:{}", JSONObject.toJSONString(detectionResponse));
}
/**
* 人脸检测并绘制检测结果
*/
@Test
public void objectDetectionAndDraw(){
DetectorModel detectorModel = ObjectDetectionModelFactory.getInstance().getModel();
detectorModel.detectAndDraw("src/main/resources/object_detection.jpg","output/object_detection_detected.png");
}
/**
* 人脸检测并绘制检测结果,返回BufferedImage
*/
@Test
public void objectDetectionAndDraw2(){
try {
DetectorModel detectorModel = ObjectDetectionModelFactory.getInstance().getModel();
BufferedImage image = null;
String imagePath = "src/main/resources/object_detection.jpg";
image = ImageIO.read(new File(Paths.get(imagePath).toAbsolutePath().toString()));
//可以根据后续业务场景使用detectedImage
BufferedImage detectedImage = detectorModel.detectAndDraw(image);
Assert.assertNotNull("detectedImage null", detectedImage);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
/**
* GPU 目标检测
*/
@Test
public void gpuObjectDetection(){
DetectorModelConfig config = new DetectorModelConfig();
config.setModelEnum(DetectorModelEnum.YOLO11N);//检测模型目前支持19种模型
config.setDevice(DeviceEnum.GPU);
DetectorModel detectorModel = ObjectDetectionModelFactory.getInstance().getModel(config);
DetectionResponse detectionResponse = detectorModel.detect("src/main/resources/dog_bike_car.jpg");
log.info("目标检测结果:{}", JSONObject.toJSONString(detectionResponse));
}
}

View File

@@ -0,0 +1,3 @@
Manifest-Version: 1.0
Main-Class: smartai.examples.face.SeetaFace6LinuxDemo

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 463 KiB

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- 步骤2: 配置文件 (src/main/resources/logback.xml) -->
<configuration scan="true" scanPeriod="30 seconds">
<!-- 控制台日志输出 -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %highlight(%-5level) %cyan(%logger{36}) - %msg%n</pattern>
</encoder>
</appender>
<root level="INFO">
<appender-ref ref="CONSOLE" />
</root>
</configuration>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB