修改心率部分,减小其负荷

This commit is contained in:
邓智航
2026-01-27 00:09:11 +08:00
parent 1875072f5b
commit 8b651bec5a
2 changed files with 58 additions and 48 deletions

View File

@@ -14,11 +14,17 @@ class HeartRateMonitor:
self.b_buffer = collections.deque(maxlen=window_size) self.b_buffer = collections.deque(maxlen=window_size)
# 滤波器状态 # 滤波器状态
self.bp_b, self.bp_a = self._create_bandpass_filter(0.75, 2.5, fps) # 45-150 BPM # 修改: 将最低频率从 0.75(45 BPM) 提高到 0.9(54 BPM) 以过滤低频噪声
self.bp_b, self.bp_a = self._create_bandpass_filter(0.9, 2.5, fps) # 54-150 BPM
# 平滑结果用的 # 平滑结果用的
self.bpm_history = collections.deque(maxlen=10) self.bpm_history = collections.deque(maxlen=10)
# 优化: 降频计算
self.frame_counter = 0
self.process_interval = 15 # 每15帧(约0.5s)计算一次,其他时间收集数据
self.last_bpm = None
def _create_bandpass_filter(self, lowcut, highcut, fs, order=5): def _create_bandpass_filter(self, lowcut, highcut, fs, order=5):
"""创建巴特沃斯带通滤波器""" """创建巴特沃斯带通滤波器"""
nyq = 0.5 * fs nyq = 0.5 * fs
@@ -92,6 +98,12 @@ class HeartRateMonitor:
progress = int(len(self.r_buffer) / self.buffer_size * 100) progress = int(len(self.r_buffer) / self.buffer_size * 100)
return None # 或者返回 progress 表示进度 return None # 或者返回 progress 表示进度
# [优化] 降频计算策略
# 我们每帧都需要收集数据(Buffer append),但不需要每帧都做 FFT
self.frame_counter += 1
if self.frame_counter % self.process_interval != 0:
return self.last_bpm
# --- 3. 信号处理 (核心升级部分) --- # --- 3. 信号处理 (核心升级部分) ---
r = np.array(self.r_buffer) r = np.array(self.r_buffer)
g = np.array(self.g_buffer) g = np.array(self.g_buffer)
@@ -119,13 +131,13 @@ class HeartRateMonitor:
mag = np.abs(fft_res) mag = np.abs(fft_res)
# D. 寻找峰值 # D. 寻找峰值
# 限制频率范围 (45 BPM - 180 BPM) # 限制频率范围 (54 BPM - 180 BPM)
interest_idx = np.where((freqs >= 0.75) & (freqs <= 3.0)) interest_idx = np.where((freqs >= 0.9) & (freqs <= 3.0))
valid_freqs = freqs[interest_idx] valid_freqs = freqs[interest_idx]
valid_mags = mag[interest_idx] valid_mags = mag[interest_idx]
if len(valid_mags) == 0: if len(valid_mags) == 0:
return None return self.last_bpm
max_idx = np.argmax(valid_mags) max_idx = np.argmax(valid_mags)
peak_freq = valid_freqs[max_idx] peak_freq = valid_freqs[max_idx]
@@ -136,4 +148,5 @@ class HeartRateMonitor:
self.bpm_history.append(bpm) self.bpm_history.append(bpm)
avg_bpm = np.mean(self.bpm_history) avg_bpm = np.mean(self.bpm_history)
self.last_bpm = int(avg_bpm)
return int(avg_bpm) return int(avg_bpm)

View File

@@ -92,7 +92,7 @@ def capture_thread():
""" """
采集线程:优化了分发逻辑,对视频流进行降频处理 采集线程:优化了分发逻辑,对视频流进行降频处理
""" """
cap = cv2.VideoCapture(1) cap = cv2.VideoCapture(0)
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
@@ -149,7 +149,7 @@ def analysis_thread():
status = 0 # 0:open 1:close status = 0 # 0:open 1:close
last_time = time.time() last_time = time.time()
last_freq = 0 last_freq = 0
# heart_monitor = HeartRateMonitor() heart_monitor = HeartRateMonitor()
while not stop_event.is_set(): while not stop_event.is_set():
try: try:
frame = frame_queue.get(timeout=1) frame = frame_queue.get(timeout=1)
@@ -220,10 +220,10 @@ def analysis_thread():
last_time = time.time() last_time = time.time()
result["eye_close_freq"] = last_freq result["eye_close_freq"] = last_freq
payload["eye_close_freq"] = last_freq payload["eye_close_freq"] = last_freq
# bpm = heart_monitor.process_frame(frame, result["landmark"]) bpm = heart_monitor.process_frame(frame, result["landmark"])
# if bpm != None: if bpm != None:
# result["heart_rate_bpm"] = bpm result["heart_rate_bpm"] = bpm
# payload["heart_rate_bpm"] = bpm payload["heart_rate_bpm"] = bpm
if data_queue.full(): if data_queue.full():
try: try:
_ = data_queue.get_nowait() _ = data_queue.get_nowait()
@@ -263,15 +263,12 @@ def video_stream_thread():
# f"filesink location={filename} " # f"filesink location={filename} "
# ) # )
# out = cv2.VideoWriter(gst_pipeline, cv2.CAP_GSTREAMER, 0, fps, (width, height)) # out = cv2.VideoWriter(gst_pipeline, cv2.CAP_GSTREAMER, 0, fps, (width, height))
# out1 = cv2.VideoWriter('output1.mp4', fourcc, 30.0, (1280, 720)) out1 = cv2.VideoWriter('output1.mp4', fourcc, 30.0, (1280, 720))
# out2 = cv2.VideoWriter('output2.mp4', fourcc, 30.0, (1280, 720)) # out2 = cv2.VideoWriter('output2.mp4', fourcc, 30.0, (1280, 720))
while not stop_event.is_set(): while not stop_event.is_set():
try: try:
frame = video_queue.get(timeout=1) frame = video_queue.get(timeout=1)
# small_frame = cv2.resize(apply_soft_roi(frame), (1280, 720))
# print("[Video] 获取一帧视频")
server.provide_frame(frame) server.provide_frame(frame)
# print("[Video] 已提供给 WebRTC 服务器")
# out1.write(frame) # out1.write(frame)
# out2.write(frame) # out2.write(frame)
except queue.Empty: except queue.Empty:
@@ -323,7 +320,7 @@ def video_stream_thread():
# except Exception as e: # except Exception as e:
# print(f"[Video] 重连中... {e}") # print(f"[Video] 重连中... {e}")
# time.sleep(3) # time.sleep(3)
# out1.release() out1.release()
# out2.release() # out2.release()
print("[Video] 线程结束") print("[Video] 线程结束")