Files
bci_algo/blinkdetection/algorithm/eye_detection.py

73 lines
1.9 KiB
Python
Raw Normal View History

2026-06-05 09:34:29 +08:00
# -*- coding: utf-8 -*-
"""
Created on Mon Sep 29 16:14:17 2025
@author: 23749
"""
import numpy as np
from scipy.signal import butter, filtfilt
## 1.Bandpass Filter
def butter_bandpass(lowcut, highcut, fs, order=4):
# 滤波器
nyq = 0.5 * fs #ny:Nyquist频率即能表示的最大有效频率
low = lowcut / nyq
high = highcut / nyq
b, a = butter(order, [low, high], btype='band') #巴特沃斯滤波器order=4阶
return b, a
def bandpass_filter(data, lowcut, highcut, fs, order=4):
b, a = butter_bandpass(lowcut, highcut, fs, order)
return filtfilt(b, a, data)
## 2.Eye Blink Dectection
def blink_detection(F, fs, Dmin, Dmax, Emin, Emax):
"""
波形检测
输入: 差分特征向量 F, 采样率 fs
输出: b (0/1), 以及计算出的 d, e
"""
if F is None or len(F) < 3:
return 0, None, None
# 找最大时间(peak) & 最小时间(valley)
t_peak = np.argmax(F)
t_valley = np.argmin(F)
# 要求 peak 在 valley 之前(符合 blink 形态),否则交换
if t_valley < t_peak:
t_peak, t_valley = t_valley, t_peak
# 计算持续时间 d (ms)
d = (t_valley - t_peak) * 1000.0 / fs
# 计算能量 e (差分平方和)
e = np.sum(F[t_peak:t_valley + 1] ** 2)
# 阈值判定
if Dmin <= d <= Dmax and Emin <= e <= Emax:
b = 1 # 检测到眨眼
else:
b = 0 # 否则 no blink
return b, d, e
if __name__ == '__main__':
import matplotlib.pyplot as plt
fs = 250 # 采样率
t = np.arange(0, 5, 1/fs)
eog = 0.01 * np.random.randn(len(t)) # 基线+噪声
# 模拟眨眼(在 2.0s 注入脉冲)
center = int(2.0 * fs)
eog[center:center+5] += 0.5
eog[center+5:center+15] -= 0.4
# 测试 blink_detection
F = np.diff(eog)
b, d, e = blink_detection(F, fs, 70, 500, 0.1, 10)
print(f"Detected: {b}, Duration: {d}ms, Energy: {e}")