diff --git a/README.md b/README.md
index 6ffa60d..7ec3480 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@
-
+
@@ -230,7 +230,7 @@ SmartJavaAI是专为JAVA 开发者打造的一个功能丰富、开箱即用的
### 1、环境要求
-- Java 版本:**JDK 11或更高版本**
+- Java 版本:**JDK 8或更高版本**
- 操作系统:不同模型支持的系统不一样,具体请查看文档
### 2、Maven
@@ -240,7 +240,7 @@ SmartJavaAI是专为JAVA 开发者打造的一个功能丰富、开箱即用的
cn.smartjavaai
smartjavaai-all
- 1.0.12
+ 1.0.13
```
### 3、完整示例代码
@@ -273,7 +273,15 @@ SmartJavaAI是专为JAVA 开发者打造的一个功能丰富、开箱即用的
🚀 **如果这个项目对你有帮助,别忘了点个 Star ⭐!你的支持是我持续优化升级的动力!** ❤️
-## 更新日志
+## 近期更新日志
+
+## [v1.0.13] - 2025-05-17
+- 支持 JDK8 环境运行
+- 引入离线依赖,支持完全离线使用
+- 优化 FaceNet 人脸比对性能,提升比对速度
+- 支持带 Alpha 通道的 4 通道图片检测
+- 目标检测:新增 YOLOv12 官方模型支持
+- 目标检测:支持加载自训练模型进行推理
## [v1.0.12] - 2025-05-09
- 新增图片与视频活体检测
@@ -297,9 +305,6 @@ SmartJavaAI是专为JAVA 开发者打造的一个功能丰富、开箱即用的
- 修复若干已知问题
- 支持自定义选择使用 GPU 或 CPU 运算
- 人脸识别模块新增多种接口,功能更加完善
-## [v1.0.6] - 2025-04-01
-- 修复人脸识别算法facenet-pytorch实现方式
-- 优化Seetaface6算法,兼容jdk高版本
diff --git a/examples/pom.xml b/examples/pom.xml
index e4926d2..f9c4ab6 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -12,7 +12,7 @@
11
11
UTF-8
- 1.0.12
+ 1.0.13
smartai.examples.face.facerec.RetinaFaceDemo
@@ -104,6 +104,14 @@
+
+ ai.djl.pytorch
+ pytorch-jni
+ 2.5.1-0.32.0
+ runtime
+
+
+
org.bytedeco
@@ -132,6 +140,15 @@
${javacv.platform.windows-x86_64}
+
+ ai.djl.pytorch
+ pytorch-native-cpu
+ ${djl.platform.windows-x86_64}
+ 2.5.1
+ runtime
+
+
+
@@ -161,6 +178,14 @@
${javacv.platform.linux-x86_64}
+
+ ai.djl.pytorch
+ pytorch-native-cpu
+ ${djl.platform.linux-x86_64}
+ 2.5.1
+ runtime
+
+
@@ -190,6 +215,14 @@
${javacv.platform.macosx-arm64}
+
+ ai.djl.pytorch
+ pytorch-native-cpu
+ ${djl.platform.osx-aarch64}
+ 2.5.1
+ runtime
+
+
@@ -220,8 +253,13 @@
${javacv.platform.linux-arm64}
-
-
+
+ ai.djl.pytorch
+ pytorch-native-cpu-precxx11
+ ${djl.platform.linux-aarch64}
+ 2.5.1
+ runtime
+
diff --git a/examples/src/main/java/smartai/examples/face/facerec/FaceNetDemo.java b/examples/src/main/java/smartai/examples/face/facerec/FaceNetDemo.java
index a1dcd7c..67bf62a 100644
--- a/examples/src/main/java/smartai/examples/face/facerec/FaceNetDemo.java
+++ b/examples/src/main/java/smartai/examples/face/facerec/FaceNetDemo.java
@@ -54,14 +54,17 @@ public class FaceNetDemo {
@Test
public void testExtractFeaturesWithCustomConfig(){
try {
- //人脸特征提取模型
- FaceModel faceModel = FaceModelFactory.getInstance().getModel(
- new FaceModelConfig(FaceModelEnum.FACENET_FEATURE_EXTRACTION));
+ //人脸模型参数
+ FaceModelConfig config = new FaceModelConfig();
+ config.setModelEnum(FaceModelEnum.FACENET_FEATURE_EXTRACTION);
//人脸特征提取参数
FaceExtractConfig extractConfig = new FaceExtractConfig();
//人脸检测模型配置
- extractConfig.setDetectModelConfig(new FaceModelConfig(FaceModelEnum.ULTRA_LIGHT_FAST_GENERIC_FACE));
- List faceResult = faceModel.extractFeatures("src/main/resources/kana1.jpg",extractConfig);
+ extractConfig.setDetectModel(FaceModelFactory.getInstance().getModel(new FaceModelConfig(FaceModelEnum.ULTRA_LIGHT_FAST_GENERIC_FACE)));
+ config.setExtractConfig(extractConfig);
+ //人脸特征提取模型
+ FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
+ List faceResult = faceModel.extractFeatures("src/main/resources/kana1.jpg");
log.info("人脸特征提取结果:{}", JSONObject.toJSONString(faceResult));
}catch (Exception e){
e.printStackTrace();
@@ -94,13 +97,16 @@ public class FaceNetDemo {
@Test
public void testExtractTopFaceFeatureWithCustomConfig(){
try {
- //人脸特征提取模型
- FaceModel faceModel = FaceModelFactory.getInstance().getModel(
- new FaceModelConfig(FaceModelEnum.FACENET_FEATURE_EXTRACTION));
+ //人脸模型参数
+ FaceModelConfig config = new FaceModelConfig();
+ config.setModelEnum(FaceModelEnum.FACENET_FEATURE_EXTRACTION);
//人脸特征提取参数
FaceExtractConfig extractConfig = new FaceExtractConfig();
//人脸检测模型配置
- extractConfig.setDetectModelConfig(new FaceModelConfig(FaceModelEnum.ULTRA_LIGHT_FAST_GENERIC_FACE));
+ extractConfig.setDetectModel(FaceModelFactory.getInstance().getModel(new FaceModelConfig(FaceModelEnum.ULTRA_LIGHT_FAST_GENERIC_FACE)));
+ config.setExtractConfig(extractConfig);
+ //人脸特征提取模型
+ FaceModel faceModel = FaceModelFactory.getInstance().getModel(config);
float[] faceResult = faceModel.extractTopFaceFeature("src/main/resources/kana1.jpg");
log.info("人脸特征提取结果:{}", JSONObject.toJSONString(faceResult));
}catch (Exception e){
diff --git a/examples/src/main/java/smartai/examples/objectdetection/ObjectDetection.java b/examples/src/main/java/smartai/examples/objectdetection/ObjectDetection.java
index f8cd784..4fc321a 100644
--- a/examples/src/main/java/smartai/examples/objectdetection/ObjectDetection.java
+++ b/examples/src/main/java/smartai/examples/objectdetection/ObjectDetection.java
@@ -13,8 +13,8 @@ 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.config.DetectorModelConfig;
+import cn.smartjavaai.objectdetection.enums.DetectorModelEnum;
import cn.smartjavaai.objectdetection.exception.DetectionException;
import cn.smartjavaai.objectdetection.model.DetectorModel;
import cn.smartjavaai.objectdetection.model.ObjectDetectionModelFactory;
@@ -62,7 +62,7 @@ public class ObjectDetection {
@Test
public void objectDetection2(){
DetectorModelConfig config = new DetectorModelConfig();
- config.setModelEnum(DetectorModelEnum.SSD_300_RESNET50);//检测模型,目前支持19种模型
+ 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));
@@ -110,5 +110,35 @@ public class ObjectDetection {
}
+ /**
+ * 使用yolo官方模型检测
+ */
+ @Test
+ public void objectDetectionWithOfficialModel(){
+ DetectorModelConfig config = new DetectorModelConfig();
+ //也支持YoloV8:YOLOV8_OFFICIAL 模型可以从文档中提供的地址下载
+ config.setModelEnum(DetectorModelEnum.YOLOV12_OFFICIAL);//检测模型,目前支持19种模型
+ // 指定模型路径,需要更改为自己的模型路径
+ config.setModelPath("/Users/xxx/Documents/develop/face_model/yolov12n.onnx");
+ DetectorModel detectorModel = ObjectDetectionModelFactory.getInstance().getModel(config);
+ //一定要将yolo官方的类别文件:synset.txt(文档中下载)放在模型同目录下,否则报错
+ detectorModel.detectAndDraw("src/main/resources/object_detection.jpg","output/object_detection_detected.png");
+ }
+
+ /**
+ * 使用自己训练的模型检测
+ */
+ @Test
+ public void objectDetectionWithCustomModel(){
+ DetectorModelConfig config = new DetectorModelConfig();
+ //也支持YoloV8:YOLOV8_CUSTOM 模型需要自己训练,训练教程可以查看文档
+ config.setModelEnum(DetectorModelEnum.YOLOV12_CUSTOM);//自定义YOLOV12模型
+ // 指定模型路径,需要更改为自己的模型路径
+ config.setModelPath("/Users/xxx/Documents/develop/fire_model/best.onnx");
+ DetectorModel detectorModel = ObjectDetectionModelFactory.getInstance().getModel(config);
+ //一定要将类别文件:synset.txt 放在模型同目录下,否则报错(具体请参看文档)
+ detectorModel.detectAndDraw("/Users/xxx/Downloads/test.jpg","output/test_detected.jpg");
+ }
+
}
diff --git a/pom.xml b/pom.xml
index 88955f5..16d9dd9 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
cn.smartjavaai
smartjavaai-parent
- 1.0.12
+ 1.0.13
pom
SmartJavaAI
@@ -19,8 +19,8 @@
- 11
- 11
+ 8
+ 8
UTF-8
0.32.0
@@ -39,13 +39,13 @@
cn.smartjavaai
smartjavaai-common
- 1.0.12
+ 1.0.13
cn.smartjavaai
smartjavaai-face
- 1.0.12
+ 1.0.13
@@ -95,7 +95,7 @@
org.testng
testng
- 7.10.2
+ 7.4.0
test
@@ -260,7 +260,7 @@
maven-javadoc-plugin
3.1.0
- ${java.home}/bin/javadoc
+
none
-Xdoclint:none
diff --git a/smartjavaai-all/pom.xml b/smartjavaai-all/pom.xml
index 53e144a..4f53fb8 100644
--- a/smartjavaai-all/pom.xml
+++ b/smartjavaai-all/pom.xml
@@ -6,11 +6,11 @@
cn.smartjavaai
smartjavaai-parent
- 1.0.12
+ 1.0.13
smartjavaai-all
- 1.0.12
+ 1.0.13
${project.artifactId}
SmartJavaAI
https://github.com/geekwenjie/SmartJavaAI
@@ -23,8 +23,8 @@
- 11
- 11
+
+
UTF-8
true
@@ -111,7 +111,7 @@
maven-javadoc-plugin
3.1.0
- ${java.home}/bin/javadoc
+
none
-Xdoclint:none
diff --git a/smartjavaai-bom/pom.xml b/smartjavaai-bom/pom.xml
index ad810da..d83389d 100644
--- a/smartjavaai-bom/pom.xml
+++ b/smartjavaai-bom/pom.xml
@@ -6,17 +6,17 @@
cn.smartjavaai
smartjavaai-parent
- 1.0.12
+ 1.0.13
- 1.0.12
+ 1.0.13
smartjavaai-bom
smartjavaai-bom
统一版本管理的 BOM 包,同时支持 import 和全量依赖
- 11
- 11
+
+
UTF-8
@@ -77,7 +77,7 @@
maven-javadoc-plugin
3.1.0
- ${java.home}/bin/javadoc
+
none
-Xdoclint:none
diff --git a/smartjavaai-common/pom.xml b/smartjavaai-common/pom.xml
index 572d218..89f8293 100644
--- a/smartjavaai-common/pom.xml
+++ b/smartjavaai-common/pom.xml
@@ -6,7 +6,7 @@
cn.smartjavaai
smartjavaai-parent
- 1.0.12
+ 1.0.13
smartjavaai-common
@@ -58,7 +58,7 @@
maven-javadoc-plugin
3.1.0
- ${java.home}/bin/javadoc
+
none
-Xdoclint:none
diff --git a/smartjavaai-face/pom.xml b/smartjavaai-face/pom.xml
index f3f3008..31189d9 100644
--- a/smartjavaai-face/pom.xml
+++ b/smartjavaai-face/pom.xml
@@ -6,11 +6,11 @@
cn.smartjavaai
smartjavaai-parent
- 1.0.12
+ 1.0.13
smartjavaai-face
- 1.0.12
+ 1.0.13
smartjavaai-face
SmartJavaAI
https://github.com/geekwenjie/SmartJavaAI
@@ -22,8 +22,8 @@
- 11
- 11
+
+
UTF-8
true
1.5.8
@@ -87,7 +87,7 @@
maven-javadoc-plugin
3.1.0
- ${java.home}/bin/javadoc
+
none
-Xdoclint:none
diff --git a/smartjavaai-face/src/main/java/cn/smartjavaai/face/config/FaceExtractConfig.java b/smartjavaai-face/src/main/java/cn/smartjavaai/face/config/FaceExtractConfig.java
index 150a99a..53aa3a4 100644
--- a/smartjavaai-face/src/main/java/cn/smartjavaai/face/config/FaceExtractConfig.java
+++ b/smartjavaai-face/src/main/java/cn/smartjavaai/face/config/FaceExtractConfig.java
@@ -1,5 +1,6 @@
package cn.smartjavaai.face.config;
+import cn.smartjavaai.face.model.facerec.FaceModel;
import lombok.Data;
/**
@@ -21,17 +22,17 @@ public class FaceExtractConfig {
private boolean align = true;
/**
- * 人脸检测模型配置
+ * 人脸检测模型
*/
- private FaceModelConfig detectModelConfig;
+ private FaceModel detectModel;
public FaceExtractConfig() {
}
- public FaceExtractConfig(boolean cropFace, boolean align, FaceModelConfig detectModelConfig) {
+ public FaceExtractConfig(boolean cropFace, boolean align, FaceModel detectModel) {
this.cropFace = cropFace;
this.align = align;
- this.detectModelConfig = detectModelConfig;
+ this.detectModel = detectModel;
}
diff --git a/smartjavaai-face/src/main/java/cn/smartjavaai/face/config/FaceModelConfig.java b/smartjavaai-face/src/main/java/cn/smartjavaai/face/config/FaceModelConfig.java
index 9e16364..74fd113 100644
--- a/smartjavaai-face/src/main/java/cn/smartjavaai/face/config/FaceModelConfig.java
+++ b/smartjavaai-face/src/main/java/cn/smartjavaai/face/config/FaceModelConfig.java
@@ -52,6 +52,11 @@ public class FaceModelConfig {
*/
private int gpuId = 0;
+ /**
+ * 人脸特征提取配置
+ */
+ private FaceExtractConfig extractConfig;
+
public FaceModelConfig() {
}
diff --git a/smartjavaai-face/src/main/java/cn/smartjavaai/face/model/facerec/AbstractFaceModel.java b/smartjavaai-face/src/main/java/cn/smartjavaai/face/model/facerec/AbstractFaceModel.java
index 36f87bc..07ea934 100644
--- a/smartjavaai-face/src/main/java/cn/smartjavaai/face/model/facerec/AbstractFaceModel.java
+++ b/smartjavaai-face/src/main/java/cn/smartjavaai/face/model/facerec/AbstractFaceModel.java
@@ -140,21 +140,6 @@ public abstract class AbstractFaceModel implements FaceModel {
throw new UnsupportedOperationException("默认不支持该功能");
}
- @Override
- public List extractFeatures(BufferedImage image, FaceExtractConfig config) {
- throw new UnsupportedOperationException("默认不支持该功能");
- }
-
- @Override
- public List extractFeatures(String imagePath, FaceExtractConfig config) {
- throw new UnsupportedOperationException("默认不支持该功能");
- }
-
- @Override
- public List extractFeatures(byte[] imageData, FaceExtractConfig config) {
- throw new UnsupportedOperationException("默认不支持该功能");
- }
-
@Override
public float[] extractTopFaceFeature(BufferedImage image) {
throw new UnsupportedOperationException("默认不支持该功能");
@@ -170,18 +155,5 @@ public abstract class AbstractFaceModel implements FaceModel {
throw new UnsupportedOperationException("默认不支持该功能");
}
- @Override
- public float[] extractTopFaceFeature(BufferedImage image, FaceExtractConfig config) {
- throw new UnsupportedOperationException("默认不支持该功能");
- }
- @Override
- public float[] extractTopFaceFeature(String imagePath, FaceExtractConfig config) {
- throw new UnsupportedOperationException("默认不支持该功能");
- }
-
- @Override
- public float[] extractTopFaceFeature(byte[] imageData, FaceExtractConfig config) {
- throw new UnsupportedOperationException("默认不支持该功能");
- }
}
diff --git a/smartjavaai-face/src/main/java/cn/smartjavaai/face/model/facerec/FaceModel.java b/smartjavaai-face/src/main/java/cn/smartjavaai/face/model/facerec/FaceModel.java
index 92e56f0..bf07399 100644
--- a/smartjavaai-face/src/main/java/cn/smartjavaai/face/model/facerec/FaceModel.java
+++ b/smartjavaai-face/src/main/java/cn/smartjavaai/face/model/facerec/FaceModel.java
@@ -199,30 +199,6 @@ public interface FaceModel {
*/
List extractFeatures(BufferedImage image);
- /**
- * 特征提取(使用自定义配置)
- * 强制裁剪操作
- * @param image BufferedImage
- * @param config
- * @return
- */
- List extractFeatures(BufferedImage image, FaceExtractConfig config);
-
- /**
- * 特征提取(使用自定义配置)
- * @param imagePath 图片路径
- * @param config
- * @return
- */
- List extractFeatures(String imagePath, FaceExtractConfig config);
-
- /**
- * 特征提取(使用自定义配置)
- * @param imageData 图片字节流
- * @param config
- * @return
- */
- List extractFeatures(byte[] imageData, FaceExtractConfig config);
/**
* 提取分数最高人脸特征(使用默认配置)
@@ -245,27 +221,6 @@ public interface FaceModel {
*/
float[] extractTopFaceFeature(byte[] imageData);
- /**
- * 提取分数最高人脸特征(使用自定义配置)
- * @param image BufferedImage
- * @return
- */
- float[] extractTopFaceFeature(BufferedImage image, FaceExtractConfig config);
- /**
- * 提取分数最高人脸特征(使用自定义配置)
- * @param imagePath 图片路径
- * @param config
- * @return
- */
- float[] extractTopFaceFeature(String imagePath, FaceExtractConfig config);
-
- /**
- * 提取分数最高人脸特征(使用自定义配置)
- * @param imageData 图片字节流
- * @param config
- * @return
- */
- float[] extractTopFaceFeature(byte[] imageData, FaceExtractConfig config);
}
diff --git a/smartjavaai-face/src/main/java/cn/smartjavaai/face/model/facerec/FeatureExtractionModel.java b/smartjavaai-face/src/main/java/cn/smartjavaai/face/model/facerec/FeatureExtractionModel.java
index c90dc72..9081b18 100644
--- a/smartjavaai-face/src/main/java/cn/smartjavaai/face/model/facerec/FeatureExtractionModel.java
+++ b/smartjavaai-face/src/main/java/cn/smartjavaai/face/model/facerec/FeatureExtractionModel.java
@@ -59,6 +59,8 @@ public class FeatureExtractionModel extends AbstractFaceModel implements AutoClo
private ZooModel model;
+ private FaceModelConfig config;
+
public static final List mean =
Arrays.asList(
127.5f / 255.0f,
@@ -75,10 +77,21 @@ public class FeatureExtractionModel extends AbstractFaceModel implements AutoClo
*/
@Override
public void loadModel(FaceModelConfig config) {
+ if(Objects.isNull(config)){
+ throw new FaceException("config为null");
+ }
+ if(Objects.isNull(config.getExtractConfig())){
+ config.setExtractConfig(getDefaultConfig());
+ }else{
+ if(Objects.isNull(config.getExtractConfig().getDetectModel())){
+ throw new FaceException("请设置人脸检测模型");
+ }
+ }
Device device = null;
if(!Objects.isNull(config.getDevice())){
device = config.getDevice() == DeviceEnum.CPU ? Device.cpu() : Device.gpu();
}
+ this.config = config;
String normalize = mean.stream().map(Object::toString).collect(Collectors.joining(","));
Criteria faceFeatureCriteria =
Criteria.builder()
@@ -162,7 +175,8 @@ public class FeatureExtractionModel extends AbstractFaceModel implements AutoClo
}
float[] feature1 = extractTopFaceFeature(imagePath1);
float[] feature2 = extractTopFaceFeature(imagePath2);
- return calculSimilar(feature1, feature2);
+ float ret = calculSimilar(feature1, feature2);
+ return ret;
}
@@ -194,37 +208,18 @@ public class FeatureExtractionModel extends AbstractFaceModel implements AutoClo
FaceExtractConfig config = new FaceExtractConfig();
FaceModelConfig detectModelConfig = new FaceModelConfig();
detectModelConfig.setModelEnum(FaceModelEnum.ULTRA_LIGHT_FAST_GENERIC_FACE);
- config.setDetectModelConfig(detectModelConfig);
+ log.debug("创建默认检测模型:ULTRA_LIGHT_FAST_GENERIC_FACE");
+ FaceModel detectModel = FaceModelFactory.getInstance().getModel(detectModelConfig);
+ log.debug("创建检测模型完毕");
+ config.setDetectModel(detectModel);
return config;
}
- @Override
- public List extractFeatures(String imagePath) {
- return extractFeatures(imagePath, getDefaultConfig());
- }
-
- @Override
- public List extractFeatures(byte[] imageData) {
- return extractFeatures(imageData, getDefaultConfig());
- }
-
@Override
public List extractFeatures(BufferedImage image) {
- return extractFeatures(image, getDefaultConfig());
- }
-
- @Override
- public List extractFeatures(BufferedImage image, FaceExtractConfig config) {
- if(Objects.isNull(config)){
- throw new FaceException("config为null");
- }
List featureList = new ArrayList();
- if(Objects.isNull(config.getDetectModelConfig())){
- throw new FaceException("config.detectModelConfig为null");
- }
- FaceModel faceModel = FaceModelFactory.getInstance().getModel(config.getDetectModelConfig());
- DetectionResponse detectedResult = faceModel.detect(image);
+ DetectionResponse detectedResult = config.getExtractConfig().getDetectModel().detect(image);
if(Objects.isNull(detectedResult) || Objects.isNull(detectedResult.getDetectionInfoList()) || detectedResult.getDetectionInfoList().isEmpty()){
throw new FaceException("未检测到人脸");
}
@@ -237,7 +232,7 @@ public class FeatureExtractionModel extends AbstractFaceModel implements AutoClo
//裁剪人脸
Image subImage = djlImage.getSubImage(rectangle.getX(), rectangle.getY() , rectangle.getWidth() , rectangle.getHeight());
//人脸对齐
- if(config.isAlign()){
+ if(config.getExtractConfig().isAlign()){
//获取子图中人脸关键点坐标
double[][] pointsArray = FaceUtils.facePoints(detectionInfo.getFaceInfo().getKeyPoints());
NDArray srcPoints = manager.create(pointsArray);
@@ -263,8 +258,21 @@ public class FeatureExtractionModel extends AbstractFaceModel implements AutoClo
return featureList;
}
+
@Override
- public List extractFeatures(String imagePath, FaceExtractConfig config) {
+ public List extractFeatures(byte[] imageData) {
+ if(Objects.isNull(imageData)){
+ throw new FaceException("图像无效");
+ }
+ try {
+ return extractFeatures(ImageIO.read(new ByteArrayInputStream(imageData)));
+ } catch (IOException e) {
+ throw new FaceException("错误的图像", e);
+ }
+ }
+
+ @Override
+ public List extractFeatures(String imagePath) {
if(!FileUtils.isFileExists(imagePath)){
throw new FaceException("图像文件不存在");
}
@@ -275,49 +283,15 @@ public class FeatureExtractionModel extends AbstractFaceModel implements AutoClo
} catch (IOException e) {
throw new FaceException("无效图片路径", e);
}
- return extractFeatures(image, config);
- }
-
- @Override
- public List extractFeatures(byte[] imageData, FaceExtractConfig config) {
- if(Objects.isNull(imageData)){
- throw new FaceException("图像无效");
- }
- try {
- return extractFeatures(ImageIO.read(new ByteArrayInputStream(imageData)), config);
- } catch (IOException e) {
- throw new FaceException("错误的图像", e);
- }
+ return extractFeatures(image);
}
@Override
public float[] extractTopFaceFeature(BufferedImage image) {
- return extractTopFaceFeature(image, getDefaultConfig());
- }
-
- @Override
- public float[] extractTopFaceFeature(String imagePath) {
- return extractTopFaceFeature(imagePath, getDefaultConfig());
- }
-
- @Override
- public float[] extractTopFaceFeature(byte[] imageData) {
- return extractTopFaceFeature(imageData, getDefaultConfig());
- }
-
- @Override
- public float[] extractTopFaceFeature(BufferedImage image, FaceExtractConfig config) {
- if(Objects.isNull(config)){
- throw new FaceException("config为null");
- }
- if(Objects.isNull(config.getDetectModelConfig())){
- throw new FaceException("config.detectModelConfig为null");
- }
Image djlImage = ImageFactory.getInstance().fromImage(OpenCVUtils.image2Mat(image));
float[] features = null;
- if(config.isCropFace()){
- FaceModel faceModel = FaceModelFactory.getInstance().getModel(config.getDetectModelConfig());
- DetectionResponse detectedResult = faceModel.detect(image);
+ if(config.getExtractConfig().isCropFace()){
+ DetectionResponse detectedResult = config.getExtractConfig().getDetectModel().detect(image);
if(Objects.isNull(detectedResult) || Objects.isNull(detectedResult.getDetectionInfoList()) || detectedResult.getDetectionInfoList().isEmpty()){
throw new FaceException("未检测到人脸");
}
@@ -327,7 +301,7 @@ public class FeatureExtractionModel extends AbstractFaceModel implements AutoClo
//裁剪人脸
Image subImage = djlImage.getSubImage(rectangle.getX(), rectangle.getY() , rectangle.getWidth() , rectangle.getHeight());
//人脸对齐
- if(config.isAlign()){
+ if(config.getExtractConfig().isAlign()){
NDManager manager = NDManager.newBaseManager();
//获取子图中人脸关键点坐标
double[][] pointsArray = FaceUtils.facePoints(detectionInfo.getFaceInfo().getKeyPoints());
@@ -355,7 +329,7 @@ public class FeatureExtractionModel extends AbstractFaceModel implements AutoClo
}
@Override
- public float[] extractTopFaceFeature(String imagePath, FaceExtractConfig config) {
+ public float[] extractTopFaceFeature(String imagePath) {
if(!FileUtils.isFileExists(imagePath)){
throw new FaceException("图像文件不存在");
}
@@ -366,16 +340,16 @@ public class FeatureExtractionModel extends AbstractFaceModel implements AutoClo
} catch (IOException e) {
throw new FaceException("无效图片路径", e);
}
- return extractTopFaceFeature(image, config);
+ return extractTopFaceFeature(image);
}
@Override
- public float[] extractTopFaceFeature(byte[] imageData, FaceExtractConfig config) {
+ public float[] extractTopFaceFeature(byte[] imageData) {
if(Objects.isNull(imageData)){
throw new FaceException("图像无效");
}
try {
- return extractTopFaceFeature(ImageIO.read(new ByteArrayInputStream(imageData)), config);
+ return extractTopFaceFeature(ImageIO.read(new ByteArrayInputStream(imageData)));
} catch (IOException e) {
throw new FaceException("错误的图像", e);
}
diff --git a/smartjavaai-face/src/main/java/cn/smartjavaai/face/model/facerec/SeetaFace6Model.java b/smartjavaai-face/src/main/java/cn/smartjavaai/face/model/facerec/SeetaFace6Model.java
index fabb2f7..0ae0013 100644
--- a/smartjavaai-face/src/main/java/cn/smartjavaai/face/model/facerec/SeetaFace6Model.java
+++ b/smartjavaai-face/src/main/java/cn/smartjavaai/face/model/facerec/SeetaFace6Model.java
@@ -629,6 +629,7 @@ public class SeetaFace6Model extends AbstractFaceModel {
@Override
public FaceResult search(BufferedImage image) {
+ long time1 = System.currentTimeMillis();
if(!ImageUtils.isImageValid(image)){
throw new FaceException("图像无效");
}
@@ -648,7 +649,12 @@ public class SeetaFace6Model extends AbstractFaceModel {
if(similarity[0] < config.getSimilarityThreshold()){
return null;
}
- return searchFaceDb(index[0], similarity[0]);
+ long time2 = System.currentTimeMillis();
+ System.out.println("总耗时1:" + (time2 - time1) + " ms");
+ FaceResult faceResult = searchFaceDb(index[0], similarity[0]);
+ long time3 = System.currentTimeMillis();
+ System.out.println("总耗时2:" + (time3 - time2) + " ms");
+ return faceResult;
} catch (FaceException e) {
throw e;
} catch (Exception e) {
diff --git a/smartjavaai-face/src/main/java/cn/smartjavaai/face/utils/OpenCVUtils.java b/smartjavaai-face/src/main/java/cn/smartjavaai/face/utils/OpenCVUtils.java
index 1061ffe..878c5a3 100644
--- a/smartjavaai-face/src/main/java/cn/smartjavaai/face/utils/OpenCVUtils.java
+++ b/smartjavaai-face/src/main/java/cn/smartjavaai/face/utils/OpenCVUtils.java
@@ -111,8 +111,26 @@ public class OpenCVUtils {
public static Mat image2Mat(BufferedImage img) {
int width = img.getWidth();
int height = img.getHeight();
+ int channels;
+
+ // 获取图像类型
+ int imageType = img.getType();
+
+ // 判断是3通道还是4通道
+ if (imageType == BufferedImage.TYPE_3BYTE_BGR) {
+ channels = 3;
+ } else if (imageType == BufferedImage.TYPE_4BYTE_ABGR || imageType == BufferedImage.TYPE_4BYTE_ABGR_PRE) {
+ channels = 4;
+ } else {
+ // 如果不是已知格式,强制转换为 3 通道 BGR
+ BufferedImage convertedImg = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
+ convertedImg.getGraphics().drawImage(img, 0, 0, null);
+ img = convertedImg;
+ channels = 3;
+ }
+
byte[] data = ((DataBufferByte) img.getRaster().getDataBuffer()).getData();
- Mat mat = new Mat(height, width, CvType.CV_8UC3);
+ Mat mat = new Mat(height, width, CvType.CV_8UC(channels));
mat.put(0, 0, data);
return mat;
}
diff --git a/smartjavaai-objectdetection/pom.xml b/smartjavaai-objectdetection/pom.xml
index 6d6e156..2c60614 100644
--- a/smartjavaai-objectdetection/pom.xml
+++ b/smartjavaai-objectdetection/pom.xml
@@ -6,11 +6,11 @@
cn.smartjavaai
smartjavaai-parent
- 1.0.12
+ 1.0.13
smartjavaai-objectdetection
- 1.0.12
+ 1.0.13
smartjavaai-objectdetection
SmartJavaAI
https://github.com/geekwenjie/SmartJavaAI
@@ -23,8 +23,8 @@
- 11
- 11
+
+
UTF-8
true
@@ -72,7 +72,7 @@
maven-javadoc-plugin
3.1.0
- ${java.home}/bin/javadoc
+
none
-Xdoclint:none
diff --git a/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/DetectorModelConfig.java b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/config/DetectorModelConfig.java
similarity index 53%
rename from smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/DetectorModelConfig.java
rename to smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/config/DetectorModelConfig.java
index 3d3a466..f1440d0 100644
--- a/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/DetectorModelConfig.java
+++ b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/config/DetectorModelConfig.java
@@ -1,6 +1,8 @@
-package cn.smartjavaai.objectdetection;
+package cn.smartjavaai.objectdetection.config;
import cn.smartjavaai.common.enums.DeviceEnum;
+import cn.smartjavaai.objectdetection.constant.DetectorConstant;
+import cn.smartjavaai.objectdetection.enums.DetectorModelEnum;
import lombok.Data;
/**
@@ -20,13 +22,25 @@ public class DetectorModelConfig {
/**
* 置信度阈值
*/
- private float threshold = DetectorConfig.DEFAULT_THRESHOLD;
+ private float threshold = DetectorConstant.DEFAULT_THRESHOLD;
/**
* 设备类型
*/
private DeviceEnum device;
+ /**
+ * 模型路径
+ */
+ private String modelPath;
+
+ /**
+ * 候选框数量:默认为8400. 应设置0到8400之间的整数
+ * 用于性能优化的关键参数,它通过限制模型后处理阶段需要处理的候选框(bounding boxes)数量来提高推理速度
+ * 建议不低于1000
+ */
+ private int maxBox;
+
public DetectorModelConfig() {
}
diff --git a/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/DetectorConfig.java b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/constant/DetectorConstant.java
similarity index 62%
rename from smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/DetectorConfig.java
rename to smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/constant/DetectorConstant.java
index a7502ac..fb83c6d 100644
--- a/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/DetectorConfig.java
+++ b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/constant/DetectorConstant.java
@@ -1,14 +1,17 @@
-package cn.smartjavaai.objectdetection;
+package cn.smartjavaai.objectdetection.constant;
/**
* @author dwj
* @date 2025/4/7
*/
-public class DetectorConfig {
+public class DetectorConstant {
/**
* 置信度阈值
*/
public static final float DEFAULT_THRESHOLD = 0.5F;
+
+
+
}
diff --git a/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/criteria/CriteriaBuilderFactory.java b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/criteria/CriteriaBuilderFactory.java
new file mode 100644
index 0000000..44cc0d2
--- /dev/null
+++ b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/criteria/CriteriaBuilderFactory.java
@@ -0,0 +1,43 @@
+package cn.smartjavaai.objectdetection.criteria;
+
+import ai.djl.modality.cv.Image;
+import ai.djl.modality.cv.output.DetectedObjects;
+import ai.djl.repository.zoo.Criteria;
+import cn.smartjavaai.objectdetection.config.DetectorModelConfig;
+import cn.smartjavaai.objectdetection.enums.DetectorModelEnum;
+import cn.smartjavaai.objectdetection.exception.DetectionException;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * Criteria构建工厂
+ * @author dwj
+ * @date 2025/5/14
+ */
+public class CriteriaBuilderFactory {
+
+ public static Criteria createCriteria(DetectorModelConfig config) {
+ //以下模型modelPath不允许为空
+ if(config.getModelEnum() == DetectorModelEnum.YOLOV8_OFFICIAL ||
+ config.getModelEnum() == DetectorModelEnum.YOLOV12_OFFICIAL ||
+ config.getModelEnum() == DetectorModelEnum.YOLOV8_CUSTOM ||
+ config.getModelEnum() == DetectorModelEnum.YOLOV12_CUSTOM){
+ if(StringUtils.isBlank(config.getModelPath())){
+ throw new DetectionException("modelPath is null");
+ }
+ }
+ switch (config.getModelEnum()) {
+ case YOLOV8_OFFICIAL:
+ return new YoloCriteriaBuilder().buildCriteria(config);
+ case YOLOV12_OFFICIAL:
+ return new YoloCriteriaBuilder().buildCriteria(config);
+ case YOLOV8_CUSTOM:
+ return new YoloCriteriaBuilder().buildCriteria(config);
+ case YOLOV12_CUSTOM:
+ return new YoloCriteriaBuilder().buildCriteria(config);
+ // 其他类型
+ default:
+ return new DJLModelCriteriaBuilder().buildCriteria(config);
+ }
+ }
+
+}
diff --git a/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/criteria/CriteriaBuilderStrategy.java b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/criteria/CriteriaBuilderStrategy.java
new file mode 100644
index 0000000..f54c0b7
--- /dev/null
+++ b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/criteria/CriteriaBuilderStrategy.java
@@ -0,0 +1,22 @@
+package cn.smartjavaai.objectdetection.criteria;
+
+import ai.djl.modality.cv.Image;
+import ai.djl.modality.cv.output.DetectedObjects;
+import ai.djl.repository.zoo.Criteria;
+import cn.smartjavaai.objectdetection.config.DetectorModelConfig;
+
+/**
+ * 模型加载策略接口,用于根据不同模型类型构建对应的 DJL Criteria 实例
+ * @author dwj
+ * @date 2025/5/14
+ */
+public interface CriteriaBuilderStrategy {
+
+ /**
+ * 根据模型类型构建对应的 DJL Criteria 实例
+ * @param config
+ * @return
+ */
+ Criteria buildCriteria(DetectorModelConfig config);
+
+}
diff --git a/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/criteria/DJLModelCriteriaBuilder.java b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/criteria/DJLModelCriteriaBuilder.java
new file mode 100644
index 0000000..4554866
--- /dev/null
+++ b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/criteria/DJLModelCriteriaBuilder.java
@@ -0,0 +1,40 @@
+package cn.smartjavaai.objectdetection.criteria;
+
+import ai.djl.Application;
+import ai.djl.Device;
+import ai.djl.modality.cv.Image;
+import ai.djl.modality.cv.output.DetectedObjects;
+import ai.djl.repository.zoo.Criteria;
+import ai.djl.training.util.ProgressBar;
+import cn.smartjavaai.common.enums.DeviceEnum;
+import cn.smartjavaai.objectdetection.config.DetectorModelConfig;
+import cn.smartjavaai.objectdetection.constant.DetectorConstant;
+
+import java.util.Objects;
+
+/**
+ * DJL提供的Criteria 构建器
+ * @author dwj
+ * @date 2025/5/14
+ */
+public class DJLModelCriteriaBuilder implements CriteriaBuilderStrategy {
+
+ private static final String DJL_MODEL_PREFIX = "djl://";
+
+ @Override
+ public Criteria buildCriteria(DetectorModelConfig config) {
+ Device device = null;
+ if(!Objects.isNull(config.getDevice())){
+ device = config.getDevice() == DeviceEnum.CPU ? Device.cpu() : Device.gpu();
+ }
+ Criteria criteria = Criteria.builder()
+ .optApplication(Application.CV.OBJECT_DETECTION)
+ .setTypes(Image.class, DetectedObjects.class)
+ .optArgument("threshold", config.getThreshold() > 0 ? config.getThreshold() : DetectorConstant.DEFAULT_THRESHOLD)
+ .optModelUrls(DJL_MODEL_PREFIX + config.getModelEnum().getModelUri())
+ .optDevice(device)
+ .optProgress(new ProgressBar())
+ .build();
+ return criteria;
+ }
+}
diff --git a/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/criteria/YoloCriteriaBuilder.java b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/criteria/YoloCriteriaBuilder.java
new file mode 100644
index 0000000..11605ee
--- /dev/null
+++ b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/criteria/YoloCriteriaBuilder.java
@@ -0,0 +1,40 @@
+package cn.smartjavaai.objectdetection.criteria;
+
+import ai.djl.modality.cv.Image;
+import ai.djl.modality.cv.output.DetectedObjects;
+import ai.djl.modality.cv.translator.YoloV8TranslatorFactory;
+import ai.djl.repository.zoo.Criteria;
+import ai.djl.training.util.ProgressBar;
+import cn.smartjavaai.objectdetection.constant.DetectorConstant;
+import cn.smartjavaai.objectdetection.config.DetectorModelConfig;
+
+import java.nio.file.Paths;
+
+/**
+ * YOLO模型Criteria 构建器
+ * @author dwj
+ * @date 2025/5/14
+ */
+public class YoloCriteriaBuilder implements CriteriaBuilderStrategy {
+ @Override
+ public Criteria buildCriteria(DetectorModelConfig config) {
+ Criteria.Builder criteriaBuilder = Criteria.builder()
+ .setTypes(Image.class, DetectedObjects.class)
+ //.optModelUrls("/Users/wenjie/Documents/develop/face_model/yolo")
+ .optModelPath(Paths.get(config.getModelPath()))
+ .optEngine("OnnxRuntime")
+ .optArgument("width", 640) //将输入图像的宽度缩放为 640 像素
+ .optArgument("height", 640)
+ .optArgument("resize", true)
+ .optArgument("toTensor", true)
+ .optArgument("applyRatio", true)
+ .optTranslatorFactory(new YoloV8TranslatorFactory())
+ .optProgress(new ProgressBar())
+ .optArgument("threshold", config.getThreshold() > 0 ? config.getThreshold() : DetectorConstant.DEFAULT_THRESHOLD);
+ if(config.getMaxBox() > 0){
+ criteriaBuilder.optArgument("maxBox", config.getMaxBox());
+ }
+ Criteria criteria = criteriaBuilder.build();
+ return criteria;
+ }
+}
diff --git a/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/DetectorModelEnum.java b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/enums/DetectorModelEnum.java
similarity index 93%
rename from smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/DetectorModelEnum.java
rename to smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/enums/DetectorModelEnum.java
index 8a8d15a..ad69fb4 100644
--- a/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/DetectorModelEnum.java
+++ b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/enums/DetectorModelEnum.java
@@ -1,4 +1,4 @@
-package cn.smartjavaai.objectdetection;
+package cn.smartjavaai.objectdetection.enums;
/**
* 目标检测模型枚举
@@ -34,7 +34,14 @@ public enum DetectorModelEnum {
YOLO3_DARKNET_COCO_608("ai.djl.mxnet/yolo/0.0.1/yolo3_darknet_coco_608"),
YOLO3_MOBILENET_COCO_320("ai.djl.mxnet/yolo/0.0.1/yolo3_mobilenet_coco_320"),
YOLO3_MOBILENET_COCO_416("ai.djl.mxnet/yolo/0.0.1/yolo3_mobilenet_coco_416"),
- YOLO3_MOBILENET_COCO_608("ai.djl.mxnet/yolo/0.0.1/yolo3_mobilenet_coco_608");
+ YOLO3_MOBILENET_COCO_608("ai.djl.mxnet/yolo/0.0.1/yolo3_mobilenet_coco_608"),
+
+ YOLOV12_OFFICIAL(""),
+ YOLOV8_OFFICIAL(""),
+
+ YOLOV8_CUSTOM(""),
+
+ YOLOV12_CUSTOM("");
/**
* 根据名称获取枚举 (忽略大小写和下划线变体)
diff --git a/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/model/DetectorModel.java b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/model/DetectorModel.java
index 133a57c..0f23684 100644
--- a/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/model/DetectorModel.java
+++ b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/model/DetectorModel.java
@@ -1,41 +1,34 @@
package cn.smartjavaai.objectdetection.model;
-import ai.djl.Application;
-import ai.djl.Device;
import ai.djl.MalformedModelException;
import ai.djl.inference.Predictor;
import ai.djl.modality.cv.Image;
import ai.djl.modality.cv.ImageFactory;
import ai.djl.modality.cv.output.DetectedObjects;
-import ai.djl.opencv.OpenCVImageFactory;
+import ai.djl.modality.cv.translator.YoloV8TranslatorFactory;
import ai.djl.repository.zoo.Criteria;
import ai.djl.repository.zoo.ModelNotFoundException;
import ai.djl.repository.zoo.ZooModel;
import ai.djl.training.util.ProgressBar;
-import ai.djl.translate.TranslateException;
import cn.smartjavaai.common.entity.DetectionResponse;
-import cn.smartjavaai.common.enums.DeviceEnum;
-import cn.smartjavaai.common.pool.ModelPredictorPoolManager;
import cn.smartjavaai.common.pool.PredictorFactory;
import cn.smartjavaai.common.utils.FileUtils;
import cn.smartjavaai.common.utils.ImageUtils;
import cn.smartjavaai.common.utils.OpenCVUtils;
-import cn.smartjavaai.objectdetection.DetectorConfig;
-import cn.smartjavaai.objectdetection.DetectorModelConfig;
+import cn.smartjavaai.objectdetection.config.DetectorModelConfig;
+import cn.smartjavaai.objectdetection.constant.DetectorConstant;
+import cn.smartjavaai.objectdetection.criteria.CriteriaBuilderFactory;
import cn.smartjavaai.objectdetection.exception.DetectionException;
import cn.smartjavaai.objectdetection.utils.DetectorUtils;
import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.Validate;
+import org.apache.commons.lang3.StringUtils;
import org.apache.commons.pool2.ObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPool;
-import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
-import java.nio.file.Path;
import java.nio.file.Paths;
-import java.time.Duration;
import java.util.Objects;
/**
@@ -50,23 +43,16 @@ public class DetectorModel implements AutoCloseable{
//private Predictor predictor;
- private static final String DJL_MODEL_PREFIX = "djl://";
+
private ObjectPool> predictorPool;
public void loadModel(DetectorModelConfig config){
- Device device = null;
- if(!Objects.isNull(config.getDevice())){
- device = config.getDevice() == DeviceEnum.CPU ? Device.cpu() : Device.gpu();
+ if(Objects.isNull(config.getModelEnum())){
+ throw new DetectionException("未配置模型枚举");
}
- Criteria criteria = Criteria.builder()
- .optApplication(Application.CV.OBJECT_DETECTION)
- .setTypes(Image.class, DetectedObjects.class)
- .optArgument("threshold", config.getThreshold() > 0 ? config.getThreshold() : DetectorConfig.DEFAULT_THRESHOLD)
- .optModelUrls(DJL_MODEL_PREFIX + config.getModelEnum().getModelUri())
- .optDevice(device)
- .optProgress(new ProgressBar())
- .build();
+ Criteria criteria = CriteriaBuilderFactory.createCriteria(config);
+
try {
model = criteria.loadModel();
// 创建池子:每个线程独享 Predictor
diff --git a/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/model/ObjectDetectionModelFactory.java b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/model/ObjectDetectionModelFactory.java
index f41a3b9..cc99cb1 100644
--- a/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/model/ObjectDetectionModelFactory.java
+++ b/smartjavaai-objectdetection/src/main/java/cn/smartjavaai/objectdetection/model/ObjectDetectionModelFactory.java
@@ -1,12 +1,11 @@
package cn.smartjavaai.objectdetection.model;
import cn.smartjavaai.common.config.Config;
-import cn.smartjavaai.objectdetection.DetectorModelConfig;
-import cn.smartjavaai.objectdetection.DetectorModelEnum;
+import cn.smartjavaai.objectdetection.config.DetectorModelConfig;
+import cn.smartjavaai.objectdetection.enums.DetectorModelEnum;
import cn.smartjavaai.objectdetection.exception.DetectionException;
import lombok.extern.slf4j.Slf4j;
-import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
diff --git a/smartjavaai-ocr/pom.xml b/smartjavaai-ocr/pom.xml
index 3087d92..0d11804 100644
--- a/smartjavaai-ocr/pom.xml
+++ b/smartjavaai-ocr/pom.xml
@@ -6,14 +6,14 @@
cn.smartjavaai
smartjavaai-parent
- 1.0.12
+ 1.0.13
smartjavaai-ocr
- 11
- 11
+
+
UTF-8
1.5.8
5.1.2-1.5.8
@@ -41,7 +41,7 @@
- 1.0.12
+ 1.0.13
smartjavaai-ocr
SmartJavaAI
https://github.com/geekwenjie/SmartJavaAI
@@ -84,7 +84,7 @@
maven-javadoc-plugin
3.1.0
- ${java.home}/bin/javadoc
+
none
-Xdoclint:none