修改心率部分,减小其负荷
This commit is contained in:
@@ -14,11 +14,17 @@ class HeartRateMonitor:
|
||||
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.frame_counter = 0
|
||||
self.process_interval = 15 # 每15帧(约0.5s)计算一次,其他时间收集数据
|
||||
self.last_bpm = None
|
||||
|
||||
def _create_bandpass_filter(self, lowcut, highcut, fs, order=5):
|
||||
"""创建巴特沃斯带通滤波器"""
|
||||
nyq = 0.5 * fs
|
||||
@@ -92,6 +98,12 @@ class HeartRateMonitor:
|
||||
progress = int(len(self.r_buffer) / self.buffer_size * 100)
|
||||
return None # 或者返回 progress 表示进度
|
||||
|
||||
# [优化] 降频计算策略
|
||||
# 我们每帧都需要收集数据(Buffer append),但不需要每帧都做 FFT
|
||||
self.frame_counter += 1
|
||||
if self.frame_counter % self.process_interval != 0:
|
||||
return self.last_bpm
|
||||
|
||||
# --- 3. 信号处理 (核心升级部分) ---
|
||||
r = np.array(self.r_buffer)
|
||||
g = np.array(self.g_buffer)
|
||||
@@ -119,13 +131,13 @@ class HeartRateMonitor:
|
||||
mag = np.abs(fft_res)
|
||||
|
||||
# D. 寻找峰值
|
||||
# 限制频率范围 (45 BPM - 180 BPM)
|
||||
interest_idx = np.where((freqs >= 0.75) & (freqs <= 3.0))
|
||||
# 限制频率范围 (54 BPM - 180 BPM)
|
||||
interest_idx = np.where((freqs >= 0.9) & (freqs <= 3.0))
|
||||
valid_freqs = freqs[interest_idx]
|
||||
valid_mags = mag[interest_idx]
|
||||
|
||||
if len(valid_mags) == 0:
|
||||
return None
|
||||
return self.last_bpm
|
||||
|
||||
max_idx = np.argmax(valid_mags)
|
||||
peak_freq = valid_freqs[max_idx]
|
||||
@@ -136,4 +148,5 @@ class HeartRateMonitor:
|
||||
self.bpm_history.append(bpm)
|
||||
avg_bpm = np.mean(self.bpm_history)
|
||||
|
||||
self.last_bpm = 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_HEIGHT, 720)
|
||||
|
||||
@@ -149,7 +149,7 @@ def analysis_thread():
|
||||
status = 0 # 0:open 1:close
|
||||
last_time = time.time()
|
||||
last_freq = 0
|
||||
# heart_monitor = HeartRateMonitor()
|
||||
heart_monitor = HeartRateMonitor()
|
||||
while not stop_event.is_set():
|
||||
try:
|
||||
frame = frame_queue.get(timeout=1)
|
||||
@@ -220,10 +220,10 @@ def analysis_thread():
|
||||
last_time = time.time()
|
||||
result["eye_close_freq"] = last_freq
|
||||
payload["eye_close_freq"] = last_freq
|
||||
# bpm = heart_monitor.process_frame(frame, result["landmark"])
|
||||
# if bpm != None:
|
||||
# result["heart_rate_bpm"] = bpm
|
||||
# payload["heart_rate_bpm"] = bpm
|
||||
bpm = heart_monitor.process_frame(frame, result["landmark"])
|
||||
if bpm != None:
|
||||
result["heart_rate_bpm"] = bpm
|
||||
payload["heart_rate_bpm"] = bpm
|
||||
if data_queue.full():
|
||||
try:
|
||||
_ = data_queue.get_nowait()
|
||||
@@ -263,15 +263,12 @@ def video_stream_thread():
|
||||
# f"filesink location={filename} "
|
||||
# )
|
||||
# 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))
|
||||
while not stop_event.is_set():
|
||||
try:
|
||||
frame = video_queue.get(timeout=1)
|
||||
# small_frame = cv2.resize(apply_soft_roi(frame), (1280, 720))
|
||||
# print("[Video] 获取一帧视频")
|
||||
server.provide_frame(frame)
|
||||
# print("[Video] 已提供给 WebRTC 服务器")
|
||||
# out1.write(frame)
|
||||
# out2.write(frame)
|
||||
except queue.Empty:
|
||||
@@ -280,50 +277,50 @@ def video_stream_thread():
|
||||
print(f"[Video] 发送错误: {e}")
|
||||
continue
|
||||
# while not stop_event.is_set():
|
||||
# try:
|
||||
# with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||
# s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||
# try:
|
||||
# with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
|
||||
# s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
|
||||
|
||||
# s.connect((SERVER_HOST, SERVER_PORT))
|
||||
# print(f"[Video] 已连接")
|
||||
# s.connect((SERVER_HOST, SERVER_PORT))
|
||||
# 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():
|
||||
# try:
|
||||
# frame = video_queue.get(timeout=1)
|
||||
# while not stop_event.is_set():
|
||||
# try:
|
||||
# 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(
|
||||
# ".jpg", small_frame, [cv2.IMWRITE_JPEG_QUALITY, 50]
|
||||
# )
|
||||
# ret, buffer = cv2.imencode(
|
||||
# ".jpg", small_frame, [cv2.IMWRITE_JPEG_QUALITY, 50]
|
||||
# )
|
||||
|
||||
# if not ret:
|
||||
# continue
|
||||
# if not ret:
|
||||
# continue
|
||||
|
||||
# frame_bytes = buffer.tobytes()
|
||||
# header_id_len = len(camera_id_bytes).to_bytes(4, "big")
|
||||
# header_frame_len = len(frame_bytes).to_bytes(4, "big")
|
||||
# frame_bytes = buffer.tobytes()
|
||||
# header_id_len = len(camera_id_bytes).to_bytes(4, "big")
|
||||
# header_frame_len = len(frame_bytes).to_bytes(4, "big")
|
||||
|
||||
# packet = (
|
||||
# header_id_len
|
||||
# + camera_id_bytes
|
||||
# + header_frame_len
|
||||
# + frame_bytes
|
||||
# )
|
||||
# s.sendall(packet)
|
||||
# packet = (
|
||||
# header_id_len
|
||||
# + camera_id_bytes
|
||||
# + header_frame_len
|
||||
# + frame_bytes
|
||||
# )
|
||||
# s.sendall(packet)
|
||||
|
||||
# except queue.Empty:
|
||||
# continue
|
||||
# except Exception as e:
|
||||
# print(f"[Video] 发送断开: {e}")
|
||||
# break
|
||||
# except queue.Empty:
|
||||
# continue
|
||||
# except Exception as e:
|
||||
# print(f"[Video] 发送断开: {e}")
|
||||
# break
|
||||
|
||||
# except Exception as e:
|
||||
# print(f"[Video] 重连中... {e}")
|
||||
# time.sleep(3)
|
||||
# out1.release()
|
||||
# except Exception as e:
|
||||
# print(f"[Video] 重连中... {e}")
|
||||
# time.sleep(3)
|
||||
out1.release()
|
||||
# out2.release()
|
||||
print("[Video] 线程结束")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user