如何在一维EAR数组中检测代表眨眼的局部最小值?
基于EAR数据的眨眼检测优化方案

该图表展示了视频全程中眼睛的EAR(眼宽高比,Eye Aspect Ratio),图中明显的陡降代表眨眼动作——EAR用于衡量眼睛张开程度,眨眼时会出现快速下降后回升的特征。现在需要基于给定的一维EAR数据数组,检测出所有代表眨眼的局部最小值,本示例中需识别出全部5次眨眼。
我尝试了以下代码:
import numpy as np from scipy.signal import find_peaks # Invert the data to find local minima inverted_data = -np.array(seq) # Use find_peaks from SciPy to find the peaks in the inverted data # Adjust the 'distance' parameter as needed for your dataset peaks, _ = find_peaks(inverted_data, distance=5, height=-0.2) print(peaks) # The number of local minima is the length of the peaks array number_of_minima = len(peaks) print("Number of local minima:", number_of_minima)
但效果不佳,核心问题是:虽然distance参数能作为基础筛选条件,但height参数依赖固定的EAR阈值,而不同个体的眼睛特征差异会导致这个阈值无法通用。
优化思路:用自适应阈值替代固定值
既然固定阈值不通用,我们可以改用个体EAR基线的相对变化来判定眨眼,核心逻辑是:眨眼时EAR会相对于常态出现大幅下降,而非单纯低于某个固定数值。
优化后的代码
import numpy as np from scipy.signal import find_peaks # 替换为你的EAR数据数组 seq = np.array([0.3, 0.32, 0.31, 0.1, 0.3, 0.32, 0.29, 0.08, 0.31, 0.3, 0.33, 0.12, 0.3, 0.29, 0.31, 0.09, 0.32, 0.3, 0.31, 0.11, 0.3]) # 计算个体EAR基线:用中位数,避免眨眼导致均值偏移 ear_baseline = np.median(seq) # 设定相对下降比例:低于基线的60%判定为眨眼候选,可根据实际情况调整 threshold_ratio = 0.6 absolute_threshold = ear_baseline * threshold_ratio # 反转数据,将原数据的局部最小值转化为反转数据的峰值 inverted_data = -seq # 调用find_peaks: # - height:反转后对应原数据低于阈值的部分,即-inverted_data < absolute_threshold → inverted_data > -absolute_threshold # - distance:确保两次眨眼间隔符合生理规律(根据帧率调整,30FPS下5帧约160ms) peaks, _ = find_peaks(inverted_data, distance=5, height=-absolute_threshold) print("眨眼对应的索引位置:", peaks) print("检测到的眨眼次数:", len(peaks))
关键调整说明
- 自适应基线:用中位数计算常态EAR值,不受眨眼动作的干扰,更贴合个体特征
- 相对阈值:通过比例设定下降幅度,无需针对不同个体手动调整固定阈值
- 参数适配:
distance可根据视频帧率微调,避免把单次眨眼误判为多次,或漏判间隔较近的眨眼
内容的提问来源于stack exchange,提问作者Mark Shteyn
相关产品推荐
相关产品推荐

