OpenCV与Compressive Tracking实现人脸的实时检测与跟踪

最近一直在关注压缩传感方面的东西,正好看到一篇新论文《Real-Time Compressive Tracking》。作者将压缩感知与图像跟踪结合起来,实现了有效的降维,最后只用一个简单的朴素贝叶斯分类器就实现了非常鲁棒的跟踪效果,值得一提的是,这个算法的实时性非常好,在320×240的分辨率下能达到40fps左右的速度。具体论文和代码可以参看作者的网页http://www4.comp.polyu.edu.hk/~cslzhang/CT/CT.htm。

有这么好的东西,怎么能抑制住我激动的心情呢,于是总在找机会实现并使用一下这个算法。

最近需要一个在室外能知道人位置的设备,当初考虑Kinect,但由于白天室外的热光源较多,很容易致盲Kinect。于是转向传统的摄像头。自然地就产生的人脸检测+跟踪的想法。


人脸检测:

目前主流的人脸检测方法就是Viola-Jones等人提出的Haar-like Feature Boost方法。该方法速度快,准确度高,再加上OpenCV中有该方法的实现(CascadeClassifier类),使用起来非常方便。下图是识别结果。



做完人脸识别后,到户外去测试,发现算法除了识别到人之外,还将一些非人类的东西识别为人,比如一些树叶密集的地方。既然Boost算法的思想就是多个弱分类器组成强分类器,我们也自然的类推一下,用多个级联检测器确定人脸。于是我又加入了对鼻子和嘴的检测器,当人脸检测器拿到所有候选人脸的位置后,再使用鼻子和嘴检测器检测候选区域,当这两种检测器都检出,或其中一个检出时,我们就可以判定这是人脸,而其他的是非人脸。通过这种方法,有效的降低了算法的错误接受率。



人脸跟踪:

跟踪方法有许多,常用的有CamShift、粒子滤波等等。但之前我说了,我很想找个机会使用CT(Compressive Tracking)算法,现在机会来了。

人脸检测器返回的是一个包围人脸的矩形,这刚好可以作为CT的初始化输入。CT的代码我是从作者的网页上下载的,为了更好的配合我们的目的,我做了一些修改。当跟踪的人离开视野后,必须停止跟踪并重置CT的贝叶斯模型,然后重新启动人脸检测器去检测新的人脸,得到新的人脸后再启动CT去跟,以此类推。研究了一下CT的代码后,发现贝叶斯分类器是有一个分数输出的,作为对匹配程度的度量,就是下面代码中的radioMax。

//processFrame函数中的代码
// predict
	sampleRect(_frame, _objectBox, rSearchWindow,detectBox);
	integral(_frame, imageIntegral, CV_32F);
	getFeatureValue(imageIntegral, detectBox, detectFeatureValue);
	int radioMaxIndex;
	float radioMax;
	radioClassifier(muPositive, sigmaPositive, muNegative, sigmaNegative, detectFeatureValue, radioMax, radioMaxIndex);
	_objectBox = detectBox[radioMaxIndex];

该值越大,匹配程度越高,经过测试,高匹配值一般在100左右,于是我们可以设定一个阈值,比如50。当贝叶斯分类器返回的分数小于该阈值时,就停止跟踪并重置分类器,然后启动人脸检测。当然这种方法存在一个问题,如果被跟踪的人突然被某个东西遮挡了一下,跟踪就停止了,而且很难保证检测器再次检测到该人。这里有一个简单但有效的解决方法,我们可以在跟踪目标移动到视场边缘时,才进行阈值判断,而其他情况下不做任何事情,尽力发挥CT的高鲁棒性!


小结:

将上面两部分和在一起后,整个程序完成了,实时性与鲁棒性均有较好的表现。注意以上提到的两个算法都有很多参数,想达到好的效果,要根据实际情况仔细条件那些参数,在做人脸检测的时候我就尝试了各种脸部部位的组合,尝试了很多训练好的文件,花了一个下午加晚上。当然如果有条件能自己训练的话,那是最好的了。另外,CT算法当中用的分类器只是最简单的朴素贝叶斯分类器,而且是在线学习的,所以有时会产生跟踪目标漂移的现象,要改进这点就可以从分类器下手,比如使用多个朴素贝叶斯分类器分别学习目标的不同状态,根据可信度决定是否学习当前状态,等等。



你可能感兴趣的:(AI,and,Image,Processing,OpenCV,压缩感知,人脸检测,目标跟踪)