眨眼检测算法有很多种,但准确率都有很大提高空间。此摘录几种简单的判断方法:
一:基于阀值的
http://www.cpe.ku.ac.th/~jeab/papers/chinnawat_JCSSE2009.pdf
当眼完全闭上时、需要更高的阀值才能找到一个联通区(media blur后)
二:简单逻辑判断法
https://github.com/madhurjain/TrackNoseBlinkEye/blob/master/TrackNoseBlinkEye/TrackNoseBlinkEye.cpp
说简单点就是判断眼中心在不在当前联通区内
/* Eye blink code goes here & checks for bounding rects
to determine whether eye is blinked or not.
*/
int is_blink(CvSeq* comp, int num, CvRect window, CvRect eye)
{
if (comp == 0 || num != 1)
return 0;
CvRect r1 = cvBoundingRect(comp, 1);
/* component is within the search window */
if (r1.x < window.x)
return 0;
if (r1.y < window.y)
return 0;
if (r1.x + r1.width > window.x + window.width)
return 0;
if (r1.y + r1.height > window.y + window.height)
return 0;
/* get the centroid of eye */
CvPoint pt = cvPoint(
eye.x + eye.width/2 ,
eye.y + eye.height/2
);
/* component is located at the eye's centroid */
if (pt.x <= r1.x || pt.x >= r1.x + r1.width)
return 0;
if (pt.y <= r1.y || pt.y >= r1.y + r1.height)
return 0;
return 1;
}
个人依据经验做的算法如下
//特征:眼睁开时图形似矩形、闭眼时似三角形。
/**
Trianglelikely Highly
开 图形似矩形 眼高
闭 似高三角形 眼低
openEyeLikely = max ((up and down value/2 )* high)
f(x) = max(openEyeLikely)
归一化处理:
高度归一化处理:Highly = float(brightCount)/rowMean.rows; 开眼时为1,闭眼时实验数据为0.3左右
rectangleLikely归一化处理: rectangleLikely = (up + down)/2 / middle. 开眼时接尽1, 闭眼小于0.5
openEyeLikely = rectangleLikely * Highly ;
*/
其实、眨点有很多特点:下眼皮很少移动、是上眼皮向下眨。由此可以做很一个眨眼周期的估计,上眼皮在一个周期内会跳动一次。
实际情况下会有很多其它问题
一:很难捕捉到真正close eye的瞬间。
二:眨眼会有拖影。
这些情况都难以解决,只能说慢点眨点吧,太快了处理不过来。