新增目标检测功能

This commit is contained in:
dengwenjie
2025-04-13 20:33:15 +08:00
parent 4eb02c6d87
commit 241b816e7f
56 changed files with 3300 additions and 1993 deletions

View File

@@ -0,0 +1,84 @@
package cn.smartjavaai.common.entity;
/**
* 检测结果-矩形区域
* @author dwj
*/
public class DetectionRectangle {
public int x;
public int y;
public int width;
public int height;
public float score;
public String className;
public DetectionRectangle() {
}
public DetectionRectangle(int x, int y, int width, int height, float score) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.score = score;
}
public DetectionRectangle(int x, int y, int width, int height, float score, String className) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
this.score = score;
this.className = className;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public float getScore() {
return score;
}
public void setScore(float score) {
this.score = score;
}
public String getClassName() {
return className;
}
public void setClassName(String className) {
this.className = className;
}
}

View File

@@ -0,0 +1,21 @@
package cn.smartjavaai.common.entity;
import java.util.List;
/**
* 检测结果
* @author dwj
* @date 2025/4/12
*/
public class DetectionResponse {
private List<DetectionRectangle> rectangleList;
public List<DetectionRectangle> getRectangleList() {
return rectangleList;
}
public void setRectangleList(List<DetectionRectangle> rectangleList) {
this.rectangleList = rectangleList;
}
}

View File

@@ -1,49 +0,0 @@
package cn.smartjavaai.common.entity;
import java.util.List;
/**
* 矩形区域
* @author dwj
*/
public class Rectangle {
/**
* 矩形区域点集合
*/
List<Point> pointList;
/**
* 矩形区域宽度
*/
int width;
/**
* 矩形区域高度
*/
int height;
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
public List<Point> getPointList() {
return pointList;
}
public void setPointList(List<Point> pointList) {
this.pointList = pointList;
}
}

View File

@@ -0,0 +1,14 @@
package cn.smartjavaai.common.enums;
/**
* 目标检测模型枚举
* @author dwj
* @date 2025/4/4
*/
public enum DeviceEnum {
// resnet50 系列
CPU,
GPU;
}

View File

@@ -0,0 +1,71 @@
package cn.smartjavaai.common.pool;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.ZooModel;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 模型共享池管理器
* @author dwj
* @date 2025/4/8
*/
public class ModelPredictorPoolManager {
// 每个模型的唯一key -> 对应Predictor池
private final Map<String, GenericObjectPool<? extends Predictor<?, ?>>> poolMap = new ConcurrentHashMap<>();
/**
* 注册模型池
* @param key 模型标识符(自定义,如模型路径、模型名等)
* @param model 模型本体
* @param config 池配置(可选)
*/
public <I, O> void registerModel(String key, ZooModel<I, O> model, GenericObjectPoolConfig<Predictor<I, O>> config) {
PredictorFactory<I, O> factory = new PredictorFactory<>(model);
GenericObjectPool<Predictor<I, O>> pool = new GenericObjectPool<>(factory, config);
poolMap.put(key, pool);
}
/**
* 借出一个 Predictor
*/
@SuppressWarnings("unchecked")
public <I, O> Predictor<I, O> borrowPredictor(String key) throws Exception {
GenericObjectPool<Predictor<I, O>> pool = (GenericObjectPool<Predictor<I, O>>) poolMap.get(key);
if (pool == null) {
throw new IllegalArgumentException("模型未注册: " + key);
}
return pool.borrowObject();
}
/**
* 归还一个 Predictor
*/
@SuppressWarnings("unchecked")
public <I, O> void returnPredictor(String key, Predictor<I, O> predictor) {
GenericObjectPool<Predictor<I, O>> pool = (GenericObjectPool<Predictor<I, O>>) poolMap.get(key);
if (pool != null) {
pool.returnObject(predictor);
}
}
/**
* 销毁全部池
*/
public void closeAll() {
for (GenericObjectPool<? extends Predictor<?, ?>> pool : poolMap.values()) {
pool.close();
}
poolMap.clear();
}
}

View File

@@ -0,0 +1,35 @@
package cn.smartjavaai.common.pool;
import ai.djl.inference.Predictor;
import ai.djl.repository.zoo.ZooModel;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.impl.DefaultPooledObject;
/**
* Predictor 工厂类
* @author dwj
* @date 2025/4/8
*/
public class PredictorFactory<I, O> extends BasePooledObjectFactory<Predictor<I, O>> {
private final ZooModel<I, O> model;
public PredictorFactory(ZooModel<I, O> model) {
this.model = model;
}
@Override
public Predictor<I, O> create() {
return model.newPredictor();
}
@Override
public PooledObject<Predictor<I, O>> wrap(Predictor<I, O> predictor) {
return new DefaultPooledObject<>(predictor);
}
@Override
public void destroyObject(PooledObject<Predictor<I, O>> p) {
p.getObject().close();
}
}

View File

@@ -0,0 +1,21 @@
package cn.smartjavaai.common.utils;
import java.io.File;
/**
* 文件操作工具类
* @author dwj
* @date 2025/4/4
*/
public class FileUtils {
/**
* 检查文件是否存在
* @param filePath
* @return
*/
public static boolean isFileExists(String filePath) {
File file = new File(filePath);
return file.exists() && !file.isDirectory(); // 确保是文件且存在
}
}

View File

@@ -1,8 +1,12 @@
package cn.smartjavaai.common.utils;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
//import java.awt.image.ColorConvertOp;
import java.awt.image.ComponentSampleModel;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
/**
@@ -74,4 +78,18 @@ public class ImageUtils {
return image;
}
/**
* 检查图像是否有效
* @param image
* @return
*/
public static boolean isImageValid(BufferedImage image) {
// 检查是否为 null 或尺寸异常如宽高为0
return image != null && image.getWidth() > 0 && image.getHeight() > 0;
}
}