对frame增加try以接住异常
This commit is contained in:
@@ -12,6 +12,8 @@ from algorithm.checkpoint.npu_yolo_onnx_person_car_phone import YOLOv8_ONNX
|
|||||||
from algorithm.checkpoint.npu_yolo_pose_onnx import YOLOv8_Pose_ONNX # Pose 专用模型
|
from algorithm.checkpoint.npu_yolo_pose_onnx import YOLOv8_Pose_ONNX # Pose 专用模型
|
||||||
from yolox.tracker.byte_tracker import BYTETracker
|
from yolox.tracker.byte_tracker import BYTETracker
|
||||||
|
|
||||||
|
from utils.logger import get_logger
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
# ========================= 配置区 =========================
|
# ========================= 配置区 =========================
|
||||||
# Kadian 模型路径与ROI(可根据实际情况修改)
|
# Kadian 模型路径与ROI(可根据实际情况修改)
|
||||||
@@ -114,15 +116,15 @@ class KadianDetector:
|
|||||||
self.frame_buffer_limit_person = int(self.TIME_TOLERANCE_PERSON * self.fps)
|
self.frame_buffer_limit_person = int(self.TIME_TOLERANCE_PERSON * self.fps)
|
||||||
self.frame_buffer_limit_car = int(self.TIME_TOLERANCE_CAR * self.fps)
|
self.frame_buffer_limit_car = int(self.TIME_TOLERANCE_CAR * self.fps)
|
||||||
|
|
||||||
print(f"\n超参数设置:")
|
logger.info(f"\n超参数设置:")
|
||||||
print(f" FPS: {self.fps:.2f}")
|
logger.info(f" FPS: {self.fps:.2f}")
|
||||||
print(f" 判定 'Only One' / 'Nobody' 需连续: {self.frame_thresh_one} 帧")
|
logger.info(f" 判定 'Only One' / 'Nobody' 需连续: {self.frame_thresh_one} 帧")
|
||||||
print(f" 判定 'Trunk Checked' 需累计检测: {self.frame_thresh_trunk_valid} 帧")
|
logger.info(f" 判定 'Trunk Checked' 需累计检测: {self.frame_thresh_trunk_valid} 帧")
|
||||||
print(f" 判定 'Phone Detected' 需累计检测: {self.frame_thresh_phone} 帧")
|
logger.info(f" 判定 'Phone Detected' 需累计检测: {self.frame_thresh_phone} 帧")
|
||||||
print(f" 手机丢失缓冲帧数: {self.frame_buffer_phone} 帧")
|
logger.info(f" 手机丢失缓冲帧数: {self.frame_buffer_phone} 帧")
|
||||||
print(f" 判定 'Uniform Invalid' 需连续检测: {self.frame_thresh_uniform} 帧")
|
logger.info(f" 判定 'Uniform Invalid' 需连续检测: {self.frame_thresh_uniform} 帧")
|
||||||
print(f" 制服合规恢复缓冲帧数: {self.frame_buffer_uniform} 帧")
|
logger.info(f" 制服合规恢复缓冲帧数: {self.frame_buffer_uniform} 帧")
|
||||||
print(f" 判定 'Too Fast' (视为Nobody) 最小停留: {self.frame_thresh_car_min_duration} 帧")
|
logger.info(f" 判定 'Too Fast' (视为Nobody) 最小停留: {self.frame_thresh_car_min_duration} 帧")
|
||||||
|
|
||||||
|
|
||||||
self.current_frame_idx = 0
|
self.current_frame_idx = 0
|
||||||
@@ -260,7 +262,7 @@ class KadianDetector:
|
|||||||
|
|
||||||
elif cls_id == 3:
|
elif cls_id == 3:
|
||||||
dets_roles.append("phone")
|
dets_roles.append("phone")
|
||||||
# print(f'dets_roles: {dets_roles}')
|
# logger.debug(f'dets_roles: {dets_roles}')
|
||||||
|
|
||||||
dets = np.array(dets_for_tracker, dtype=np.float32) if len(dets_for_tracker) else np.empty((0, 5))
|
dets = np.array(dets_for_tracker, dtype=np.float32) if len(dets_for_tracker) else np.empty((0, 5))
|
||||||
|
|
||||||
@@ -269,7 +271,7 @@ class KadianDetector:
|
|||||||
[self.height, self.width],
|
[self.height, self.width],
|
||||||
[self.height, self.width]
|
[self.height, self.width]
|
||||||
)
|
)
|
||||||
# print("tracks: {}".format(tracks))
|
# logger.debug("tracks: {}".format(tracks))
|
||||||
# 绘制骨骼
|
# 绘制骨骼
|
||||||
frame = YOLOv8_Pose_ONNX.draw_keypoints(frame, pose_results)
|
frame = YOLOv8_Pose_ONNX.draw_keypoints(frame, pose_results)
|
||||||
# ========= 绘制 ROI =========
|
# ========= 绘制 ROI =========
|
||||||
@@ -285,7 +287,7 @@ class KadianDetector:
|
|||||||
current_trunks = [] # (cx, cy)
|
current_trunks = [] # (cx, cy)
|
||||||
|
|
||||||
for t in tracks:
|
for t in tracks:
|
||||||
# print("t: {}".format(t))
|
# logger.debug("t: {}".format(t))
|
||||||
tid = t.track_id
|
tid = t.track_id
|
||||||
# cls_id = -1
|
# cls_id = -1
|
||||||
|
|
||||||
@@ -319,7 +321,7 @@ class KadianDetector:
|
|||||||
cls_id = 2
|
cls_id = 2
|
||||||
elif role == "phone":
|
elif role == "phone":
|
||||||
cls_id = 3
|
cls_id = 3
|
||||||
# print("tid: {}, role: {}, cls: {}".format(tid, role,cls_id))
|
# logger.debug("tid: {}, role: {}, cls: {}".format(tid, role,cls_id))
|
||||||
|
|
||||||
x1, y1, x2, y2 = map(int, t.tlbr)
|
x1, y1, x2, y2 = map(int, t.tlbr)
|
||||||
|
|
||||||
@@ -498,12 +500,12 @@ class KadianDetector:
|
|||||||
|
|
||||||
# 情况1:通过时间太短 -> 归类为 Nobody (Too Fast)
|
# 情况1:通过时间太短 -> 归类为 Nobody (Too Fast)
|
||||||
if duration_frames < self.frame_thresh_car_min_duration:
|
if duration_frames < self.frame_thresh_car_min_duration:
|
||||||
print(f"ALARM: Car {car_id} passed too fast -> Regarded as Nobody Checked!")
|
logger.warning(f"ALARM: Car {car_id} passed too fast -> Regarded as Nobody Checked!")
|
||||||
self.fast_pass_alerts[car_id] = self.current_frame_idx + int(3.0 * self.fps)
|
self.fast_pass_alerts[car_id] = self.current_frame_idx + int(3.0 * self.fps)
|
||||||
|
|
||||||
# 情况2:时间够长,但没检查后备箱 -> Unchecked Trunk
|
# 情况2:时间够长,但没检查后备箱 -> Unchecked Trunk
|
||||||
elif not car_info['is_checked']:
|
elif not car_info['is_checked']:
|
||||||
print(f"ALARM: Car {car_id} left without checking trunk!")
|
logger.warning(f"ALARM: Car {car_id} left without checking trunk!")
|
||||||
self.unchecked_trunk_alerts[car_id] = self.current_frame_idx + int(3.0 * self.fps)
|
self.unchecked_trunk_alerts[car_id] = self.current_frame_idx + int(3.0 * self.fps)
|
||||||
|
|
||||||
del self.roi_car_registry[car_id]
|
del self.roi_car_registry[car_id]
|
||||||
@@ -698,69 +700,75 @@ class FrameProcessorWorker(threading.Thread):
|
|||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
cam_id = item["camera_id"]
|
|
||||||
ts = item["timestamp"]
|
|
||||||
frame = item["frame"]
|
|
||||||
|
|
||||||
# 抽帧控制
|
|
||||||
if ts - self.last_ts.get(cam_id, 0) < target_interval:
|
|
||||||
self.raw_queue.task_done()
|
|
||||||
continue
|
|
||||||
self.last_ts[cam_id] = ts
|
|
||||||
|
|
||||||
# 获取检测器实例
|
|
||||||
if cam_id not in self.kadian_detectors:
|
|
||||||
self.kadian_detectors[cam_id] = KadianDetector()
|
|
||||||
detector = self.kadian_detectors[cam_id]
|
|
||||||
|
|
||||||
# 执行检测
|
|
||||||
result = detector.process_frame(frame.copy(), cam_id, ts)
|
|
||||||
|
|
||||||
result_img = result["image"]
|
|
||||||
result_type = result["alerts"]
|
|
||||||
# print(f"alerts: {result_type}")
|
|
||||||
|
|
||||||
# ========= 核心修改:过滤5秒内重复的action =========
|
|
||||||
# 初始化当前摄像头的推送时间记录
|
|
||||||
if cam_id not in self.last_alert_push_time:
|
|
||||||
self.last_alert_push_time[cam_id] = {}
|
|
||||||
|
|
||||||
# 筛选出符合推送条件的action(5秒内未推送过)
|
|
||||||
push_actions = []
|
|
||||||
current_time = time.time()
|
|
||||||
for alert in result_type:
|
|
||||||
action = alert['action']
|
|
||||||
last_push = self.last_alert_push_time[cam_id].get(action, 0)
|
|
||||||
# 检查是否超过推送间隔
|
|
||||||
if current_time - last_push >= ALERT_PUSH_INTERVAL:
|
|
||||||
push_actions.append(action)
|
|
||||||
# 更新该action的最后推送时间
|
|
||||||
self.last_alert_push_time[cam_id][action] = current_time
|
|
||||||
|
|
||||||
# 通过 WebSocket 发送帧结果
|
|
||||||
try:
|
try:
|
||||||
img_b64 = self._encode_base64(result_img)
|
cam_id = item["camera_id"]
|
||||||
except Exception as e:
|
ts = item["timestamp"]
|
||||||
print(f"[ERROR] Encode image failed: {e}")
|
frame = item["frame"]
|
||||||
img_b64 = None
|
|
||||||
|
|
||||||
if img_b64 is not None:
|
# 抽帧控制
|
||||||
# 将abnormal_actions对象数组转换为字符串数组
|
if ts - self.last_ts.get(cam_id, 0) < target_interval:
|
||||||
# action_names = [action_info['action'] for action_info in push_actions]
|
self.raw_queue.task_done()
|
||||||
|
continue
|
||||||
|
self.last_ts[cam_id] = ts
|
||||||
|
|
||||||
msg = {
|
# 获取检测器实例
|
||||||
"msg_type": "frame",
|
if cam_id not in self.kadian_detectors:
|
||||||
"camera_id": 0,
|
self.kadian_detectors[cam_id] = KadianDetector()
|
||||||
"timestamp": ts,
|
detector = self.kadian_detectors[cam_id]
|
||||||
# "result_type": action_names,
|
|
||||||
"result_type": push_actions,
|
# 执行检测
|
||||||
"image_base64": img_b64,
|
result = detector.process_frame(frame.copy(), cam_id, ts)
|
||||||
}
|
|
||||||
|
result_img = result["image"]
|
||||||
|
result_type = result["alerts"]
|
||||||
|
# logger.debug(f"alerts: {result_type}")
|
||||||
|
|
||||||
|
# ========= 核心修改:过滤5秒内重复的action =========
|
||||||
|
# 初始化当前摄像头的推送时间记录
|
||||||
|
if cam_id not in self.last_alert_push_time:
|
||||||
|
self.last_alert_push_time[cam_id] = {}
|
||||||
|
|
||||||
|
# 筛选出符合推送条件的action(5秒内未推送过)
|
||||||
|
push_actions = []
|
||||||
|
current_time = time.time()
|
||||||
|
for alert in result_type:
|
||||||
|
action = alert['action']
|
||||||
|
last_push = self.last_alert_push_time[cam_id].get(action, 0)
|
||||||
|
# 检查是否超过推送间隔
|
||||||
|
if current_time - last_push >= ALERT_PUSH_INTERVAL:
|
||||||
|
push_actions.append(action)
|
||||||
|
# 更新该action的最后推送时间
|
||||||
|
self.last_alert_push_time[cam_id][action] = current_time
|
||||||
|
|
||||||
|
# 通过 WebSocket 发送帧结果
|
||||||
try:
|
try:
|
||||||
self.ws_queue.put(msg, timeout=1.0)
|
img_b64 = self._encode_base64(result_img)
|
||||||
# if push_actions and len(push_actions) > 0:
|
except Exception as e:
|
||||||
# self.ws_queue_2.put(msg, timeout=1.0)
|
logger.error(f"[ERROR] Encode image failed: {e}")
|
||||||
except queue.Full:
|
img_b64 = None
|
||||||
print("[WARN] ws_send_queue full, drop frame message")
|
|
||||||
|
|
||||||
self.raw_queue.task_done()
|
if img_b64 is not None:
|
||||||
|
# 将abnormal_actions对象数组转换为字符串数组
|
||||||
|
# action_names = [action_info['action'] for action_info in push_actions]
|
||||||
|
|
||||||
|
msg = {
|
||||||
|
"msg_type": "frame",
|
||||||
|
"camera_id": 0,
|
||||||
|
"timestamp": ts,
|
||||||
|
# "result_type": action_names,
|
||||||
|
"result_type": push_actions,
|
||||||
|
"image_base64": img_b64,
|
||||||
|
}
|
||||||
|
try:
|
||||||
|
self.ws_queue.put(msg, timeout=1.0)
|
||||||
|
# if push_actions and len(push_actions) > 0:
|
||||||
|
# self.ws_queue_2.put(msg, timeout=1.0)
|
||||||
|
except queue.Full:
|
||||||
|
logger.warning("[WARN] ws_send_queue full, drop frame message")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"[ERROR] Frame processing failed for camera {cam_id if 'cam_id' in locals() else 'unknown'}: {e}")
|
||||||
|
logger.exception("Exception details:") # 打印完整的堆栈跟踪
|
||||||
|
# 继续处理下一帧,不要退出循环
|
||||||
|
finally:
|
||||||
|
self.raw_queue.task_done()
|
||||||
|
|||||||
Reference in New Issue
Block a user