perf: optimize video playback and detection interval
This commit is contained in:
parent
c6a2e4ada0
commit
54ed5e0682
@ -85,3 +85,14 @@ logging:
|
||||
|
||||
# 调试图像保存路径
|
||||
debug_image_path: "debug/"
|
||||
|
||||
# 性能保护配置
|
||||
performance:
|
||||
# 处理帧率上限(每秒最多处理多少帧),0 或 null 表示不限制
|
||||
max_processing_fps: 0
|
||||
|
||||
# 帧间隔,1 表示每帧处理,2 表示处理 1 帧跳过 1 帧
|
||||
frame_stride: 1
|
||||
|
||||
# 检测时间间隔(秒),0 表示每帧都检测
|
||||
detection_interval_seconds: 0.1 # 每秒检测10次
|
||||
|
||||
238
main.py
238
main.py
@ -77,6 +77,7 @@ class YantaiVisionXSystem:
|
||||
self.alarm_manager = AlarmManager(self.logger)
|
||||
self.tech_ui = TechUI()
|
||||
self.performance_limiter = PerformanceLimiter()
|
||||
self._detection_interval_seconds: float = 0.0
|
||||
|
||||
self._window_internal_name = "YantaiVisionX Monitor"
|
||||
self._window_display_name = "烟台蓬莱国际机场低能见度识别软件"
|
||||
@ -118,16 +119,24 @@ class YantaiVisionXSystem:
|
||||
|
||||
max_fps = performance_cfg.get("max_processing_fps")
|
||||
frame_stride = performance_cfg.get("frame_stride", 1)
|
||||
detection_interval = performance_cfg.get("detection_interval_seconds", 0)
|
||||
self.performance_limiter.update_settings(max_processing_fps=max_fps, frame_stride=frame_stride)
|
||||
try:
|
||||
detection_interval_value = float(detection_interval)
|
||||
except (TypeError, ValueError):
|
||||
detection_interval_value = 0.0
|
||||
self._detection_interval_seconds = detection_interval_value if detection_interval_value and detection_interval_value > 0 else 0.0
|
||||
self.logger.log_info(
|
||||
f"性能限制器配置: max_fps={self.performance_limiter.max_processing_fps}, "
|
||||
f"frame_stride={self.performance_limiter.frame_stride}"
|
||||
f"frame_stride={self.performance_limiter.frame_stride}, "
|
||||
f"detection_interval={self._detection_interval_seconds}s"
|
||||
)
|
||||
|
||||
def update_performance_settings(
|
||||
self,
|
||||
max_processing_fps: Optional[float] = None,
|
||||
frame_stride: Optional[int] = None,
|
||||
detection_interval_seconds: Optional[float] = None,
|
||||
) -> None:
|
||||
"""运行中动态调整性能限制参数"""
|
||||
|
||||
@ -135,6 +144,12 @@ class YantaiVisionXSystem:
|
||||
max_processing_fps=max_processing_fps,
|
||||
frame_stride=frame_stride,
|
||||
)
|
||||
if detection_interval_seconds is not None:
|
||||
try:
|
||||
value = float(detection_interval_seconds)
|
||||
except (TypeError, ValueError):
|
||||
value = 0.0
|
||||
self._detection_interval_seconds = value if value > 0 else 0.0
|
||||
|
||||
def initialize_system(self, camera_config=None) -> bool:
|
||||
"""
|
||||
@ -210,10 +225,24 @@ class YantaiVisionXSystem:
|
||||
self.logger.log_error("摄像头打开失败")
|
||||
return
|
||||
|
||||
self.logger.log_info("开始 LED 检测...")
|
||||
# 获取视频/摄像头帧率,用于控制播放速度
|
||||
video_fps = self.camera.get_fps()
|
||||
if video_fps <= 0:
|
||||
video_fps = 30.0
|
||||
frame_interval = 1.0 / video_fps # 每帧间隔(秒)
|
||||
|
||||
self.logger.log_info(f"开始 LED 检测... 帧率: {video_fps:.1f}fps")
|
||||
|
||||
limiter = self.performance_limiter
|
||||
frame_index = 0
|
||||
last_detection_result = None
|
||||
last_detection_time: Optional[float] = None
|
||||
display_frame_interval = 5 # 每5帧显示一次,降低UI绑定开销
|
||||
|
||||
# 性能统计
|
||||
loop_start = time.perf_counter()
|
||||
total_display_time = 0.0
|
||||
display_count = 0
|
||||
|
||||
try:
|
||||
while self.is_running:
|
||||
@ -225,45 +254,77 @@ class YantaiVisionXSystem:
|
||||
|
||||
current_frame_index = frame_index
|
||||
frame_index += 1
|
||||
current_time = time.perf_counter()
|
||||
|
||||
# 每100帧输出一次性能统计
|
||||
if frame_index % 100 == 0:
|
||||
elapsed = current_time - loop_start
|
||||
actual_fps = frame_index / elapsed if elapsed > 0 else 0
|
||||
avg_display = (total_display_time / display_count * 1000) if display_count > 0 else 0
|
||||
print(f"[性能] 帧:{frame_index} 实际FPS:{actual_fps:.1f} 显示次数:{display_count} 平均显示耗时:{avg_display:.1f}ms")
|
||||
|
||||
should_process = True
|
||||
if limiter and not limiter.should_process_frame(current_frame_index):
|
||||
continue
|
||||
|
||||
# 图像预处理
|
||||
enhanced_frame = self.image_enhancer.preprocess_frame(
|
||||
frame, mode="normal"
|
||||
)
|
||||
|
||||
# LED检测
|
||||
detection_result = self.led_detector.detect_leds(enhanced_frame)
|
||||
|
||||
# 记录结果
|
||||
self.logger.log_detection_result(detection_result)
|
||||
should_process = False
|
||||
if last_detection_result is None:
|
||||
should_process = True
|
||||
|
||||
alarm_result = self.alarm_manager.process_detection(detection_result)
|
||||
for event in alarm_result.events:
|
||||
self.logger.log_alarm_event(event)
|
||||
for roi_name in alarm_result.recoveries:
|
||||
self.logger.log_recovery_event(
|
||||
roi_name,
|
||||
detection_result.frame_count,
|
||||
detection_result.timestamp
|
||||
if should_process and self._detection_interval_seconds > 0:
|
||||
now = time.perf_counter()
|
||||
if (
|
||||
last_detection_time is not None
|
||||
and (now - last_detection_time) < self._detection_interval_seconds
|
||||
):
|
||||
should_process = False
|
||||
else:
|
||||
last_detection_time = now
|
||||
elif should_process:
|
||||
last_detection_time = time.perf_counter()
|
||||
|
||||
detection_result = None
|
||||
if should_process:
|
||||
# 图像预处理
|
||||
enhanced_frame = self.image_enhancer.preprocess_frame(
|
||||
frame, mode="normal"
|
||||
)
|
||||
|
||||
# 保存结果
|
||||
if (
|
||||
save_results
|
||||
and self.logger.save_results_enabled
|
||||
and detection_result.frame_count % self.logger.save_results_interval == 0
|
||||
):
|
||||
self.logger.save_result_to_file(detection_result)
|
||||
|
||||
# 显示结果
|
||||
if self.display_enabled:
|
||||
self._display_results(frame, detection_result)
|
||||
|
||||
if limiter:
|
||||
limiter.enforce_rate_limit()
|
||||
|
||||
# LED检测
|
||||
detection_result = self.led_detector.detect_leds(enhanced_frame)
|
||||
last_detection_result = detection_result
|
||||
|
||||
# 记录结果
|
||||
self.logger.log_detection_result(detection_result)
|
||||
|
||||
alarm_result = self.alarm_manager.process_detection(detection_result)
|
||||
for event in alarm_result.events:
|
||||
self.logger.log_alarm_event(event)
|
||||
for roi_name in alarm_result.recoveries:
|
||||
self.logger.log_recovery_event(
|
||||
roi_name,
|
||||
detection_result.frame_count,
|
||||
detection_result.timestamp
|
||||
)
|
||||
|
||||
# 保存结果
|
||||
if (
|
||||
save_results
|
||||
and self.logger.save_results_enabled
|
||||
and detection_result.frame_count % self.logger.save_results_interval == 0
|
||||
):
|
||||
self.logger.save_result_to_file(detection_result)
|
||||
|
||||
display_detection_result = last_detection_result if last_detection_result is not None else detection_result
|
||||
|
||||
# 控制显示帧率:每N帧显示一次,避免UI绑定拖慢速度
|
||||
should_display = (current_frame_index % display_frame_interval == 0)
|
||||
|
||||
# 显示结果
|
||||
if self.display_enabled and display_detection_result is not None and should_display:
|
||||
t0 = time.perf_counter()
|
||||
self._display_results(frame, display_detection_result)
|
||||
total_display_time += time.perf_counter() - t0
|
||||
display_count += 1
|
||||
|
||||
# 检查退出条件
|
||||
if cv2.waitKey(1) & 0xFF == ord('q'):
|
||||
break
|
||||
@ -310,14 +371,23 @@ class YantaiVisionXSystem:
|
||||
results = [] if self.logger.save_results_enabled else None
|
||||
last_frame = None
|
||||
last_detection_result = None
|
||||
last_detection_time: Optional[float] = None
|
||||
display_frame_interval = 5 # 每5帧显示一次,降低UI绑定开销
|
||||
|
||||
self.logger.log_info(f"开始处理视频: {video_path}")
|
||||
|
||||
limiter = self.performance_limiter
|
||||
frame_index = 0
|
||||
|
||||
# 性能统计
|
||||
loop_start = time.perf_counter()
|
||||
total_display_time = 0.0
|
||||
display_count = 0
|
||||
|
||||
try:
|
||||
while self.is_running:
|
||||
current_time = time.perf_counter()
|
||||
|
||||
success, frame = self.camera.read_frame()
|
||||
if not success:
|
||||
if self.display_enabled and last_frame is not None:
|
||||
@ -326,46 +396,78 @@ class YantaiVisionXSystem:
|
||||
|
||||
current_frame_index = frame_index
|
||||
frame_index += 1
|
||||
|
||||
# 每100帧输出一次性能统计
|
||||
if frame_index % 100 == 0:
|
||||
elapsed = current_time - loop_start
|
||||
actual_fps = frame_index / elapsed if elapsed > 0 else 0
|
||||
avg_display = (total_display_time / display_count * 1000) if display_count > 0 else 0
|
||||
print(f"[性能] 帧:{frame_index} 实际FPS:{actual_fps:.1f} 显示次数:{display_count} 平均显示耗时:{avg_display:.1f}ms")
|
||||
|
||||
should_process = True
|
||||
if limiter and not limiter.should_process_frame(current_frame_index):
|
||||
continue
|
||||
|
||||
# 图像预处理
|
||||
enhanced_frame = self.image_enhancer.preprocess_frame(
|
||||
frame, mode="normal"
|
||||
)
|
||||
|
||||
# LED检测
|
||||
detection_result = self.led_detector.detect_leds(enhanced_frame)
|
||||
if results is not None:
|
||||
results.append(detection_result)
|
||||
should_process = False
|
||||
if last_detection_result is None:
|
||||
should_process = True
|
||||
|
||||
if should_process and self._detection_interval_seconds > 0:
|
||||
now = time.perf_counter()
|
||||
if (
|
||||
last_detection_time is not None
|
||||
and (now - last_detection_time) < self._detection_interval_seconds
|
||||
):
|
||||
should_process = False
|
||||
else:
|
||||
last_detection_time = now
|
||||
elif should_process:
|
||||
last_detection_time = time.perf_counter()
|
||||
|
||||
detection_result = None
|
||||
if should_process:
|
||||
# 图像预处理
|
||||
enhanced_frame = self.image_enhancer.preprocess_frame(
|
||||
frame, mode="normal"
|
||||
)
|
||||
|
||||
# LED检测
|
||||
detection_result = self.led_detector.detect_leds(enhanced_frame)
|
||||
last_detection_result = detection_result
|
||||
|
||||
if results is not None:
|
||||
results.append(detection_result)
|
||||
|
||||
# 记录结果
|
||||
if detection_result.frame_count % 100 == 0:
|
||||
self.logger.log_detection_result(detection_result)
|
||||
|
||||
alarm_result = self.alarm_manager.process_detection(detection_result)
|
||||
for event in alarm_result.events:
|
||||
self.logger.log_alarm_event(event)
|
||||
for roi_name in alarm_result.recoveries:
|
||||
self.logger.log_recovery_event(
|
||||
roi_name,
|
||||
detection_result.frame_count,
|
||||
detection_result.timestamp
|
||||
)
|
||||
|
||||
if self.display_enabled and frame is not None:
|
||||
last_frame = frame.copy()
|
||||
else:
|
||||
last_frame = None
|
||||
last_detection_result = detection_result
|
||||
|
||||
# 记录结果
|
||||
if detection_result.frame_count % 100 == 0:
|
||||
self.logger.log_detection_result(detection_result)
|
||||
|
||||
alarm_result = self.alarm_manager.process_detection(detection_result)
|
||||
for event in alarm_result.events:
|
||||
self.logger.log_alarm_event(event)
|
||||
for roi_name in alarm_result.recoveries:
|
||||
self.logger.log_recovery_event(
|
||||
roi_name,
|
||||
detection_result.frame_count,
|
||||
detection_result.timestamp
|
||||
)
|
||||
|
||||
display_detection_result = last_detection_result if last_detection_result is not None else detection_result
|
||||
|
||||
# 控制显示帧率:每N帧显示一次,避免UI绑定拖慢速度
|
||||
should_display = (current_frame_index % display_frame_interval == 0)
|
||||
|
||||
# 显示结果
|
||||
if self.display_enabled:
|
||||
self._display_results(frame, detection_result)
|
||||
if self.display_enabled and display_detection_result is not None and should_display:
|
||||
t0 = time.perf_counter()
|
||||
self._display_results(frame, display_detection_result)
|
||||
total_display_time += time.perf_counter() - t0
|
||||
display_count += 1
|
||||
if cv2.waitKey(1) & 0xFF == ord('q'):
|
||||
break
|
||||
|
||||
if limiter:
|
||||
limiter.enforce_rate_limit()
|
||||
|
||||
# 保存批量结果
|
||||
if results:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user