眼球中心定位跟踪算法—eyelike 代码解析
转载自:https://blog.csdn.net/wphkadn/article/details/53304611
论文及代码地址
原始论文 Accurate eye centre localisation by means of gradients
原始代码 eyelike
我自己提交的将opencv改为纯c++地址:https://github.com/kadn/imitated-eyeLike-Master
代码分析(很久之前写的,排版有点乱,有时间再更新)
Main函数中
face_cascade用于实现人脸捕获,之后是窗口命名。
通过CvCapture将摄像头捕获到的图像传入frame,然后对frame进行分析
进入detectAndDisplay
frame是总的图像.
Faces是在frame基础上得到的人脸区域,vector<Rect>型
通过split函数将frame通道分开,并且取R通道作为灰度图。
face_cascade.detectMultiScale用于检测在此灰度图上面的人脸区域。
对每一个人脸区域均做如下处理:
首先在原图中用矩形标出人脸位置
然后进入findEyes函数 faceROI是灰度图的人脸区域部分,即ROI。
接下来标出眼球所处的区域(此部分为估计区域),以人脸区域为准,按比例估计眼镜区域
cv::Point leftPupil =findEyeCenter(faceROI,leftEyeRegion,"Left Eye");
此语句用于查找眼球的中心,即瞳孔附近。
首先将估计的眼球区域拿出来作为图像命名为eyeROIUnscaled,再改变大小换成较为方形的。
宽度为50,称此图为eyeROI
标记处face上面eye的矩形图
rectangle(face,eye,1234);通过注释此行可以知道原先估计出来的眼睛区域较大,一般都会将眉毛包括进去。
cv::Mat gradientX =computeMatXGradient(eyeROI);
cv::Mat gradientY =computeMatXGradient(eyeROI.t()).t();
cv::Mat mags =matrixMagnitude(gradientX, gradientY);
通过这三个函数来将eyeROI的梯度计算出来,不过这时候的eyeROI已经是变形后的了
double gradientThresh =computeDynamicThreshold(mags, kGradientThreshold);
计算出动态阈值来去除掉较小的部分,以max为基准。
详细来说,将小的部分置为0,大的部分将gradientX和gradientY归一3,而mags不变
之后以5*5的高斯滤波器滤波。
根据eyeROI灰度图的灰度值来为计算出将来要用到的每一个点的附加权重值,命名为weight
然后通过遍历gradientX和gradientY(此时已经成单位值)来寻找可能的中心点。
首先排除gradientX=0以及gradientY=0的点,接下来测试其它点testPossibleCentersFormula
对于每一个不被排除的点(x,y)都进行如下操作:
求出可能点中心点到(x,y)的距离向量,单位化,但mag保持原值。因为这一过程主要测试找到两个向量方向相同的点,所以不必约束其向量大小,重点在单位化后的内积大小。找到最大的意味着找到了方向相同的一系列点。此次最大的内积结果记为dotProduct。将内积结果加上权重后记录于Or中。Or是outSum的指针。
numGradient记录rows*cols。
将outSum变换数据类型成为out。
找出out中最大值以及它的位置分别记为maxVal和maxP
此时设置另外一个阈值,即floodThresh=maxVal * kPostProcessThreshold;
此语句舍弃了97%的点。那些被舍弃的点置0,其他保存
经过floodKillEdges。又去除了一些点。
这时取最大值就认为是eyecenter.
在这里也就是可以总结说:只计算了一次,便将中心点通过两次取最大值得到了。
程序的后半部分便是标记出原图的眼球中心。然后将结果图显示出来。