求基于Tracking.js的纯JavaScript眨眼检测实现方案(兼容其他JS库)
嘿,我来帮你搞定这个眨眼检测的问题!既然你已经能用Tracking.js拿到眼睛的矩形框了,接下来的核心就是通过眼睛的高度变化来判断是否眨眼——毕竟眨眼时眼睛会快速闭合再张开,垂直高度会明显缩水。下面是具体的实现方案,准确率基本能达到你要的70%-80%,还可以通过小技巧进一步优化:
基于Tracking.js的眨眼检测实现方案
核心逻辑
眨眼的本质是眼睛垂直高度在短时间内急剧下降,然后快速恢复。我们可以通过持续记录眼睛矩形的高度,对比基准高度(正常睁眼时的高度)的比值,再结合连续帧的判断,来避免误判,最终检测出眨眼动作。
具体步骤实现
1. 先初始化必要的变量
我们需要存储基准高度、采样帧计数、眨眼判定的阈值等,用来处理每帧数据:
// 存储眼睛基准高度(取前N帧的平均值,避免初始帧的误差) let eyeBaseHeight = 0; // 记录已采样的帧数,用来计算基准高度 let sampleFrames = 0; // 采样阈值:比如前10帧用来初始化基准高度,确保数据稳定 const SAMPLE_THRESHOLD = 10; // 眨眼判定阈值:当当前高度低于基准的45%左右时,认为接近闭眼状态 const BLINK_RATIO_THRESHOLD = 0.45; // 连续低帧计数:需要连续2-3帧都低于阈值才判定为眨眼,避免偶然波动的误判 let lowHeightFrameCount = 0; // 眨眼触发标记,防止短时间内重复触发 let blinkDetected = false;
2. 在track回调中加入眨眼判断逻辑
把下面的代码整合到你已有的track事件回调里,替换或补充你原有的处理逻辑:
tracker.on('track', function(event) { // 如果没检测到眼睛,重置计数(比如用户转头、遮挡了) if (event.data.length === 0) { lowHeightFrameCount = 0; return; } event.data.forEach(function(rect) { // 保留你原有的绘制矩形逻辑 window.plot(rect.x, rect.y, rect.width, rect.height); const currentEyeHeight = rect.height; // 第一步:初始化基准高度,取前10帧的平均值 if (sampleFrames < SAMPLE_THRESHOLD) { eyeBaseHeight += currentEyeHeight; sampleFrames++; // 采样完成后计算平均值 if (sampleFrames === SAMPLE_THRESHOLD) { eyeBaseHeight = eyeBaseHeight / SAMPLE_THRESHOLD; console.log('基准眼睛高度初始化完成:', eyeBaseHeight); } return; } // 第二步:计算当前高度和基准高度的比值 const heightRatio = currentEyeHeight / eyeBaseHeight; // 第三步:判断是否是眨眼动作 if (heightRatio < BLINK_RATIO_THRESHOLD) { lowHeightFrameCount++; // 连续2帧以上低于阈值,且还没触发过眨眼,判定为有效眨眼 if (lowHeightFrameCount >= 2 && !blinkDetected) { blinkDetected = true; console.log('眨眼检测到了!'); // 这里可以添加你的自定义逻辑,比如触发事件、更新页面UI等 // 例如:document.dispatchEvent(new CustomEvent('blinkDetected')); } } else { // 恢复正常高度,重置计数和标记 lowHeightFrameCount = 0; blinkDetected = false; } }); });
3. 几个提升准确率的小技巧
- 动态更新基准高度:如果用户使用过程中调整了姿势(比如凑近屏幕),眼睛高度会变化,可以每隔300帧重新计算一次基准,或者当连续20帧的高度都高于当前基准的1.2倍时,自动更新基准值。
- 过滤异常值:如果某帧的眼睛高度突然变得极小(比如1-2px),大概率是检测错误,直接忽略这帧的数据。
- 双眼协同判断:如果Tracking.js同时检测到左右眼,取两者高度的平均值来计算比值,这样比单眼判断更稳定,减少误判概率。
替代方案(如果Tracking.js稳定性不够)
要是Tracking.js的眼睛检测偶尔会飘,推荐试试face-api.js——它基于TensorFlow.js,能精准检测人脸关键点(包括上下眼睑的位置),计算眼睛的**眼宽眼高比(EAR)**来判断眨眼,准确率会更高。核心逻辑大概是这样:
// 先加载模型(可以本地部署模型文件,或者用公开的CDN) await faceapi.loadFaceLandmarkModel('/models'); // 检测人脸关键点 const detections = await faceapi.detectFaceLandmarks(document.getElementById('img')); const leftEye = detections.landmarks.getLeftEye(); const rightEye = detections.landmarks.getRightEye(); // 计算单眼的眼宽眼高比 function calculateEyeAspectRatio(eye) { // 计算垂直方向的两个距离 const vertical1 = faceapi.euclideanDistance(eye[1], eye[5]); const vertical2 = faceapi.euclideanDistance(eye[2], eye[4]); // 计算水平方向的距离 const horizontal = faceapi.euclideanDistance(eye[0], eye[3]); // 计算比值:(垂直距离平均值)/水平距离 return (vertical1 + vertical2) / (2 * horizontal); } const leftEAR = calculateEyeAspectRatio(leftEye); const rightEAR = calculateEyeAspectRatio(rightEye); const avgEAR = (leftEAR + rightEAR) / 2; // 一般来说,EAR低于0.25时就可以判定为眨眼 if (avgEAR < 0.25) { console.log('眨眼检测到了!'); // 你的自定义逻辑 }
内容的提问来源于stack exchange,提问作者Ganesh K
相关产品推荐
相关产品推荐

