1、集成车牌识别模型,支持车牌检测与识别

2、新增 Milvus 身份验证支持
3、目标检测功能升级:可指定类别及topk
4、支持自定义线程池线程数量
This commit is contained in:
dengwenjie
2025-07-28 12:04:02 +08:00
parent 1bd74d1bb8
commit 1d45bc597d
117 changed files with 3490 additions and 437 deletions

View File

@@ -12,7 +12,7 @@
<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.20</smartjavaai.version>
<smartjavaai.version>1.0.22</smartjavaai.version>
<!--如果打包运行需要替换成你的main-->
<exec.mainClass>smartai.examples.face.facedet.FaceDetDemo</exec.mainClass>
@@ -95,6 +95,13 @@
<dependency>
<groupId>cn.smartjavaai</groupId>
<artifactId>smartjavaai-face</artifactId>
<version>1.0.22</version>
</dependency>
<dependency>
<groupId>cn.smartjavaai</groupId>
<artifactId>smartjavaai-all</artifactId>
<version>1.0.22</version>
</dependency>

View File

@@ -0,0 +1,25 @@
package smartai.examples.face;
import cn.smartjavaai.common.utils.VideoUtils;
import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
/**
* 视频预处理
* @author dwj
* @date 2025/7/17
*/
public class VideoDemo {
public static void main(String[] args) {
try {
VideoUtils.rotateVideo("/Users/wenjie/Downloads/girl.mp4", "/Users/wenjie/Downloads/girl_rotate.mp4", 180,"mp4", avcodec.AV_CODEC_ID_H264);
} catch (FFmpegFrameRecorder.Exception e) {
throw new RuntimeException(e);
} catch (FFmpegFrameGrabber.Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -57,7 +57,8 @@ public class FaceAttributeDetDemo {
*/
@Test
public void testFaceAttributeDetect(){
try (FaceAttributeModel faceAttributeModel = getFaceAttributeModel()){
try {
FaceAttributeModel faceAttributeModel = getFaceAttributeModel();
DetectionResponse detectionResponse = faceAttributeModel.detect("src/main/resources/iu_1.jpg");
//绘制并导出人脸属性图片,小人脸仅有人脸框
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/iu_1.jpg").toAbsolutePath().toString()));
@@ -73,7 +74,8 @@ public class FaceAttributeDetDemo {
*/
@Test
public void testFaceAttributeDetect2(){
try (FaceAttributeModel faceAttributeModel = getFaceAttributeModel()){
try {
FaceAttributeModel faceAttributeModel = getFaceAttributeModel();
FaceAttribute faceAttribute = faceAttributeModel.detectTopFace("src/main/resources/iu_1.jpg");
log.info("人脸属性检测结果:{}", JSONObject.toJSONString(faceAttribute));
} catch (Exception e) {
@@ -86,7 +88,8 @@ public class FaceAttributeDetDemo {
*/
@Test
public void testFaceAttributeDetect3(){
try (FaceAttributeModel faceAttributeModel = getFaceAttributeModel()){
try {
FaceAttributeModel faceAttributeModel = getFaceAttributeModel();
FaceAttribute faceAttribute = faceAttributeModel.detectTopFace("src/main/resources/iu_1.jpg");
log.info("人脸属性检测结果:{}", JSONObject.toJSONString(faceAttribute));
} catch (Exception e) {
@@ -103,8 +106,9 @@ public class FaceAttributeDetDemo {
*/
@Test
public void testFaceAttributeDetect4(){
try (FaceDetModel faceDetModel = getFaceDetModel();
FaceAttributeModel faceAttributeModel = getFaceAttributeModel()){
try {
FaceDetModel faceDetModel = getFaceDetModel();
FaceAttributeModel faceAttributeModel = getFaceAttributeModel();
//人脸检测
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/iu_1.jpg").toAbsolutePath().toString()));
R<DetectionResponse> detectionResponse = faceDetModel.detect(image);

View File

@@ -88,7 +88,8 @@ public class ExpressionRecDemo {
*/
@Test
public void testExpressionDetect() {
try (ExpressionModel model = getExpressionModel()){
try {
ExpressionModel model = getExpressionModel();
R<ExpressionResult> result = model.detectTopFace("src/main/resources/emotion/happy.png");
if(result.isSuccess()){
log.info("识别结果:{}", JSONObject.toJSONString(result.getData().getExpression().getDescription()));
@@ -106,7 +107,8 @@ public class ExpressionRecDemo {
*/
@Test
public void testExpressionDetect2() {
try (ExpressionModel model = getExpressionModel()){
try {
ExpressionModel model = getExpressionModel();
R<DetectionResponse> result = model.detect("src/main/resources/emotion/happy.png");
if(result.isSuccess()){
//log.info("识别结果:{}", JSONObject.toJSONString(result.getData()));
@@ -128,8 +130,9 @@ public class ExpressionRecDemo {
*/
@Test
public void testExpressionDetect3() {
try (FaceDetModel faceDetModel = getFaceDetModel();
ExpressionModel model = getExpressionModel()){
try {
FaceDetModel faceDetModel = getFaceDetModel();
ExpressionModel model = getExpressionModel();
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/emotion/happy.png").toAbsolutePath().toString()));
R<DetectionResponse> detResult = faceDetModel.detect(image);
if(detResult.isSuccess()){
@@ -156,8 +159,9 @@ public class ExpressionRecDemo {
*/
@Test
public void testExpressionDetect4() {
try (FaceDetModel faceDetModel = getFaceDetModel();
ExpressionModel model = getExpressionModel()){
try {
FaceDetModel faceDetModel = getFaceDetModel();
ExpressionModel model = getExpressionModel();
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/emotion/happy.png").toAbsolutePath().toString()));
R<DetectionResponse> detResult = faceDetModel.detect(image);
if(detResult.isSuccess()){
@@ -182,7 +186,8 @@ public class ExpressionRecDemo {
*/
@Test
public void testExpressionDetectAndDraw(){
try (ExpressionModel model = getExpressionModel()){
try {
ExpressionModel model = getExpressionModel();
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/emotion/surprise.png").toAbsolutePath().toString()));
R<DetectionResponse> result = model.detect(image);
if(result.isSuccess()){
@@ -206,7 +211,8 @@ public class ExpressionRecDemo {
*/
@Test
public void testExpressionDetectCamera(){
try (ExpressionModel expressionModel = getExpressionModel()){
try {
ExpressionModel expressionModel = getExpressionModel();
OpenCV.loadShared();
VideoCapture capture = new VideoCapture(0);
if (!capture.isOpened()) {

View File

@@ -82,7 +82,8 @@ public class FaceDetDemo {
*/
@Test
public void testFaceDetect(){
try (FaceDetModel faceModel = FaceDetModelFactory.getInstance().getModel()) {
try {
FaceDetModel faceModel = FaceDetModelFactory.getInstance().getModel();
R<DetectionResponse> detectedResult = faceModel.detect(imgPath);
if(detectedResult.isSuccess()){
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectedResult.getData()));
@@ -100,7 +101,8 @@ public class FaceDetDemo {
*/
@Test
public void testFaceDetectCustomConfig(){
try (FaceDetModel faceModel = getFaceDetModel()){
try {
FaceDetModel faceModel = getFaceDetModel();
R<DetectionResponse> detectedResult = faceModel.detect(imgPath);
if(detectedResult.isSuccess()){
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectedResult.getData()));
@@ -118,7 +120,8 @@ public class FaceDetDemo {
*/
@Test
public void testFaceDetectAndDraw(){
try (FaceDetModel faceModel = getFaceDetModel()){
try {
FaceDetModel faceModel = getFaceDetModel();
faceModel.detectAndDraw("src/main/resources/largest_selfie.jpg","output/largest_selfie_detected.png");
} catch (Exception e) {
throw new RuntimeException(e);
@@ -131,7 +134,8 @@ public class FaceDetDemo {
*/
@Test
public void testFaceDetectAndDraw2(){
try (FaceDetModel faceModel = getFaceDetModel()){
try {
FaceDetModel faceModel = getFaceDetModel();
BufferedImage image = null;
String imagePath = "src/main/resources/largest_selfie.jpg";
image = ImageIO.read(new File(Paths.get(imagePath).toAbsolutePath().toString()));
@@ -154,11 +158,12 @@ public class FaceDetDemo {
*/
@Test
public void testDetectFaceOffine(){
FaceDetConfig config = new FaceDetConfig();
config.setModelEnum(FaceDetModelEnum.RETINA_FACE);//人脸模型
//模型路径,不同模型下载路径请参看文档
config.setModelPath("/Users/xxx/Documents/develop/face_model/retinaface.pt");
try (FaceDetModel faceModel = FaceDetModelFactory.getInstance().getModel(config)) {
try {
FaceDetConfig config = new FaceDetConfig();
config.setModelEnum(FaceDetModelEnum.RETINA_FACE);//人脸模型
//模型路径,不同模型下载路径请参看文档
config.setModelPath("/Users/xxx/Documents/develop/face_model/retinaface.pt");
FaceDetModel faceModel = FaceDetModelFactory.getInstance().getModel(config);
R<DetectionResponse> detectedResult = faceModel.detect(imgPath);
if(detectedResult.isSuccess()){
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectedResult.getData()));
@@ -175,10 +180,11 @@ public class FaceDetDemo {
*/
@Test
public void testDetectFaceGPU(){
FaceDetConfig config = new FaceDetConfig();
config.setModelEnum(FaceDetModelEnum.RETINA_FACE);//人脸模型
config.setDevice(DeviceEnum.GPU);
try (FaceDetModel faceModel = FaceDetModelFactory.getInstance().getModel(config)) {
try {
FaceDetConfig config = new FaceDetConfig();
config.setModelEnum(FaceDetModelEnum.RETINA_FACE);//人脸模型
config.setDevice(DeviceEnum.GPU);
FaceDetModel faceModel = FaceDetModelFactory.getInstance().getModel(config);
R<DetectionResponse> detectedResult = faceModel.detect(imgPath);
if(detectedResult.isSuccess()){
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectedResult.getData()));
@@ -196,7 +202,8 @@ public class FaceDetDemo {
*/
@Test
public void testFaceDetectSeetaface6(){
try (FaceDetModel faceModel = getSeetaface6DetModel()){
try {
FaceDetModel faceModel = getSeetaface6DetModel();
R<DetectionResponse> detectedResult = faceModel.detect(imgPath);
if(detectedResult.isSuccess()){
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectedResult.getData()));
@@ -215,7 +222,8 @@ public class FaceDetDemo {
*/
@Test
public void testDetectCamera(){
try (FaceDetModel faceModel = getFaceDetModel()){
try {
FaceDetModel faceModel = getFaceDetModel();
OpenCV.loadShared();
VideoCapture capture = new VideoCapture(0);
if (!capture.isOpened()) {

View File

@@ -95,6 +95,8 @@ public class FaceRecDemo {
MilvusConfig vectorDBConfig = new MilvusConfig();
vectorDBConfig.setHost("127.0.0.1");
vectorDBConfig.setPort(19530);
//vectorDBConfig.setUsername("root");
//vectorDBConfig.setPassword("Milvus");
//vectorDBConfig.setCollectionName("face5");
//ID策略自动生成
vectorDBConfig.setIdStrategy(IdStrategy.AUTO);
@@ -135,7 +137,8 @@ public class FaceRecDemo {
*/
@Test
public void testExtractFeatures(){
try (FaceRecModel faceRecModel = getFaceRecModel()){
try {
FaceRecModel faceRecModel = getFaceRecModel();
//提取图片中所有人脸特征
R<DetectionResponse> faceResult = faceRecModel.extractFeatures("src/main/resources/iu_1.jpg");
if(faceResult.isSuccess()){
@@ -158,7 +161,8 @@ public class FaceRecDemo {
*/
@Test
public void featureComparison(){
try (FaceRecModel faceRecModel = getFaceRecModel()){
try {
FaceRecModel faceRecModel = getFaceRecModel();
//基于图像直接比对人脸特征
R<Float> similarResult = faceRecModel.featureComparison("src/main/resources/iu_1.jpg","src/main/resources/iu_2.jpg");
if(similarResult.isSuccess()){
@@ -183,7 +187,8 @@ public class FaceRecDemo {
*/
@Test
public void featureComparison2(){
try (FaceRecModel faceRecModel = getFaceRecModel()){
try {
FaceRecModel faceRecModel = getFaceRecModel();
//特征提取(提取分数最高人脸特征),适用于单人脸场景
R<float[]> featureResult1 = faceRecModel.extractTopFaceFeature("src/main/resources/iu_1.jpg");
if(featureResult1.isSuccess()){
@@ -220,7 +225,8 @@ public class FaceRecDemo {
*/
@Test
public void searchFace(){
try (FaceRecModel faceRecModel = getFaceRecModelWithDbConfig()){
try {
FaceRecModel faceRecModel = getFaceRecModelWithDbConfig();
//等待加载人脸库结束
while (!faceRecModel.isLoadFaceCompleted()){
Thread.sleep(100);
@@ -296,7 +302,8 @@ public class FaceRecDemo {
*/
@Test
public void searchFace2(){
try (FaceRecModel faceRecModel = getFaceRecModelWithSQLiteConfig()){
try {
FaceRecModel faceRecModel = getFaceRecModelWithSQLiteConfig();
//等待加载人脸库结束
while (!faceRecModel.isLoadFaceCompleted()){
Thread.sleep(100);
@@ -367,7 +374,8 @@ public class FaceRecDemo {
@Test
public void getFaceInfo(){
//使用ID获取人脸信息
try (FaceRecModel faceRecModel = getFaceRecModelWithSQLiteConfig()){
try {
FaceRecModel faceRecModel = getFaceRecModelWithSQLiteConfig();
//等待加载人脸库结束
while (!faceRecModel.isLoadFaceCompleted()){
Thread.sleep(100);
@@ -390,7 +398,8 @@ public class FaceRecDemo {
@Test
public void listFaces(){
//使用ID获取人脸信息
try (FaceRecModel faceRecModel = getFaceRecModelWithDbConfig()){
try {
FaceRecModel faceRecModel = getFaceRecModelWithDbConfig();
//等待加载人脸库结束
while (!faceRecModel.isLoadFaceCompleted()){
Thread.sleep(100);

View File

@@ -133,7 +133,8 @@ public class LivenessDetDemo {
*/
@Test
public void testLivenessDetect(){
try (LivenessDetModel livenessDetModel = getLivenessDetModel()){
try {
LivenessDetModel livenessDetModel = getLivenessDetModel();
R<DetectionResponse> response = livenessDetModel.detect("src/main/resources/liveness/1.jpg");
if(response.isSuccess()){
for (DetectionInfo detectionInfo : response.getData().getDetectionInfoList()){
@@ -152,7 +153,8 @@ public class LivenessDetDemo {
*/
@Test
public void testLivenessDetectAndDraw(){
try (LivenessDetModel livenessDetModel = getLivenessDetModel()){
try {
LivenessDetModel livenessDetModel = getLivenessDetModel();
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/liveness/1.jpg").toAbsolutePath().toString()));
R<DetectionResponse> response = livenessDetModel.detect(image);
if(response.isSuccess()){
@@ -175,7 +177,8 @@ public class LivenessDetDemo {
*/
@Test
public void testLivenessDetect2(){
try (LivenessDetModel livenessDetModel = getLivenessDetModel()){
try {
LivenessDetModel livenessDetModel = getLivenessDetModel();
//指定文件夹路径
File dir = new File("face-example/src/main/resources/liveness");
File[] files = dir.listFiles();
@@ -198,8 +201,9 @@ public class LivenessDetDemo {
*/
@Test
public void testLivenessDetect3(){
try (FaceDetModel faceDetectModel = getFaceDetModel();
LivenessDetModel livenessDetModel = getLivenessDetModel()){
try {
FaceDetModel faceDetectModel = getFaceDetModel();
LivenessDetModel livenessDetModel = getLivenessDetModel();
// 将图片路径转换为 BufferedImage
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/liveness/1.jpg").toAbsolutePath().toString()));
//人脸检测
@@ -230,8 +234,9 @@ public class LivenessDetDemo {
*/
@Test
public void testLivenessDetect4(){
try (FaceDetModel faceDetModel = getFaceDetModel();
LivenessDetModel livenessDetModel = getMiniVisionLivenessDetModel()){
try {
FaceDetModel faceDetModel = getFaceDetModel();
LivenessDetModel livenessDetModel = getMiniVisionLivenessDetModel();
// 将图片路径转换为 BufferedImage
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/liveness/1.jpg").toAbsolutePath().toString()));
R<DetectionResponse> detResult = faceDetModel.detect(image);
@@ -259,7 +264,8 @@ public class LivenessDetDemo {
*/
@Test
public void testLivenessDetectVideo(){
try (LivenessDetModel livenessDetModel = getLivenessDetModel()){
try {
LivenessDetModel livenessDetModel = getLivenessDetModel();
//视频路径
R<LivenessResult> livenessStatus = livenessDetModel.detectVideo("video.mp4");
if (livenessStatus.isSuccess()){
@@ -278,7 +284,8 @@ public class LivenessDetDemo {
*/
@Test
public void testLivenessDetectCamera(){
try (LivenessDetModel livenessDetModel = getLivenessDetModel()){
try {
LivenessDetModel livenessDetModel = getLivenessDetModel();
OpenCV.loadShared();
VideoCapture capture = new VideoCapture(0);
if (!capture.isOpened()) {

View File

@@ -78,8 +78,9 @@ public class FaceQualityDetDemo {
*/
@Test
public void evaluateBrightness(){
try (FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel()){
try {
FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel();
//人脸检测
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/iu_1.jpg").toAbsolutePath().toString()));
R<DetectionResponse> detectionResponse = faceDetModel.detect(image);
@@ -110,8 +111,9 @@ public class FaceQualityDetDemo {
*/
@Test
public void evaluateCompleteness(){
try (FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel()){
try {
FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel();
//人脸检测
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/iu_1.jpg").toAbsolutePath().toString()));
R<DetectionResponse> detectionResponse = faceDetModel.detect(image);
@@ -142,8 +144,9 @@ public class FaceQualityDetDemo {
*/
@Test
public void evaluateClarity(){
try (FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel()){
try {
FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel();
//人脸检测
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/iu_1.jpg").toAbsolutePath().toString()));
R<DetectionResponse> detectionResponse = faceDetModel.detect(image);
@@ -174,8 +177,9 @@ public class FaceQualityDetDemo {
*/
@Test
public void evaluatePose(){
try (FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel()){
try {
FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel();
//人脸检测
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/iu_1.jpg").toAbsolutePath().toString()));
R<DetectionResponse> detectionResponse = faceDetModel.detect(image);
@@ -207,8 +211,9 @@ public class FaceQualityDetDemo {
*/
@Test
public void evaluateResolution(){
try (FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel()){
try {
FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel();
//人脸检测
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/iu_1.jpg").toAbsolutePath().toString()));
R<DetectionResponse> detectionResponse = faceDetModel.detect(image);
@@ -240,8 +245,9 @@ public class FaceQualityDetDemo {
*/
@Test
public void evaluateAll(){
try (FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel()){
try {
FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel();
//人脸检测
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/iu_1.jpg").toAbsolutePath().toString()));
R<DetectionResponse> detectionResponse = faceDetModel.detect(image);