同步算法修改

This commit is contained in:
zqc
2026-02-26 15:56:12 +08:00
parent 36cc5949d3
commit b59aec5f7f

View File

@@ -79,7 +79,7 @@ class KadianDetector:
# 1. 业务判定时间阈值 # 1. 业务判定时间阈值
self.TIME_THRESHOLD_ONLY_ONE = 3.0 # 单人单检判定时长 self.TIME_THRESHOLD_ONLY_ONE = 3.0 # 单人单检判定时长
self.TIME_THRESHOLD_NOBODY = 2.0 # 无人检查判定时长 self.TIME_THRESHOLD_NOBODY = 3.0 # 无人检查判定时长
# 后备箱检查判定阈值 # 后备箱检查判定阈值
self.TIME_THRESHOLD_TRUNK_OPEN = 0.5 self.TIME_THRESHOLD_TRUNK_OPEN = 0.5
@@ -129,6 +129,15 @@ class KadianDetector:
logger.info(f" 制服合规恢复缓冲帧数: {self.frame_buffer_uniform}") logger.info(f" 制服合规恢复缓冲帧数: {self.frame_buffer_uniform}")
logger.info(f" 判定 'Too Fast' (视为Nobody) 最小停留: {self.frame_thresh_car_min_duration}") logger.info(f" 判定 'Too Fast' (视为Nobody) 最小停留: {self.frame_thresh_car_min_duration}")
self.onlyone_counter = 0
self.onlyone_lost_counter = 0
self.onlyone_buffer_limit = self.frame_buffer_limit_person # 10帧1秒
self.onlyone_thresh = self.frame_thresh_one # 30帧3秒
self.nobody_counter = 0
self.nobody_present_counter = 0
self.nobody_buffer_limit = 10 # 10帧1秒
self.nobody_thresh = self.frame_thresh_nobody # 20帧2秒
self.current_frame_idx = 0 self.current_frame_idx = 0
self.cnt_frame_one_person = 0 self.cnt_frame_one_person = 0
@@ -161,21 +170,14 @@ class KadianDetector:
用于 pointPolygonTest 和 polylines 用于 pointPolygonTest 和 polylines
""" """
if self.roi_points is None: if self.roi_points is None:
# 使用默认相对坐标 raise ValueError("ROI points must be provided; cannot be None.")
default_rel = np.array([
[0.15, 0.01], if self.roi_points.max() <= 1.0:
[0.45, 0.01], # 相对坐标 → 转换为绝对
[0.95, 0.95], roi_abs = self.roi_points * np.array([frame_width, frame_height])
[0.35, 0.95]
], dtype=np.float64)
roi_abs = default_rel * np.array([frame_width, frame_height])
else: else:
if self.roi_points.max() <= 1.0: # 绝对坐标,直接使用
# 相对坐标 → 转换为绝对 roi_abs = self.roi_points.copy()
roi_abs = self.roi_points * np.array([frame_width, frame_height])
else:
# 绝对坐标,直接使用
roi_abs = self.roi_points.copy()
# 强制转为 int32关键解决 OpenCV 断言错误) # 强制转为 int32关键解决 OpenCV 断言错误)
return roi_abs.astype(np.int32) return roi_abs.astype(np.int32)
@@ -529,34 +531,87 @@ class KadianDetector:
# ========================================== # ==========================================
# 9. 业务逻辑判定 (Only One / Nobody) # 9. 业务逻辑判定 (Only One / Nobody)
# ========================================== # ==========================================
status_text = "" # status_text = ""
#
# if effective_car_count > 0:
# # --- Only One ---
# if current_roi_person_count == 1:
# self.cnt_frame_one_person += 1
# self.cnt_missing_buffer_person = 0
# self.cnt_frame_nobody = 0
#
# # --- Nobody ---
# elif current_roi_person_count == 0:
# if self.cnt_frame_one_person > 0 and self.cnt_missing_buffer_person < self.frame_buffer_limit_person:
# self.cnt_frame_one_person += 1
# self.cnt_missing_buffer_person += 1
# self.cnt_frame_nobody = 0
# status_text = f"Person Buffer ({self.cnt_missing_buffer_person}/{self.frame_buffer_limit_person})"
# else:
# self.cnt_frame_one_person = 0
# self.cnt_missing_buffer_person = 0
# self.cnt_frame_nobody += 1
# else:
# self.cnt_frame_one_person = 0
# self.cnt_missing_buffer_person = 0
# self.cnt_frame_nobody = 0
# else:
# self.cnt_frame_one_person = 0
# self.cnt_missing_buffer_person = 0
# self.cnt_frame_nobody = 0
if effective_car_count > 0: # ==========================================
# --- Only One --- # 9. 业务逻辑判定 (Only One / Nobody) - 重构版
if current_roi_person_count == 1: # ==========================================
self.cnt_frame_one_person += 1 if effective_car_count >= 0: # 只要没人就检测,不用等到来了车再检测
self.cnt_missing_buffer_person = 0 # ----- 定义条件 -----
self.cnt_frame_nobody = 0 onlyone_condition = (current_roi_person_count == 1 and self.pose_person_count == 1)
nobody_condition = (current_roi_person_count == 0 and self.pose_person_count == 0)
# --- Nobody --- # ----- Onlyone 计数器更新 -----
elif current_roi_person_count == 0: if onlyone_condition:
if self.cnt_frame_one_person > 0 and self.cnt_missing_buffer_person < self.frame_buffer_limit_person: self.onlyone_counter += 1
self.cnt_frame_one_person += 1 self.onlyone_lost_counter = 0
self.cnt_missing_buffer_person += 1
self.cnt_frame_nobody = 0
status_text = f"Person Buffer ({self.cnt_missing_buffer_person}/{self.frame_buffer_limit_person})"
else:
self.cnt_frame_one_person = 0
self.cnt_missing_buffer_person = 0
self.cnt_frame_nobody += 1
else: else:
self.cnt_frame_one_person = 0 if self.onlyone_counter > 0:
self.cnt_missing_buffer_person = 0 self.onlyone_lost_counter += 1
self.cnt_frame_nobody = 0 if self.onlyone_lost_counter > self.onlyone_buffer_limit:
self.onlyone_counter = 0
self.onlyone_lost_counter = 0
# 没有累积的 Onlyone 则不做任何事
# ----- Nobody 计数器更新 -----
if nobody_condition:
self.nobody_counter += 1
self.nobody_present_counter = 0
else:
if self.nobody_counter > 0:
self.nobody_present_counter += 1
if self.nobody_present_counter > self.nobody_buffer_limit:
self.nobody_counter = 0
self.nobody_present_counter = 0
# 没有累积的 Nobody 则不做任何事
# ----- 准备显示状态文字(可选)-----
if self.onlyone_counter > 0:
if onlyone_condition:
status_text = f"OnlyOne: {self.onlyone_counter}/{self.onlyone_thresh}"
else:
status_text = f"OnlyOne Lost: {self.onlyone_lost_counter}/{self.onlyone_buffer_limit}"
elif self.nobody_counter > 0:
if nobody_condition:
status_text = f"Nobody: {self.nobody_counter}/{self.nobody_thresh}"
else:
status_text = f"Nobody Interrupted: {self.nobody_present_counter}/{self.nobody_buffer_limit}"
else:
status_text = ""
else: else:
self.cnt_frame_one_person = 0 # 无活跃车辆,清零所有计数器
self.cnt_missing_buffer_person = 0 self.onlyone_counter = 0
self.cnt_frame_nobody = 0 self.onlyone_lost_counter = 0
self.nobody_counter = 0
self.nobody_present_counter = 0
# ========================================== # ==========================================
# 10. 显示报警 (UI分层优化) # 10. 显示报警 (UI分层优化)
@@ -581,25 +636,37 @@ class KadianDetector:
# 第一层:实时状态 (Real-time Status) # 第一层:实时状态 (Real-time Status)
# ------------------------------------------------ # ------------------------------------------------
# A. 显示 Only One # A. 显示 Only One
if self.cnt_frame_one_person >= self.frame_thresh_one: # if self.cnt_frame_one_person >= self.frame_thresh_one:
current_frame_alerts.append( # current_frame_alerts.append(
{ # {
'time': current_time_sec, # 'time': current_time_sec,
'action': "Only One", # 'action': "Only One",
} # }
) # )
self.draw_alert(frame, "Only One", (0, 255, 255), status_text, offset_y=alert_offset) # self.draw_alert(frame, "Only One", (0, 255, 255), status_text, offset_y=alert_offset)
# alert_offset += 100
#
# # B. 显示 Nobody (实时状态)
# elif self.cnt_frame_nobody >= self.frame_thresh_nobody:
# current_frame_alerts.append(
# {
# 'time': current_time_sec,
# 'action': "Nobody",
# }
# )
# self.draw_alert(frame, "Nobody", (0, 0, 255), offset_y=alert_offset)
# alert_offset += 100
# A. 显示 Only One当累积帧数达到阈值时
if self.onlyone_counter >= self.onlyone_thresh:
current_frame_alerts.append({'time': current_time_sec, 'action': "Only One"})
self.draw_alert(frame, "Only One", (0, 255, 255), None, offset_y=alert_offset)
alert_offset += 100 alert_offset += 100
# B. 显示 Nobody (实时状态) # B. 显示 Nobody(当累积帧数达到阈值时)
elif self.cnt_frame_nobody >= self.frame_thresh_nobody: elif self.nobody_counter >= self.nobody_thresh:
current_frame_alerts.append( current_frame_alerts.append({'time': current_time_sec, 'action': "Nobody"})
{ self.draw_alert(frame, "Nobody", (0, 0, 255), None, offset_y=alert_offset)
'time': current_time_sec,
'action': "Nobody",
}
)
self.draw_alert(frame, "Nobody", (0, 0, 255), offset_y=alert_offset)
alert_offset += 100 alert_offset += 100
# C. 显示 Trunk Checked (在车辆存活期间) # C. 显示 Trunk Checked (在车辆存活期间)
@@ -619,28 +686,28 @@ class KadianDetector:
if self.phone_alert_active: if self.phone_alert_active:
# 可以显示检测的持续时间 # 可以显示检测的持续时间
duration_seconds = self.phone_detection_frames / self.fps duration_seconds = self.phone_detection_frames / self.fps
sub_text = f"Detected for {duration_seconds:.1f}s" #sub_text = f"Detected for {duration_seconds:.1f}s"
current_frame_alerts.append( current_frame_alerts.append(
{ {
'time': current_time_sec, 'time': current_time_sec,
'action': "Playing Phone", 'action': "Playing Phone",
} }
) )
self.draw_alert(frame, "Playing Phone", (255, 0, 0), sub_text, offset_y=alert_offset) self.draw_alert(frame, "Playing Phone", (255, 0, 0), None, offset_y=alert_offset)
alert_offset += 100 alert_offset += 100
# E. 新增:显示 Unvaild Uniform!! # E. 新增:显示 Unvaild Uniform!!
if self.uniform_alert_active: if self.uniform_alert_active:
# 显示具体数量差异 # 显示具体数量差异
diff = self.pose_person_count - current_roi_person_count diff = self.pose_person_count - current_roi_person_count
sub_text = f"Missing {diff} uniform(s)" #sub_text = f"Missing {diff} uniform(s)"
current_frame_alerts.append( current_frame_alerts.append(
{ {
'time': current_time_sec, 'time': current_time_sec,
'action': "Unvaild Uniform!!", 'action': "Unvaild Uniform!!",
} }
) )
self.draw_alert(frame, "Unvaild Uniform!!", (255, 165, 0), sub_text, offset_y=alert_offset) self.draw_alert(frame, "Unvaild Uniform!!", (255, 165, 0), None, offset_y=alert_offset)
alert_offset += 100 alert_offset += 100
# 第二层:离场违规 (Post-Event Alerts) # 第二层:离场违规 (Post-Event Alerts)
@@ -663,18 +730,18 @@ class KadianDetector:
self.draw_alert(frame, alert_text, (0, 0, 255), offset_y=alert_offset) self.draw_alert(frame, alert_text, (0, 0, 255), offset_y=alert_offset)
alert_offset += 100 alert_offset += 100
# G. 显示 Nobody (离场结果) # G. 显示 Ignore (离场结果)
expired_fast_alerts = [cid for cid, end_frame in self.fast_pass_alerts.items() if expired_fast_alerts = [cid for cid, end_frame in self.fast_pass_alerts.items() if
self.current_frame_idx > end_frame] self.current_frame_idx > end_frame]
for cid in expired_fast_alerts: for cid in expired_fast_alerts:
del self.fast_pass_alerts[cid] del self.fast_pass_alerts[cid]
if len(self.fast_pass_alerts) > 0: if len(self.fast_pass_alerts) > 0:
alert_text = f"Nobody (ID:{list(self.fast_pass_alerts.keys())})" alert_text = f"Ignore: (ID:{list(self.fast_pass_alerts.keys())})"
current_frame_alerts.append( current_frame_alerts.append(
{ {
'time': current_time_sec, 'time': current_time_sec,
'action': "Nobody", 'action': "Ignore",
} }
) )
self.draw_alert(frame, alert_text, (0, 0, 255), offset_y=alert_offset) self.draw_alert(frame, alert_text, (0, 0, 255), offset_y=alert_offset)