Merge remote-tracking branch 'origin/master'
This commit is contained in:
43
README.md
43
README.md
@@ -1,40 +1,3 @@
|
|||||||
<p align="center">
|
java 17
|
||||||
<img alt="logo" src="https://gdhxkj.oss-cn-guangzhou.aliyuncs.com/file/2025/01/16/蒜头王八_20250116174410A005.png" style="width: 80px;">
|
node16 .20
|
||||||
</p>
|
opencv推测4.10
|
||||||
<h1 align="center" style="margin: 30px 0 30px; font-weight: bold;">rtsp视频分析 v1.0.0</h1>
|
|
||||||
<h4 align="center">基于SpringBoot+Vue前后端分离的rtsp视频分析系统</h4>
|
|
||||||
|
|
||||||
## 平台简介
|
|
||||||
|
|
||||||
这是一个基于ruoyi-vue框架改进而来的RTSP视频分析平台,继承ruoyi框架的基本功能。项目集成了虹软SDK,实现了人脸识别、活体检测、3D角度分析、年龄及性别识别等功能;同时,利用JavaCV进行高效的视频处理,将rtsp视频转成http-flv和ws-flv。后端采用SpringBoot框架,前端则运用了Vue3框架,确保系统的稳定与用户体验的流畅。
|
|
||||||
|
|
||||||
* 前端采用Vue3、Element Plus、XgpLayer。
|
|
||||||
* 后端采用Spring Boot、Spring Security、Redis 、 javaCv & Jwt。
|
|
||||||
|
|
||||||
加微信联系: chenbai0511
|
|
||||||
|
|
||||||
## 内置功能
|
|
||||||
|
|
||||||
1. 若依全功能。
|
|
||||||
2. rtsp视频转http-flv,ws-flv在线播放。
|
|
||||||
3. rtsp视频人脸识别,活体检测,3D角度分析,年龄及性别识别。
|
|
||||||
|
|
||||||
## 演示图
|
|
||||||
|
|
||||||
<table>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://gdhxkj.oss-cn-guangzhou.aliyuncs.com/file/2025/01/16/g1_20250116174656A007.png"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://gdhxkj.oss-cn-guangzhou.aliyuncs.com/file/2025/01/16/g2_20250116174755A009.png"/></td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td><img src="https://gdhxkj.oss-cn-guangzhou.aliyuncs.com/file/2025/01/16/g3_20250116174816A011.png"/></td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
|
|
||||||
## 联系我吧
|
|
||||||
|
|
||||||
<img src="https://gdhxkj.oss-cn-guangzhou.aliyuncs.com/file/2025/01/16/17c8bc62cbd5b58c27775e0c2ff83bd_20250116174058A003.jpg" style="width: 500px; display: block; margin: auto;"/>
|
|
||||||
|
|
||||||
qwq
|
|
||||||
2
pom.xml
2
pom.xml
@@ -42,7 +42,7 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bytedeco</groupId>
|
<groupId>org.bytedeco</groupId>
|
||||||
<artifactId>javacv-platform</artifactId>
|
<artifactId>javacv-platform</artifactId>
|
||||||
<version>1.5.10</version> <!-- 版本号需与项目兼容 -->
|
<version>1.5.12</version> <!-- 版本号需与项目兼容 -->
|
||||||
</dependency>
|
</dependency>
|
||||||
<!-- SpringBoot的依赖配置-->
|
<!-- SpringBoot的依赖配置-->
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ ruoyi:
|
|||||||
# 版权年份
|
# 版权年份
|
||||||
copyrightYear: 2025
|
copyrightYear: 2025
|
||||||
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
|
# 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath)
|
||||||
profile: /home/wangyu/uploadPath
|
profile: D:\temp
|
||||||
# 获取ip地址开关
|
# 获取ip地址开关
|
||||||
addressEnabled: false
|
addressEnabled: false
|
||||||
# 验证码类型 math 数字计算 char 字符验证
|
# 验证码类型 math 数字计算 char 字符验证
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
trash
|
||||||
BIN
ruoyi-admin/src/main/resources/libs/models/garbage/garbage.onnx
Normal file
BIN
ruoyi-admin/src/main/resources/libs/models/garbage/garbage.onnx
Normal file
Binary file not shown.
5
ruoyi-admin/src/main/resources/libs/models/models.json
Normal file
5
ruoyi-admin/src/main/resources/libs/models/models.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
[
|
||||||
|
{"name":"garbage","path":"libs/models/garbage","size":[640,640],"backend":"OpenCV"},
|
||||||
|
{"name":"smoke","path":"libs/models/smoke","size":[640,640],"backend":"OpenCV"}
|
||||||
|
|
||||||
|
]
|
||||||
@@ -35,7 +35,12 @@
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.bytedeco</groupId>
|
<groupId>org.bytedeco</groupId>
|
||||||
<artifactId>javacv-platform</artifactId>
|
<artifactId>javacv-platform</artifactId>
|
||||||
<version>1.5.11</version>
|
<version>1.5.12</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.bytedeco</groupId>
|
||||||
|
<artifactId>opencv-platform</artifactId>
|
||||||
|
<version>4.11.0-1.5.12</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!-- 解析 models.json-->
|
<!-- 解析 models.json-->
|
||||||
|
|||||||
@@ -201,16 +201,15 @@ public class MediaTransferFlvByJavacv extends MediaTransfer implements Runnable
|
|||||||
if (!enableDetection) return;
|
if (!enableDetection) return;
|
||||||
|
|
||||||
modelManager = new ModelManager();
|
modelManager = new ModelManager();
|
||||||
URL json = getClass().getResource("/models/models.json");
|
URL json = getClass().getResource("/libs/models/models.json");
|
||||||
modelManager.load(json);
|
modelManager.load(json);
|
||||||
|
|
||||||
// 你可按需切换单模型或多模型并行
|
// 你可按需切换单模型或多模型并行
|
||||||
// detector = modelManager.get("person-helmet");
|
// detector = modelManager.get("person-helmet");
|
||||||
detector = new CompositeDetector(
|
detector = new CompositeDetector(
|
||||||
"all-models",
|
"all-models",
|
||||||
java.util.List.of(
|
java.util.List.of(
|
||||||
modelManager.get("person-helmet"),
|
modelManager.get("garbage"),
|
||||||
modelManager.get("vehicle-plate")
|
modelManager.get("smoke")
|
||||||
),
|
),
|
||||||
2 // 并行度
|
2 // 并行度
|
||||||
);
|
);
|
||||||
@@ -345,6 +344,7 @@ public class MediaTransferFlvByJavacv extends MediaTransfer implements Runnable
|
|||||||
if (enableDetection) initDetectors();
|
if (enableDetection) initDetectors();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("初始化检测模型失败:{}", e.getMessage(), e);
|
log.error("初始化检测模型失败:{}", e.getMessage(), e);
|
||||||
|
// 模型失败不影响推流,但不禁用检测
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!createGrabber()) return;
|
if (!createGrabber()) return;
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ public final class OnnxYoloDetector implements YoloDetector {
|
|||||||
} else {
|
} else {
|
||||||
this.classes = new String[0];
|
this.classes = new String[0];
|
||||||
}
|
}
|
||||||
|
System.out.println("CV_VERSION = " + CV_VERSION);
|
||||||
try {
|
try {
|
||||||
// 加载ONNX模型
|
// 加载ONNX模型
|
||||||
this.net = readNetFromONNX(onnx);
|
this.net = readNetFromONNX(onnx);
|
||||||
|
|||||||
@@ -25,15 +25,9 @@ public final class OpenVinoYoloDetector implements YoloDetector {
|
|||||||
this.input = new Size(inW, inH);
|
this.input = new Size(inW, inH);
|
||||||
this.colorBGR = colorBGR;
|
this.colorBGR = colorBGR;
|
||||||
|
|
||||||
// 自动查找模型文件
|
String xml = dir.resolve("model.xml").toString();
|
||||||
String xml = findModelFile(dir, ".xml");
|
String bin = dir.resolve("model.bin").toString();
|
||||||
String bin = findModelFile(dir, ".bin");
|
|
||||||
|
|
||||||
if (xml == null || bin == null) {
|
|
||||||
throw new Exception("找不到模型文件,请确保目录中存在 .xml 和 .bin 文件: " + dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 读取类别文件
|
|
||||||
Path clsPath = dir.resolve("classes.txt");
|
Path clsPath = dir.resolve("classes.txt");
|
||||||
if (Files.exists(clsPath)) {
|
if (Files.exists(clsPath)) {
|
||||||
this.classes = Files.readAllLines(clsPath).stream().map(String::trim)
|
this.classes = Files.readAllLines(clsPath).stream().map(String::trim)
|
||||||
@@ -42,34 +36,19 @@ public final class OpenVinoYoloDetector implements YoloDetector {
|
|||||||
this.classes = new String[0];
|
this.classes = new String[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
this.net = readNetFromModelOptimizer(xml, bin);
|
||||||
// 加载模型,但强制使用OpenCV后端
|
|
||||||
this.net = readNetFromModelOptimizer(xml, bin);
|
|
||||||
|
|
||||||
// 强制使用OpenCV后端,避免OpenVINO依赖
|
boolean set = false;
|
||||||
|
if ("openvino".equalsIgnoreCase(backend)) {
|
||||||
|
try {
|
||||||
|
net.setPreferableBackend(DNN_BACKEND_INFERENCE_ENGINE);
|
||||||
|
net.setPreferableTarget(DNN_TARGET_CPU);
|
||||||
|
set = true;
|
||||||
|
} catch (Throwable ignore) { /* 回退 */ }
|
||||||
|
}
|
||||||
|
if (!set) {
|
||||||
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
net.setPreferableBackend(DNN_BACKEND_OPENCV);
|
||||||
net.setPreferableTarget(DNN_TARGET_CPU);
|
net.setPreferableTarget(DNN_TARGET_CPU);
|
||||||
|
|
||||||
System.out.println("模型加载成功: " + name + " (使用OpenCV后端)");
|
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new Exception("模型加载失败: " + e.getMessage() +
|
|
||||||
"\n请确保模型文件完整且格式正确", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 在目录中查找指定扩展名的模型文件
|
|
||||||
*/
|
|
||||||
private String findModelFile(Path dir, String extension) {
|
|
||||||
try {
|
|
||||||
return Files.list(dir)
|
|
||||||
.filter(path -> path.toString().toLowerCase().endsWith(extension.toLowerCase()))
|
|
||||||
.map(Path::toString)
|
|
||||||
.findFirst()
|
|
||||||
.orElse(null);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user