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

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:
@@ -280,50 +277,50 @@ def video_stream_thread():
print(f"[Video] 发送错误: {e}") print(f"[Video] 发送错误: {e}")
continue continue
# while not stop_event.is_set(): # while not stop_event.is_set():
# try: # try:
# with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: # with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
# s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1) # s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
# s.connect((SERVER_HOST, SERVER_PORT)) # s.connect((SERVER_HOST, SERVER_PORT))
# print(f"[Video] 已连接") # print(f"[Video] 已连接")
# camera_id_bytes = CAMERA_ID.encode("utf-8") # camera_id_bytes = CAMERA_ID.encode("utf-8")
# 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)) # small_frame = cv2.resize(apply_soft_roi(frame), (1280, 720))
# ret, buffer = cv2.imencode( # ret, buffer = cv2.imencode(
# ".jpg", small_frame, [cv2.IMWRITE_JPEG_QUALITY, 50] # ".jpg", small_frame, [cv2.IMWRITE_JPEG_QUALITY, 50]
# ) # )
# if not ret: # if not ret:
# continue # continue
# frame_bytes = buffer.tobytes() # frame_bytes = buffer.tobytes()
# header_id_len = len(camera_id_bytes).to_bytes(4, "big") # header_id_len = len(camera_id_bytes).to_bytes(4, "big")
# header_frame_len = len(frame_bytes).to_bytes(4, "big") # header_frame_len = len(frame_bytes).to_bytes(4, "big")
# packet = ( # packet = (
# header_id_len # header_id_len
# + camera_id_bytes # + camera_id_bytes
# + header_frame_len # + header_frame_len
# + frame_bytes # + frame_bytes
# ) # )
# s.sendall(packet) # s.sendall(packet)
# except queue.Empty: # except queue.Empty:
# continue # continue
# except Exception as e: # except Exception as e:
# print(f"[Video] 发送断开: {e}") # print(f"[Video] 发送断开: {e}")
# break # break
# 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] 线程结束")