feat: 新增人员徘徊/静止行为分析功能
本次提交实现了完整的人员行为分析系统,包括: 1. 新增基于位置和跟踪ID的两种行为检测算法 2. 新增徘徊检测服务与行为处理器模块 3. 前后端集成算法配置界面与告警展示 4. 支持图片和视频流场景下的行为分析 5. 新增算法配置接口与文档说明 具体改动: - 新增loitering_detection模型目录与算法实现 - 新增AlgorithmConfig组件实现可视化配置 - 扩展图片/视频检测接口支持算法参数传递 - 新增行为告警推送与前端展示页面 - 优化检测服务,集成行为分析逻辑 - 移除冗余日志输出,完善代码注释
This commit is contained in:
@@ -93,6 +93,13 @@
|
||||
<div class="slider-value">{{ config.iou.toFixed(2) }}</div>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 算法配置(仅对人员检测模型显示) -->
|
||||
<AlgorithmConfig
|
||||
v-model="config.algorithmConfig"
|
||||
@change="onAlgorithmChange"
|
||||
:model-id="config.model"
|
||||
/>
|
||||
|
||||
</el-form>
|
||||
</el-card>
|
||||
</div>
|
||||
@@ -225,6 +232,7 @@ import {
|
||||
QuestionFilled
|
||||
} from '@element-plus/icons-vue'
|
||||
import { detectionApi } from '@/api/detection'
|
||||
import AlgorithmConfig from './AlgorithmConfig.vue'
|
||||
|
||||
const props = defineProps({
|
||||
models: {
|
||||
@@ -236,7 +244,8 @@ const props = defineProps({
|
||||
const config = ref({
|
||||
model: props.models.length > 0 ? props.models[0].id : 'fire_detection',
|
||||
confidence: 0.5,
|
||||
iou: 0.45
|
||||
iou: 0.45,
|
||||
algorithmConfig: {}
|
||||
})
|
||||
|
||||
// 可拖拽调整宽度相关
|
||||
@@ -271,7 +280,20 @@ const originalImage = ref('')
|
||||
const resultImage = ref('')
|
||||
const detections = ref([])
|
||||
const stats = ref(null)
|
||||
const uploadUrl = computed(() => `/api/detect/image?model_id=${config.value.model}&confidence=${config.value.confidence}&iou=${config.value.iou}`)
|
||||
const uploadUrl = computed(() => {
|
||||
const params = new URLSearchParams({
|
||||
model_id: config.value.model,
|
||||
confidence: config.value.confidence,
|
||||
iou: config.value.iou
|
||||
})
|
||||
|
||||
// 添加算法配置
|
||||
if (config.value.algorithmConfig && Object.keys(config.value.algorithmConfig).length > 0) {
|
||||
params.append('algorithm_config', JSON.stringify(config.value.algorithmConfig))
|
||||
}
|
||||
|
||||
return `/api/detect/image?${params.toString()}`
|
||||
})
|
||||
|
||||
const formatConfidence = (value) => {
|
||||
return `置信度: ${value.toFixed(2)}`
|
||||
@@ -303,6 +325,22 @@ const handleUploadSuccess = (response) => {
|
||||
}
|
||||
detections.value = response.data.detections || []
|
||||
stats.value = response.data.stats
|
||||
|
||||
// 处理告警信息
|
||||
if (response.data.alerts && response.data.alerts.length > 0) {
|
||||
alerts.value = response.data.alerts
|
||||
console.log('收到告警:', response.data.alerts)
|
||||
|
||||
// 显示告警通知
|
||||
response.data.alerts.forEach(alert => {
|
||||
ElMessage({
|
||||
message: `行为告警: ${alert.type} - ${alert.message}`,
|
||||
type: 'warning',
|
||||
duration: 3000
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
ElMessage.success('检测完成')
|
||||
} else {
|
||||
ElMessage.error(response.message)
|
||||
@@ -320,6 +358,10 @@ const modelName = computed(() => {
|
||||
const model = props.models.find(m => m.id === config.value.model)
|
||||
return model ? model.name : config.value.model
|
||||
})
|
||||
|
||||
const onAlgorithmChange = (algoConfig) => {
|
||||
config.value.algorithmConfig = algoConfig
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
@@ -624,6 +666,78 @@ const modelName = computed(() => {
|
||||
color: #409eff;
|
||||
}
|
||||
|
||||
/* 告警卡片 */
|
||||
.alerts-card {
|
||||
margin-bottom: 20px;
|
||||
border: 2px solid #f56c6c;
|
||||
}
|
||||
|
||||
.alerts-card .card-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.alert-count {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.alerts-container {
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.alert-item {
|
||||
background: #fef0f0;
|
||||
border-left: 4px solid #f56c6c;
|
||||
padding: 12px;
|
||||
border-radius: 4px;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.alert-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.alert-time {
|
||||
font-size: 12px;
|
||||
color: #909399;
|
||||
}
|
||||
|
||||
.alert-detail {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.alert-message {
|
||||
font-size: 14px;
|
||||
color: #f56c6c;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.alert-duration {
|
||||
font-size: 13px;
|
||||
color: #606266;
|
||||
background: #fff;
|
||||
padding: 2px 8px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.alert-bbox {
|
||||
font-size: 12px;
|
||||
color: #606266;
|
||||
background: #fff;
|
||||
padding: 4px 8px;
|
||||
border-radius: 4px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* 响应式布局 */
|
||||
@media (max-width: 768px) {
|
||||
.image-detection-container {
|
||||
|
||||
Reference in New Issue
Block a user