修改心率部分,减小其负荷
This commit is contained in:
@@ -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)
|
||||||
@@ -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] 线程结束")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user