宠物异常行为预警系统:边缘计算与实时检测
摘要:本文深入讲解宠物异常行为预警系统的设计,涵盖边缘计算架构、实时检测算法、多级告警机制、推送通知等完整技术方案。
一、异常行为分类体系
1.1 异常行为分级
| 级别 | 类型 | 描述 | 响应时间 | 推送方式 |
|---|---|---|---|---|
| P0-紧急 | 生命威胁 | 抽搐、窒息、严重外伤 | 即时 | 电话+短信+APP |
| P1-严重 | 健康异常 | 呕吐、腹泻、拒食>24h | 5分钟 | 短信+APP |
| P2-警告 | 行为异常 | 过度舔舐、异常叫声 | 15分钟 | APP推送 |
| P3-提示 | 生活异常 | 饮水过多、活动量下降 | 1小时 | APP通知 |
1.2 异常行为特征库
python
ANOMALY_FEATURES = {
"vomiting": {
"level": "P1",
"sensors": ["camera", "imu"],
"description": "呕吐行为",
"indicators": {
"body_motion": "repeated_contraction",
"posture": "head_low_neck_extended",
"duration_min": 5, # 秒
"repetition": 2
}
},
"seizure": {
"level": "P0",
"sensors": ["imu", "heart_rate"],
"description": "抽搐/癫痫发作",
"indicators": {
"imu_pattern": "high_freq_involuntary",
"heart_rate": "elevated_irregular",
"duration_min": 10,
"movement_intensity": ">5g"
}
},
"excessive_licking": {
"level": "P2",
"sensors": ["camera", "imu"],
"description": "过度舔舐(可能皮肤问题)",
"indicators": {
"body_part": "same_area_repeated",
"frequency": ">10_times_per_hour",
"duration_total": ">30_min_per_day"
}
},
"lethargy": {
"level": "P1",
"sensors": ["imu", "activity"],
"description": "嗜睡/无精打采",
"indicators": {
"activity_level": "<30%_of_baseline",
"sleep_duration": ">18_hours",
"response_to_stimuli": "delayed_or_none"
}
},
"loss_of_appetite": {
"level": "P1",
"sensors": ["feeder", "camera"],
"description": "食欲不振",
"indicators": {
"food_consumed": "<50%_of_normal",
"duration": ">24_hours",
"water_intake": "normal_or_decreased"
}
},
"pacing": {
"level": "P2",
"sensors": ["camera", "imu"],
"description": "踱步/不安",
"indicators": {
"pattern": "repetitive_path",
"duration": ">30_minutes",
"time_of_day": "any"
}
},
"hiding": {
"level": "P2",
"sensors": ["camera", "location"],
"description": "躲藏(可能生病或恐惧)",
"indicators": {
"location": "unusual_hiding_spot",
"duration": ">2_hours",
"social_avoidance": True
}
}
}
二、边缘计算架构
2.1 边缘推理框架
┌─────────────────────────────────────────────────┐
│ 边缘设备 (Jetson/RK3588) │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 视频流 │ │ 传感器流 │ │ 音频流 │ │
│ │ 接收 │ │ 接收 │ │ 接收 │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ 特征提取层 │ │
│ │ 视觉特征 │ 运动特征 │ 声音特征 │ │
│ └─────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ 行为识别模型 │ │
│ │ YOLOv8 + LSTM + Transformer │ │
│ └─────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ 异常检测引擎 │ │
│ │ 规则引擎 + 异常检测模型 │ │
│ └─────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────┐ │
│ │ 告警决策层 │ │
│ │ 告警聚合 │ 去重 │ 升级 │ 推送 │ │
│ └─────────────────────────────────────────┘ │
└─────────────────────────────────────────────────┘
2.2 多线程流水线
python
import threading
import queue
from dataclasses import dataclass
from typing import Optional
import time
@dataclass
class DetectionResult:
timestamp: float
behavior: str
confidence: float
level: str
source: str
metadata: dict
class EdgeAnomalyDetector:
def __init__(self):
self.video_queue = queue.Queue(maxsize=30)
self.sensor_queue = queue.Queue(maxsize=100)
self.audio_queue = queue.Queue(maxsize=30)
self.result_queue = queue.Queue(maxsize=50)
self.alert_queue = queue.Queue(maxsize=20)
# 加载模型
self.yolo_model = self.load_yolo_model()
self.lstm_model = self.load_lstm_model()
self.anomaly_model = self.load_anomaly_model()
# 状态管理
self.behavior_buffer = []
self.alert_history = {}
def start(self):
"""启动所有处理线程"""
threads = [
threading.Thread(target=self.video_process_loop, daemon=True),
threading.Thread(target=self.sensor_process_loop, daemon=True),
threading.Thread(target=self.audio_process_loop, daemon=True),
threading.Thread(target=self.fusion_loop, daemon=True),
threading.Thread(target=self.alert_loop, daemon=True),
]
for t in threads:
t.start()
def video_process_loop(self):
"""视频处理线程"""
frame_buffer = []
while True:
frame = self.video_queue.get()
# YOLO检测
detections = self.yolo_model.detect(frame)
# 提取视觉特征
features = self.extract_visual_features(detections)
frame_buffer.append(features)
# 保持最近30帧
if len(frame_buffer) > 30:
frame_buffer.pop(0)
# LSTM时序分析
if len(frame_buffer) >= 16:
behavior = self.lstm_model.predict(frame_buffer[-16:])
self.result_queue.put(DetectionResult(
timestamp=time.time(),
behavior=behavior['type'],
confidence=behavior['confidence'],
level=behavior.get('level', 'P3'),
source='video',
metadata={'bbox': detections}
))
def sensor_process_loop(self):
"""传感器处理线程"""
while True:
data = self.sensor_queue.get()
# 提取运动特征
activity = self.classify_activity(data['imu'])
# 心率异常检测
hr_anomaly = self.detect_hr_anomaly(data['heart_rate'])
# 温度异常检测
temp_anomaly = self.detect_temp_anomaly(data['temperature'])
if hr_anomaly or temp_anomaly:
self.result_queue.put(DetectionResult(
timestamp=time.time(),
behavior='health_anomaly',
confidence=0.8,
level='P1',
source='sensor',
metadata={
'heart_rate': data['heart_rate'],
'temperature': data['temperature'],
'activity': activity
}
))
def fusion_loop(self):
"""多模态融合线程"""
results_buffer = []
while True:
result = self.result_queue.get()
results_buffer.append(result)
# 保持最近100个结果
if len(results_buffer) > 100:
results_buffer.pop(0)
# 异常检测
anomaly = self.anomaly_model.detect(results_buffer)
if anomaly['is_anomaly']:
# 告警聚合(避免重复告警)
alert_key = f"{anomaly['type']}_{anomaly.get('source', 'unknown')}"
if self.should_alert(alert_key):
self.alert_queue.put({
'type': anomaly['type'],
'level': anomaly['level'],
'confidence': anomaly['confidence'],
'timestamp': time.time(),
'details': anomaly['details']
})
def alert_loop(self):
"""告警处理线程"""
while True:
alert = self.alert_queue.get()
# 根据级别选择推送方式
if alert['level'] == 'P0':
self.send_phone_call(alert)
self.send_sms(alert)
self.send_app_push(alert)
elif alert['level'] == 'P1':
self.send_sms(alert)
self.send_app_push(alert)
elif alert['level'] == 'P2':
self.send_app_push(alert)
else:
self.store_notification(alert)
# 记录告警历史
self.alert_history[alert['type']] = time.time()
def should_alert(self, alert_key: str, cooldown: int = 300) -> bool:
"""告警去重:同一类型告警冷却期"""
last_alert = self.alert_history.get(alert_key, 0)
return time.time() - last_alert > cooldown
三、实时行为检测算法
3.1 视觉行为检测
python
import cv2
import numpy as np
from ultralytics import YOLO
class VisualBehaviorDetector:
def __init__(self, model_path):
self.model = YOLO(model_path)
self.behavior_classes = [
'sleeping', 'eating', 'drinking', 'playing',
'grooming', 'walking', 'sitting', 'standing',
'vomiting', 'seizure', 'pacing', 'hiding'
]
def detect_frame(self, frame):
"""单帧检测"""
results = self.model(frame, verbose=False)
detections = []
for r in results:
for box in r.boxes:
cls = int(box.cls[0])
conf = float(bo