You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于视频绿色通道提取心率的Python代码优化求助

优化基于视频绿色通道的心率提取代码

原代码存在几个核心问题导致心率计算不准确,下面给出针对性的优化方案:

原代码的关键问题

  1. 频率计算错误:np.fft.fftfreq返回的是归一化频率(单位:周期/采样点),需要乘以**视频帧率(采样率)**才能得到实际物理频率(Hz),原代码直接用归一化频率判断范围,完全偏离实际心率对应的频率区间。
  2. 心率计算逻辑错误:FFT后的峰值对应信号的频率分量,不是时间域的心跳次数,原代码通过计数峰值个数计算心率的逻辑完全错误,正确方式是取幅度最高的有效频率,再转换为BPM(频率×60)。
  3. 缺少信号预处理:原始绿色通道信号包含大量噪声,直接FFT会产生无效峰值,影响结果准确性。
  4. 未过滤负频率:FFT结果是对称的,负频率部分没有实际意义,应该只保留正频率区间。

优化后的代码

import numpy as np
from scipy.signal import find_peaks, savgol_filter

class ExtractHeartRate:
    def __init__(self, green_channel, timer, fps):
        self.green_channel = green_channel  # 时间序列的绿色通道数据(每帧的平均亮度值)
        self.timer = timer
        self.fps = fps  # 视频帧率(每秒采样帧数,即采样率)
        self.heart_rate = 0

    def calc_hr_process(self):
        # 1. 信号预处理:去均值 + 平滑降噪
        signal = self.green_channel - np.mean(self.green_channel)  # 去除直流分量
        signal = savgol_filter(signal, window_length=5, polyorder=2)  # 平滑滤波,减少噪声

        # 2. 执行FFT并处理结果
        n = len(signal)
        fft_result = np.fft.fft(signal)
        fft_amplitude = np.abs(fft_result)[:n//2]  # 只保留正频率部分的幅度
        fft_freq = np.fft.fftfreq(n, d=1/self.fps)[:n//2]  # 计算实际物理频率(Hz)

        # 3. 定位有效频率范围内的峰值
        # 对应心率范围:48~120BPM → 0.8~2Hz(BPM = 频率×60)
        freq_mask = (fft_freq >= 0.8) & (fft_freq <= 2)
        filtered_amp = fft_amplitude[freq_mask]
        filtered_freq = fft_freq[freq_mask]

        if len(filtered_amp) == 0:
            self.heart_rate = 0
            return self.heart_rate

        # 4. 找到幅度最高的峰值(对应最强的心率频率分量)
        peaks, _ = find_peaks(filtered_amp, height=np.max(filtered_amp)*0.5)  # 只保留幅度超过最大值50%的峰值
        if not peaks.size:
            self.heart_rate = 0
            return self.heart_rate

        # 取幅度最大的峰值对应的频率
        max_peak_idx = peaks[np.argmax(filtered_amp[peaks])]
        dominant_freq = filtered_freq[max_peak_idx]

        # 5. 转换为BPM
        self.heart_rate = round(dominant_freq * 60)
        # 确保结果在合理范围内
        self.heart_rate = max(40, min(self.heart_rate, 180))
        return self.heart_rate

优化说明

  • 信号预处理:通过去均值去除直流分量,用Savitzky-Golay滤波平滑信号,有效降低噪声对FFT的干扰。
  • 正确的频率计算:通过fps将归一化频率转换为实际Hz,确保频率范围判断符合真实心率区间。
  • 峰值选择逻辑:只保留正频率部分,筛选出对应48~120BPM的频率区间,然后取幅度最高的峰值作为心率对应的频率分量,避免无效噪声峰值的干扰。
  • 结果修正:最后将心率限制在40~180BPM的合理范围内,避免极端异常值。

内容的提问来源于stack exchange,提问作者daniel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 11:10:24