mirror of
https://github.com/geekwenjie/SmartJavaAI.git
synced 2026-09-12 20:58:51 +00:00
【人脸识别】 新增多种人脸识别模型
【底层优化】 支持自由选择 OpenCV 或 BufferedImage 作为图像引擎 【通用图像】 全部模型启用 Image 输入,支持各类图片格式与 Image 的互转 【模型管理】 优化模型生命周期,关闭后可重新创建 【人脸识别】 支持在人脸查询结果中绘制姓名标注 【人脸检测】 新增人脸裁剪功能 【修复】 修复若干已知问题,提升系统稳定性
This commit is contained in:
@@ -34,4 +34,8 @@ public interface ActionRecModel extends AutoCloseable{
|
||||
}
|
||||
|
||||
|
||||
default void setFromFactory(boolean fromFactory){
|
||||
throw new UnsupportedOperationException("默认不支持该功能");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@ public class ActionRecModelFactory {
|
||||
throw new DetectionException(e);
|
||||
}
|
||||
model.loadModel(config);
|
||||
model.setFromFactory(true);
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -90,14 +91,6 @@ public class ActionRecModelFactory {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 移除缓存的模型
|
||||
* @param modelEnum
|
||||
*/
|
||||
public static void removeFromCache(ActionRecModelEnum modelEnum) {
|
||||
modelMap.remove(modelEnum);
|
||||
}
|
||||
|
||||
|
||||
// 初始化默认算法
|
||||
static {
|
||||
@@ -107,5 +100,27 @@ public class ActionRecModelFactory {
|
||||
registerAlgorithm(ActionRecModelEnum.VIT_BASE_PATCH16_224_DJL, CommonActionRecModel.class);
|
||||
log.debug("缓存目录:{}", Config.getCachePath());
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭所有已加载的模型
|
||||
*/
|
||||
public void closeAll() {
|
||||
modelMap.values().forEach(model -> {
|
||||
try {
|
||||
model.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
modelMap.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除缓存的模型
|
||||
* @param modelEnum
|
||||
*/
|
||||
public static void removeFromCache(ActionRecModelEnum modelEnum) {
|
||||
modelMap.remove(modelEnum);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -110,6 +110,9 @@ public class CommonActionRecModel implements ActionRecModel{
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
if (fromFactory) {
|
||||
ActionRecModelFactory.removeFromCache(config.getModelEnum());
|
||||
}
|
||||
try {
|
||||
if (predictorPool != null) {
|
||||
predictorPool.close();
|
||||
@@ -125,4 +128,14 @@ public class CommonActionRecModel implements ActionRecModel{
|
||||
log.warn("关闭 model 失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean fromFactory = false;
|
||||
|
||||
@Override
|
||||
public void setFromFactory(boolean fromFactory) {
|
||||
this.fromFactory = fromFactory;
|
||||
}
|
||||
public boolean isFromFactory() {
|
||||
return fromFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,12 @@ import ai.djl.modality.cv.output.DetectedObjects;
|
||||
import ai.djl.repository.zoo.Criteria;
|
||||
import ai.djl.repository.zoo.ModelNotFoundException;
|
||||
import ai.djl.repository.zoo.ZooModel;
|
||||
import cn.smartjavaai.action.model.ActionRecModelFactory;
|
||||
import cn.smartjavaai.common.cv.SmartImageFactory;
|
||||
import cn.smartjavaai.common.entity.DetectionResponse;
|
||||
import cn.smartjavaai.common.entity.R;
|
||||
import cn.smartjavaai.common.pool.PredictorFactory;
|
||||
import cn.smartjavaai.common.utils.ImageUtils;
|
||||
import cn.smartjavaai.instanceseg.config.InstanceSegModelConfig;
|
||||
import cn.smartjavaai.instanceseg.criteria.InstanceSegCriteriaFactory;
|
||||
import cn.smartjavaai.instanceseg.exception.InstanceSegException;
|
||||
@@ -124,8 +126,9 @@ public class CommonInstanceSegModel implements InstanceSegModel {
|
||||
|
||||
@Override
|
||||
public R<DetectionResponse> detectAndDraw(String imagePath, String outputPath) {
|
||||
Image img = null;
|
||||
try {
|
||||
Image img = SmartImageFactory.getInstance().fromFile(Paths.get(imagePath));
|
||||
img = SmartImageFactory.getInstance().fromFile(Paths.get(imagePath));
|
||||
DetectedObjects detectedObjects = detectCore(img);
|
||||
if(Objects.isNull(detectedObjects) || detectedObjects.getNumberOfObjects() == 0){
|
||||
return R.fail(R.Status.NO_OBJECT_DETECTED);
|
||||
@@ -136,11 +139,16 @@ public class CommonInstanceSegModel implements InstanceSegModel {
|
||||
return R.ok(detectionResponse);
|
||||
} catch (IOException e) {
|
||||
throw new InstanceSegException(e);
|
||||
} finally {
|
||||
ImageUtils.releaseOpenCVMat(img);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
if (fromFactory) {
|
||||
InstanceSegModelFactory.removeFromCache(config.getModelEnum());
|
||||
}
|
||||
try {
|
||||
if (predictorPool != null) {
|
||||
predictorPool.close();
|
||||
@@ -156,4 +164,14 @@ public class CommonInstanceSegModel implements InstanceSegModel {
|
||||
log.warn("关闭 model 失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean fromFactory = false;
|
||||
|
||||
@Override
|
||||
public void setFromFactory(boolean fromFactory) {
|
||||
this.fromFactory = fromFactory;
|
||||
}
|
||||
public boolean isFromFactory() {
|
||||
return fromFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,5 +43,8 @@ public interface InstanceSegModel extends AutoCloseable{
|
||||
throw new UnsupportedOperationException("默认不支持该功能");
|
||||
}
|
||||
|
||||
default void setFromFactory(boolean fromFactory){
|
||||
throw new UnsupportedOperationException("默认不支持该功能");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ public class InstanceSegModelFactory {
|
||||
throw new DetectionException(e);
|
||||
}
|
||||
model.loadModel(config);
|
||||
model.setFromFactory(true);
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -97,6 +98,19 @@ public class InstanceSegModelFactory {
|
||||
modelMap.remove(modelEnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭所有已加载的模型
|
||||
*/
|
||||
public void closeAll() {
|
||||
modelMap.values().forEach(model -> {
|
||||
try {
|
||||
model.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
modelMap.clear();
|
||||
}
|
||||
|
||||
// 初始化默认算法
|
||||
static {
|
||||
|
||||
@@ -12,6 +12,8 @@ import cn.smartjavaai.common.cv.SmartImageFactory;
|
||||
import cn.smartjavaai.common.entity.DetectionResponse;
|
||||
import cn.smartjavaai.common.entity.R;
|
||||
import cn.smartjavaai.common.pool.PredictorFactory;
|
||||
import cn.smartjavaai.common.utils.ImageUtils;
|
||||
import cn.smartjavaai.instanceseg.model.InstanceSegModelFactory;
|
||||
import cn.smartjavaai.obb.config.ObbDetModelConfig;
|
||||
import cn.smartjavaai.obb.criteria.ObbDetCriteriaFactory;
|
||||
import cn.smartjavaai.obb.entity.ObbResult;
|
||||
@@ -125,8 +127,9 @@ public class CommonObbDetModel implements ObbDetModel {
|
||||
|
||||
@Override
|
||||
public R<DetectionResponse> detectAndDraw(String imagePath, String outputPath) {
|
||||
Image img = null;
|
||||
try {
|
||||
Image img = SmartImageFactory.getInstance().fromFile(Paths.get(imagePath));
|
||||
img = SmartImageFactory.getInstance().fromFile(Paths.get(imagePath));
|
||||
ObbResult obbResult = detectCore(img);
|
||||
if(Objects.isNull(obbResult) || CollectionUtils.isEmpty(obbResult.getRotatedBoxeList())){
|
||||
return R.fail(R.Status.NO_OBJECT_DETECTED);
|
||||
@@ -137,11 +140,16 @@ public class CommonObbDetModel implements ObbDetModel {
|
||||
return R.ok(detectionResponse);
|
||||
} catch (IOException e) {
|
||||
throw new ObbDetException(e);
|
||||
} finally {
|
||||
ImageUtils.releaseOpenCVMat(img);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
if (fromFactory) {
|
||||
ObbDetModelFactory.removeFromCache(config.getModelEnum());
|
||||
}
|
||||
try {
|
||||
if (predictorPool != null) {
|
||||
predictorPool.close();
|
||||
@@ -157,4 +165,14 @@ public class CommonObbDetModel implements ObbDetModel {
|
||||
log.warn("关闭 model 失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean fromFactory = false;
|
||||
|
||||
@Override
|
||||
public void setFromFactory(boolean fromFactory) {
|
||||
this.fromFactory = fromFactory;
|
||||
}
|
||||
public boolean isFromFactory() {
|
||||
return fromFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,4 +57,7 @@ public interface ObbDetModel extends AutoCloseable{
|
||||
}
|
||||
|
||||
|
||||
default void setFromFactory(boolean fromFactory){
|
||||
throw new UnsupportedOperationException("默认不支持该功能");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ public class ObbDetModelFactory {
|
||||
throw new DetectionException(e);
|
||||
}
|
||||
model.loadModel(config);
|
||||
model.setFromFactory(true);
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -97,6 +98,19 @@ public class ObbDetModelFactory {
|
||||
modelMap.remove(modelEnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭所有已加载的模型
|
||||
*/
|
||||
public void closeAll() {
|
||||
modelMap.values().forEach(model -> {
|
||||
try {
|
||||
model.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
modelMap.clear();
|
||||
}
|
||||
|
||||
// 初始化默认算法
|
||||
static {
|
||||
|
||||
@@ -4,22 +4,20 @@ import ai.djl.MalformedModelException;
|
||||
import ai.djl.engine.Engine;
|
||||
import ai.djl.inference.Predictor;
|
||||
import ai.djl.modality.cv.Image;
|
||||
import ai.djl.modality.cv.ImageFactory;
|
||||
import ai.djl.modality.cv.output.BoundingBox;
|
||||
import ai.djl.modality.cv.output.DetectedObjects;
|
||||
import ai.djl.repository.zoo.Criteria;
|
||||
import ai.djl.repository.zoo.ModelNotFoundException;
|
||||
import ai.djl.repository.zoo.ZooModel;
|
||||
import cn.smartjavaai.common.cv.SmartImageFactory;
|
||||
import cn.smartjavaai.common.entity.DetectionResponse;
|
||||
import cn.smartjavaai.common.entity.R;
|
||||
import cn.smartjavaai.common.pool.PredictorFactory;
|
||||
import cn.smartjavaai.common.utils.BufferedImageUtils;
|
||||
import cn.smartjavaai.common.utils.FileUtils;
|
||||
import cn.smartjavaai.common.utils.ImageUtils;
|
||||
import cn.smartjavaai.common.utils.OpenCVUtils;
|
||||
import cn.smartjavaai.objectdetection.config.DetectorModelConfig;
|
||||
import cn.smartjavaai.objectdetection.criteria.CriteriaBuilderFactory;
|
||||
import cn.smartjavaai.objectdetection.exception.DetectionException;
|
||||
import cn.smartjavaai.vision.utils.CategoryMaskFilter;
|
||||
import cn.smartjavaai.vision.utils.DetectedObjectsFilter;
|
||||
import cn.smartjavaai.vision.utils.DetectorUtils;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -31,8 +29,6 @@ import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.*;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
@@ -86,23 +82,21 @@ public class DetectorModel implements AutoCloseable{
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
@Deprecated
|
||||
public DetectionResponse detect(String imagePath){
|
||||
if(!FileUtils.isFileExists(imagePath)){
|
||||
throw new DetectionException("图像文件不存在");
|
||||
}
|
||||
Image image = null;
|
||||
try {
|
||||
image = ImageFactory.getInstance().fromFile(Paths.get(imagePath));
|
||||
DetectedObjects detectedObjects = detect(image);
|
||||
image = SmartImageFactory.getInstance().fromFile(Paths.get(imagePath));
|
||||
DetectedObjects detectedObjects = detectCore(image);
|
||||
return DetectorUtils.convertToDetectionResponse(detectedObjects, image);
|
||||
} catch (Exception e) {
|
||||
throw new DetectionException(e);
|
||||
} finally {
|
||||
if (image != null){
|
||||
((Mat)image.getWrappedImage()).release();
|
||||
}
|
||||
ImageUtils.releaseOpenCVMat(image);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -117,8 +111,8 @@ public class DetectorModel implements AutoCloseable{
|
||||
}
|
||||
Image img = null;
|
||||
try {
|
||||
img = ImageFactory.getInstance().fromFile(Paths.get(imagePath));
|
||||
DetectedObjects detectedObjects = detect(img);
|
||||
img = SmartImageFactory.getInstance().fromFile(Paths.get(imagePath));
|
||||
DetectedObjects detectedObjects = detectCore(img);
|
||||
if(Objects.isNull(detectedObjects) || detectedObjects.getNumberOfObjects() == 0){
|
||||
throw new DetectionException("未检测到图片中的物体");
|
||||
}
|
||||
@@ -129,9 +123,7 @@ public class DetectorModel implements AutoCloseable{
|
||||
} catch (IOException e) {
|
||||
throw new DetectionException(e);
|
||||
} finally {
|
||||
if (img != null){
|
||||
((Mat)img.getWrappedImage()).release();
|
||||
}
|
||||
ImageUtils.releaseOpenCVMat(img);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,6 +132,7 @@ public class DetectorModel implements AutoCloseable{
|
||||
* @param imageData
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public DetectionResponse detect(byte[] imageData){
|
||||
if(Objects.isNull(imageData)){
|
||||
throw new DetectionException("图像无效");
|
||||
@@ -159,21 +152,20 @@ public class DetectorModel implements AutoCloseable{
|
||||
* @param image
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public DetectionResponse detect(BufferedImage image){
|
||||
if(!ImageUtils.isImageValid(image)){
|
||||
if(!BufferedImageUtils.isImageValid(image)){
|
||||
throw new DetectionException("图像无效");
|
||||
}
|
||||
Image img = null;
|
||||
try {
|
||||
img = ImageFactory.getInstance().fromImage(OpenCVUtils.image2Mat(image));
|
||||
DetectedObjects detectedObjects = detect(img);
|
||||
img = SmartImageFactory.getInstance().fromBufferedImage(image);
|
||||
DetectedObjects detectedObjects = detectCore(img);
|
||||
return DetectorUtils.convertToDetectionResponse(detectedObjects, img);
|
||||
} catch (Exception e) {
|
||||
throw new DetectionException(e);
|
||||
} finally {
|
||||
if (img != null) {
|
||||
((Mat)img.getWrappedImage()).release();
|
||||
}
|
||||
ImageUtils.releaseOpenCVMat(img);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -183,30 +175,20 @@ public class DetectorModel implements AutoCloseable{
|
||||
* @param sourceImage
|
||||
* @return
|
||||
*/
|
||||
@Deprecated
|
||||
public BufferedImage detectAndDraw(BufferedImage sourceImage){
|
||||
if(!ImageUtils.isImageValid(sourceImage)){
|
||||
if(!BufferedImageUtils.isImageValid(sourceImage)){
|
||||
throw new DetectionException("图像无效");
|
||||
}
|
||||
Image img = ImageFactory.getInstance().fromImage(OpenCVUtils.image2Mat(sourceImage));
|
||||
DetectedObjects detectedObjects = detect(img);
|
||||
Image img = SmartImageFactory.getInstance().fromBufferedImage(sourceImage);
|
||||
DetectedObjects detectedObjects = detectCore(img);
|
||||
if(Objects.isNull(detectedObjects) || detectedObjects.getNumberOfObjects() == 0){
|
||||
throw new DetectionException("未检测到图片中的物体");
|
||||
}
|
||||
img.drawBoundingBoxes(detectedObjects);
|
||||
try {
|
||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||
// 调用 save 方法将 Image 写入字节流
|
||||
img.save(outputStream, "png");
|
||||
// 将字节流转换为 BufferedImage
|
||||
byte[] imageBytes = outputStream.toByteArray();
|
||||
return ImageIO.read(new ByteArrayInputStream(imageBytes));
|
||||
} catch (IOException e) {
|
||||
throw new DetectionException("导出图片失败", e);
|
||||
} finally {
|
||||
if (img != null) {
|
||||
((Mat)img.getWrappedImage()).release();
|
||||
}
|
||||
}
|
||||
BufferedImage drawnImage = ImageUtils.toBufferedImage(img);
|
||||
ImageUtils.releaseOpenCVMat(img);
|
||||
return drawnImage;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -214,7 +196,35 @@ public class DetectorModel implements AutoCloseable{
|
||||
* @param image
|
||||
* @return
|
||||
*/
|
||||
public DetectedObjects detect(Image image){
|
||||
public DetectionResponse detect(Image image){
|
||||
DetectedObjects detectedObjects = detectCore(image);
|
||||
return DetectorUtils.convertToDetectionResponse(detectedObjects, image);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 检测并绘制
|
||||
* @param image
|
||||
* @return
|
||||
*/
|
||||
public DetectionResponse detectAndDraw(Image image){
|
||||
DetectedObjects detectedObjects = detectCore(image);
|
||||
if(Objects.isNull(detectedObjects) || detectedObjects.getNumberOfObjects() == 0){
|
||||
throw new DetectionException("未检测到图片中的物体");
|
||||
}
|
||||
Image img = ImageUtils.copy(image);
|
||||
DetectionResponse detectionResponse = DetectorUtils.convertToDetectionResponse(detectedObjects, img);
|
||||
img.drawBoundingBoxes(detectedObjects);
|
||||
detectionResponse.setDrawnImage(img);
|
||||
return detectionResponse;
|
||||
}
|
||||
|
||||
/**
|
||||
* 目标检测
|
||||
* @param image
|
||||
* @return
|
||||
*/
|
||||
public DetectedObjects detectCore(Image image){
|
||||
Predictor<Image, DetectedObjects> predictor = null;
|
||||
try {
|
||||
predictor = predictorPool.borrowObject();
|
||||
|
||||
@@ -58,5 +58,8 @@ public interface PersonDetModel extends AutoCloseable{
|
||||
throw new UnsupportedOperationException("默认不支持该功能");
|
||||
}
|
||||
|
||||
default void setFromFactory(boolean fromFactory){
|
||||
throw new UnsupportedOperationException("默认不支持该功能");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import ai.djl.modality.cv.output.Mask;
|
||||
import ai.djl.modality.cv.output.Rectangle;
|
||||
import cn.hutool.core.date.LocalDateTimeUtil;
|
||||
import cn.hutool.core.lang.UUID;
|
||||
import cn.smartjavaai.common.cv.SmartImageFactory;
|
||||
import cn.smartjavaai.common.entity.*;
|
||||
import cn.smartjavaai.common.enums.VideoSourceType;
|
||||
import cn.smartjavaai.common.utils.ImageUtils;
|
||||
@@ -230,7 +231,7 @@ public class StreamDetector implements AutoCloseable{
|
||||
mat = converterToMat.convert(frame);
|
||||
if (mat == null) return;
|
||||
|
||||
Image image = ImageFactory.getInstance().fromImage(mat);
|
||||
Image image = SmartImageFactory.getInstance().fromMat(mat);
|
||||
DetectedObjects detectedObjects = predictor.predict(image);
|
||||
// log.info("内部检测结果:{}", detectedObjects.toString());
|
||||
DetectionResponse detectionResponse = DetectorUtils.convertToDetectionResponse(detectedObjects, image);
|
||||
|
||||
@@ -4,6 +4,7 @@ import ai.djl.Device;
|
||||
import ai.djl.modality.Classifications;
|
||||
import ai.djl.modality.cv.Image;
|
||||
import ai.djl.modality.cv.output.Joints;
|
||||
import ai.djl.modality.cv.translator.YoloPoseTranslatorFactory;
|
||||
import ai.djl.repository.zoo.Criteria;
|
||||
import ai.djl.training.util.ProgressBar;
|
||||
import ai.djl.translate.Translator;
|
||||
@@ -20,6 +21,7 @@ import cn.smartjavaai.obb.exception.ObbDetException;
|
||||
import cn.smartjavaai.obb.translator.YoloV11OddTranslator;
|
||||
import cn.smartjavaai.objectdetection.constant.DetectorConstant;
|
||||
import cn.smartjavaai.pose.config.PoseModelConfig;
|
||||
import cn.smartjavaai.pose.enums.PoseModelEnum;
|
||||
import cn.smartjavaai.pose.exception.PoseException;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
@@ -58,19 +60,26 @@ public class PoseCriteriaFactory {
|
||||
* @return
|
||||
*/
|
||||
public static Criteria<Image, Joints[]> createDJLCriteria(PoseModelConfig config, Device device) {
|
||||
if(StringUtils.isNotBlank(config.getModelPath())
|
||||
&& DJLCommonUtils.isServingPropertiesExists(Paths.get(config.getModelPath()))){
|
||||
throw new PoseException("模型所在目录未找到 serving.properties 文件");
|
||||
// if(StringUtils.isNotBlank(config.getModelPath())
|
||||
// && !DJLCommonUtils.isServingPropertiesExists(Paths.get(config.getModelPath()))){
|
||||
// throw new PoseException("模型所在目录未找到 serving.properties 文件");
|
||||
// }
|
||||
|
||||
Criteria<Image, Joints[]> criteria = null;
|
||||
if(config.getModelEnum() == PoseModelEnum.YOLO11N_POSE_PT || config.getModelEnum() == PoseModelEnum.YOLO11N_POSE_ONNX
|
||||
|| config.getModelEnum() == PoseModelEnum.YOLOV8N_POSE_PT || config.getModelEnum() == PoseModelEnum.YOLOV8N_POSE_ONNX){
|
||||
criteria =
|
||||
Criteria.builder()
|
||||
.setTypes(Image.class, Joints[].class)
|
||||
.optModelUrls(StringUtils.isNotBlank(config.getModelPath()) ? null : config.getModelEnum().getModelUri())
|
||||
.optModelPath(StringUtils.isNotBlank(config.getModelPath()) ? Paths.get(config.getModelPath()) : null)
|
||||
.optDevice(device)
|
||||
.optTranslatorFactory(new YoloPoseTranslatorFactory())
|
||||
.optArgument("threshold", config.getThreshold() > 0 ? config.getThreshold() : null)
|
||||
.optProgress(new ProgressBar())
|
||||
.build();
|
||||
}
|
||||
Criteria<Image, Joints[]> criteria =
|
||||
Criteria.builder()
|
||||
.setTypes(Image.class, Joints[].class)
|
||||
.optModelUrls(StringUtils.isNotBlank(config.getModelPath()) ? null : config.getModelEnum().getModelUri())
|
||||
.optModelPath(StringUtils.isNotBlank(config.getModelPath()) ? Paths.get(config.getModelPath()) : null)
|
||||
.optDevice(device)
|
||||
.optArgument("threshold", config.getThreshold() > 0 ? config.getThreshold() : null)
|
||||
.optProgress(new ProgressBar())
|
||||
.build();
|
||||
|
||||
return criteria;
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ import cn.smartjavaai.common.entity.R;
|
||||
import cn.smartjavaai.common.pool.PredictorFactory;
|
||||
import cn.smartjavaai.common.utils.ImageUtils;
|
||||
import cn.smartjavaai.obb.exception.ObbDetException;
|
||||
import cn.smartjavaai.obb.model.ObbDetModelFactory;
|
||||
import cn.smartjavaai.objectdetection.config.PersonDetModelConfig;
|
||||
import cn.smartjavaai.objectdetection.criteria.PersonDetCriteriaFactory;
|
||||
import cn.smartjavaai.objectdetection.exception.DetectionException;
|
||||
@@ -121,6 +122,7 @@ public class CommonPoseModel implements PoseModel {
|
||||
}
|
||||
// 调用 save 方法将 Image 写入字节流
|
||||
img.save(Files.newOutputStream(Paths.get(outputPath)), "png");
|
||||
ImageUtils.releaseOpenCVMat(img);
|
||||
return allJoints;
|
||||
} catch (IOException e) {
|
||||
throw new ObbDetException(e);
|
||||
@@ -129,6 +131,9 @@ public class CommonPoseModel implements PoseModel {
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
if (fromFactory) {
|
||||
PoseDetModelFactory.removeFromCache(config.getModelEnum());
|
||||
}
|
||||
try {
|
||||
if (predictorPool != null) {
|
||||
predictorPool.close();
|
||||
@@ -144,4 +149,14 @@ public class CommonPoseModel implements PoseModel {
|
||||
log.warn("关闭 model 失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean fromFactory = false;
|
||||
|
||||
@Override
|
||||
public void setFromFactory(boolean fromFactory) {
|
||||
this.fromFactory = fromFactory;
|
||||
}
|
||||
public boolean isFromFactory() {
|
||||
return fromFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,6 +76,7 @@ public class PoseDetModelFactory {
|
||||
throw new DetectionException(e);
|
||||
}
|
||||
model.loadModel(config);
|
||||
model.setFromFactory(true);
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -99,6 +100,20 @@ public class PoseDetModelFactory {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 关闭所有已加载的模型
|
||||
*/
|
||||
public void closeAll() {
|
||||
modelMap.values().forEach(model -> {
|
||||
try {
|
||||
model.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
modelMap.clear();
|
||||
}
|
||||
|
||||
// 初始化默认算法
|
||||
static {
|
||||
registerAlgorithm(PoseModelEnum.YOLOV8N_POSE_ONNX, CommonPoseModel.class);
|
||||
|
||||
@@ -49,5 +49,8 @@ public interface PoseModel extends AutoCloseable{
|
||||
throw new UnsupportedOperationException("默认不支持该功能");
|
||||
}
|
||||
|
||||
default void setFromFactory(boolean fromFactory){
|
||||
throw new UnsupportedOperationException("默认不支持该功能");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import cn.smartjavaai.common.utils.Base64ImageUtils;
|
||||
import cn.smartjavaai.common.utils.ImageUtils;
|
||||
import cn.smartjavaai.instanceseg.exception.InstanceSegException;
|
||||
import cn.smartjavaai.objectdetection.exception.DetectionException;
|
||||
import cn.smartjavaai.pose.model.PoseDetModelFactory;
|
||||
import cn.smartjavaai.semseg.config.SemSegModelConfig;
|
||||
import cn.smartjavaai.semseg.criteria.SemSegCriteriaFactory;
|
||||
import cn.smartjavaai.vision.utils.CategoryMaskFilter;
|
||||
@@ -122,6 +123,7 @@ public class CommonSemSegModel implements SemSegModel {
|
||||
}
|
||||
ImageUtils.drawMask(categoryMask, img, 180, 0);
|
||||
img.save(Files.newOutputStream(Paths.get(outputPath)), "png");
|
||||
ImageUtils.releaseOpenCVMat(img);
|
||||
return R.ok(categoryMask);
|
||||
} catch (IOException e) {
|
||||
throw new InstanceSegException(e);
|
||||
@@ -141,6 +143,9 @@ public class CommonSemSegModel implements SemSegModel {
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
if (fromFactory) {
|
||||
SemSegModelFactory.removeFromCache(config.getModelEnum());
|
||||
}
|
||||
try {
|
||||
if (predictorPool != null) {
|
||||
predictorPool.close();
|
||||
@@ -156,4 +161,14 @@ public class CommonSemSegModel implements SemSegModel {
|
||||
log.warn("关闭 model 失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean fromFactory = false;
|
||||
|
||||
@Override
|
||||
public void setFromFactory(boolean fromFactory) {
|
||||
this.fromFactory = fromFactory;
|
||||
}
|
||||
public boolean isFromFactory() {
|
||||
return fromFactory;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,5 +38,8 @@ public interface SemSegModel extends AutoCloseable{
|
||||
}
|
||||
|
||||
|
||||
default void setFromFactory(boolean fromFactory){
|
||||
throw new UnsupportedOperationException("默认不支持该功能");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ public class SemSegModelFactory {
|
||||
throw new DetectionException(e);
|
||||
}
|
||||
model.loadModel(config);
|
||||
model.setFromFactory(true);
|
||||
return model;
|
||||
}
|
||||
|
||||
@@ -97,6 +98,19 @@ public class SemSegModelFactory {
|
||||
modelMap.remove(modelEnum);
|
||||
}
|
||||
|
||||
/**
|
||||
* 关闭所有已加载的模型
|
||||
*/
|
||||
public void closeAll() {
|
||||
modelMap.values().forEach(model -> {
|
||||
try {
|
||||
model.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
});
|
||||
modelMap.clear();
|
||||
}
|
||||
|
||||
// 初始化默认算法
|
||||
static {
|
||||
|
||||
@@ -60,13 +60,13 @@ public class DetectorUtils {
|
||||
DetectionRectangle rectangle = new DetectionRectangle(x, y, width, height);
|
||||
DetectionInfo detectionInfo = new DetectionInfo(rectangle, detection.getProbabilities().get(index).floatValue());
|
||||
//目标检测
|
||||
if(box instanceof Rectangle){
|
||||
ObjectDetInfo objectDetInfo = new ObjectDetInfo(className);
|
||||
detectionInfo.setObjectDetInfo(objectDetInfo);
|
||||
}else if(box instanceof Mask){
|
||||
if(box instanceof Mask){
|
||||
Mask mask = (Mask)box;
|
||||
InstanceSegInfo instanceSegInfo = new InstanceSegInfo(className, mask.getProbDist());
|
||||
detectionInfo.setInstanceSegInfo(instanceSegInfo);
|
||||
}else if(box instanceof Rectangle){
|
||||
ObjectDetInfo objectDetInfo = new ObjectDetInfo(className);
|
||||
detectionInfo.setObjectDetInfo(objectDetInfo);
|
||||
}
|
||||
detectionInfoList.add(detectionInfo);
|
||||
index++;
|
||||
@@ -106,9 +106,9 @@ public class DetectorUtils {
|
||||
Imgproc.line(srcMat, points.get(0).toCvPoint(), points.get(1).toCvPoint(), new Scalar(0, 255, 0), 1);
|
||||
Imgproc.line(srcMat, points.get(1).toCvPoint(), points.get(2).toCvPoint(), new Scalar(0, 255, 0),1);
|
||||
Imgproc.line(srcMat, points.get(2).toCvPoint(), points.get(3).toCvPoint(), new Scalar(0, 255, 0),1);
|
||||
Imgproc.line(srcMat, points.get(3).toCvPoint(), points.get(1).toCvPoint(), new Scalar(0, 255, 0), 1);
|
||||
Imgproc.line(srcMat, points.get(3).toCvPoint(), points.get(0).toCvPoint(), new Scalar(0, 255, 0), 1);
|
||||
// 中文乱码
|
||||
Imgproc.putText(srcMat, box.className, points.get(0).toCvPoint(), Imgproc.FONT_HERSHEY_SCRIPT_SIMPLEX, 1.0, new Scalar(0, 255, 0), 1);
|
||||
Imgproc.putText(srcMat, box.className, points.get(0).toCvPoint(), Imgproc.FONT_HERSHEY_SIMPLEX, 1.0, new Scalar(0, 255, 0), 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user