Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 736b0a05d5 | |||
| 33e272cbc7 | |||
| f8b4b65ced | |||
| caa7adb27c |
@@ -34,6 +34,7 @@ class AlarmType(str, Enum):
|
|||||||
INTRUSION = "intrusion"
|
INTRUSION = "intrusion"
|
||||||
ILLEGAL_PARKING = "illegal_parking"
|
ILLEGAL_PARKING = "illegal_parking"
|
||||||
VEHICLE_CONGESTION = "vehicle_congestion"
|
VEHICLE_CONGESTION = "vehicle_congestion"
|
||||||
|
NON_MOTOR_VEHICLE_PARKING = "non_motor_vehicle_parking"
|
||||||
|
|
||||||
|
|
||||||
ALARM_TYPE_NAMES: Dict[str, str] = {
|
ALARM_TYPE_NAMES: Dict[str, str] = {
|
||||||
@@ -41,6 +42,7 @@ ALARM_TYPE_NAMES: Dict[str, str] = {
|
|||||||
AlarmType.INTRUSION: "周界入侵",
|
AlarmType.INTRUSION: "周界入侵",
|
||||||
AlarmType.ILLEGAL_PARKING: "车辆违停",
|
AlarmType.ILLEGAL_PARKING: "车辆违停",
|
||||||
AlarmType.VEHICLE_CONGESTION: "车辆拥堵",
|
AlarmType.VEHICLE_CONGESTION: "车辆拥堵",
|
||||||
|
AlarmType.NON_MOTOR_VEHICLE_PARKING: "非机动车违停",
|
||||||
}
|
}
|
||||||
|
|
||||||
# VLM 场景下的简短名称(用于截图分析提示词,尽量精炼)
|
# VLM 场景下的简短名称(用于截图分析提示词,尽量精炼)
|
||||||
@@ -49,6 +51,7 @@ ALARM_TYPE_SHORT_NAMES: Dict[str, str] = {
|
|||||||
AlarmType.INTRUSION: "入侵",
|
AlarmType.INTRUSION: "入侵",
|
||||||
AlarmType.ILLEGAL_PARKING: "违停",
|
AlarmType.ILLEGAL_PARKING: "违停",
|
||||||
AlarmType.VEHICLE_CONGESTION: "拥堵",
|
AlarmType.VEHICLE_CONGESTION: "拥堵",
|
||||||
|
AlarmType.NON_MOTOR_VEHICLE_PARKING: "非机动车违停",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -147,8 +150,9 @@ ALARM_LEVEL_NAMES: Dict[int, str] = {
|
|||||||
ALARM_TYPE_DEFAULT_LEVEL: Dict[str, int] = {
|
ALARM_TYPE_DEFAULT_LEVEL: Dict[str, int] = {
|
||||||
AlarmType.INTRUSION: 1, # 重要
|
AlarmType.INTRUSION: 1, # 重要
|
||||||
AlarmType.LEAVE_POST: 2, # 普通
|
AlarmType.LEAVE_POST: 2, # 普通
|
||||||
AlarmType.ILLEGAL_PARKING: 2, # 普通
|
AlarmType.ILLEGAL_PARKING: 1, # 重要(与 edge 端一致)
|
||||||
AlarmType.VEHICLE_CONGESTION: 2, # 普通
|
AlarmType.VEHICLE_CONGESTION: 2, # 普通
|
||||||
|
AlarmType.NON_MOTOR_VEHICLE_PARKING: 2, # 普通
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -328,6 +328,18 @@ def _build_aiot_menus():
|
|||||||
"visible": True,
|
"visible": True,
|
||||||
"keepAlive": True,
|
"keepAlive": True,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"id": 2030,
|
||||||
|
"parentId": 2000,
|
||||||
|
"name": "算法全局参数",
|
||||||
|
"path": "device/algorithm",
|
||||||
|
"component": "aiot/device/algorithm/index",
|
||||||
|
"componentName": "AiotDeviceAlgorithm",
|
||||||
|
"icon": "ep:setting",
|
||||||
|
"sort": 5,
|
||||||
|
"visible": True,
|
||||||
|
"keepAlive": True,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"id": 2040,
|
"id": 2040,
|
||||||
"parentId": 2000,
|
"parentId": 2000,
|
||||||
|
|||||||
@@ -193,11 +193,11 @@ async def _build_daily_report_data() -> Optional[Dict]:
|
|||||||
false_alarm_count += 1
|
false_alarm_count += 1
|
||||||
if sec_ext.dispatched_time and sec_ext.confirmed_time:
|
if sec_ext.dispatched_time and sec_ext.confirmed_time:
|
||||||
delta = (sec_ext.confirmed_time - sec_ext.dispatched_time).total_seconds() / 60.0
|
delta = (sec_ext.confirmed_time - sec_ext.dispatched_time).total_seconds() / 60.0
|
||||||
if 0 <= delta <= 360:
|
if 0 <= delta <= 60:
|
||||||
response_times.append(delta)
|
response_times.append(delta)
|
||||||
if sec_ext.dispatched_time and sec_ext.completed_time:
|
if sec_ext.dispatched_time and sec_ext.completed_time:
|
||||||
delta = (sec_ext.completed_time - sec_ext.dispatched_time).total_seconds() / 60.0
|
delta = (sec_ext.completed_time - sec_ext.dispatched_time).total_seconds() / 60.0
|
||||||
if 0 <= delta <= 24 * 60:
|
if 0 <= delta <= 6 * 60:
|
||||||
close_times.append(delta)
|
close_times.append(delta)
|
||||||
|
|
||||||
clean_ext = clean_ext_map.get(order.id)
|
clean_ext = clean_ext_map.get(order.id)
|
||||||
@@ -207,11 +207,11 @@ async def _build_daily_report_data() -> Optional[Dict]:
|
|||||||
dispatch_time = clean_ext.first_dispatched_time or clean_ext.dispatched_time
|
dispatch_time = clean_ext.first_dispatched_time or clean_ext.dispatched_time
|
||||||
if dispatch_time and clean_ext.arrived_time:
|
if dispatch_time and clean_ext.arrived_time:
|
||||||
delta = (clean_ext.arrived_time - dispatch_time).total_seconds() / 60.0
|
delta = (clean_ext.arrived_time - dispatch_time).total_seconds() / 60.0
|
||||||
if 0 <= delta <= 360:
|
if 0 <= delta <= 60:
|
||||||
response_times.append(delta)
|
response_times.append(delta)
|
||||||
if dispatch_time and clean_ext.completed_time:
|
if dispatch_time and clean_ext.completed_time:
|
||||||
delta = (clean_ext.completed_time - dispatch_time).total_seconds() / 60.0
|
delta = (clean_ext.completed_time - dispatch_time).total_seconds() / 60.0
|
||||||
if 0 <= delta <= 24 * 60:
|
if 0 <= delta <= 6 * 60:
|
||||||
close_times.append(delta)
|
close_times.append(delta)
|
||||||
|
|
||||||
camera_counter = Counter()
|
camera_counter = Counter()
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ VLM_TYPE_NAMES = {
|
|||||||
"intrusion": "周界入侵",
|
"intrusion": "周界入侵",
|
||||||
"illegal_parking": "车辆违停",
|
"illegal_parking": "车辆违停",
|
||||||
"vehicle_congestion": "车辆拥堵",
|
"vehicle_congestion": "车辆拥堵",
|
||||||
|
"non_motor_vehicle_parking": "非机动车违停",
|
||||||
}
|
}
|
||||||
|
|
||||||
# 算法类型 → VLM Prompt 模板
|
# 算法类型 → VLM Prompt 模板
|
||||||
@@ -58,6 +59,20 @@ description要求:≤15字,直接说结论,注明大致车辆数。
|
|||||||
告警成立示例:"约5辆车拥堵在路口"
|
告警成立示例:"约5辆车拥堵在路口"
|
||||||
误报示例:"车辆正常通行无拥堵"
|
误报示例:"车辆正常通行无拥堵"
|
||||||
仅输出JSON:{{"confirmed":true,"description":"..."}}""",
|
仅输出JSON:{{"confirmed":true,"description":"..."}}""",
|
||||||
|
|
||||||
|
"non_motor_vehicle_parking": """你是安防监控AI复核员。算法类型:非机动车违停检测,监控区域:{roi_name}。
|
||||||
|
任务:判断图中是否有非机动车(自行车、电动车、摩托车等)违规停放在禁停区域。
|
||||||
|
分析要点:
|
||||||
|
1. 是否存在非机动车(自行车、电动车、共享单车等)
|
||||||
|
2. 非机动车是否处于静止停放状态(而非骑行经过)
|
||||||
|
3. 是否在禁停区域/消防通道内
|
||||||
|
4. 停放是否造成通道阻塞
|
||||||
|
- confirmed=true:有非机动车违停(告警成立)
|
||||||
|
- confirmed=false:无非机动车违停(误报)
|
||||||
|
description要求:≤15字,直接说结论。
|
||||||
|
告警成立示例:"电动车违停在消防通道"
|
||||||
|
误报示例:"该区域无非机动车违停"
|
||||||
|
仅输出JSON:{{"confirmed":true,"description":"..."}}""",
|
||||||
}
|
}
|
||||||
|
|
||||||
# 通用降级 prompt(未知算法类型时使用)
|
# 通用降级 prompt(未知算法类型时使用)
|
||||||
@@ -172,13 +187,16 @@ class VLMService:
|
|||||||
content = content.strip()
|
content = content.strip()
|
||||||
|
|
||||||
result = json.loads(content)
|
result = json.loads(content)
|
||||||
|
# 兼容不同 prompt 返回格式(is_real/reason vs confirmed/description)
|
||||||
|
confirmed = result.get("confirmed") if "confirmed" in result else result.get("is_real", True)
|
||||||
|
description = result.get("description") or result.get("reason", "")
|
||||||
logger.info(
|
logger.info(
|
||||||
f"VLM 复核完成: confirmed={result.get('confirmed')}, "
|
f"VLM 复核完成: confirmed={confirmed}, "
|
||||||
f"desc={result.get('description', '')[:30]}"
|
f"desc={description[:30]}"
|
||||||
)
|
)
|
||||||
return {
|
return {
|
||||||
"confirmed": result.get("confirmed", True),
|
"confirmed": confirmed,
|
||||||
"description": result.get("description", ""),
|
"description": description,
|
||||||
"skipped": False,
|
"skipped": False,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user