物体检测方法大致可分为两类,基于知识的方法和基于统计的方法。前者如template matching, surf/sift detector等等。这些方法都基于咱们对于识别目标已有比较清晰的刻画。虽然有些特征能抗必定的形变,但整体泛化性不够强。若是检测目标比较固定且对时间要求不高,能够考虑用这类方法。但有些应用是无法提供模板的,或者说模板太多(一一匹配的话检测时间没法接受),又或者说咱们须要容忍更大程度或更多样的形变(如人脸,行人等)。这时候就要考虑用基于统计的方法了。既然是基于统计,就得有大量的样本,分类器对这些样本进行学习来得到参数。获得目标分类器后,要进行检测时就很快了。OpenCV中带的Haar特征级联分类器就是这样一种方法,它位于app目录下,该目录下有两个实现,一个是老的实现haartraining,只支持Haar特征。另外一个是新的traincascade,支持更多特征(LBP,HOG)和boosted分类器,更易于扩展。除此以外OpenCV的data目录下有不少训练好的级联分类器(如人脸,眼睛检测等),load进来就能够用,无需训练。官方例程中的objectdetection,facedetect等例子就是直接用了这些训练好的分类器,如自带的face detection程序:html
:linux
固然了,做为有理想有抱负的码农,用现成的分类器是不会知足的。现实使用中咱们常常须要训练针对各类应用的分类器。下面介绍如何训练一个本身的级联分类器。整个过程大体可分为如下几步(基于OpenCV 2.4.4):api
1. 收集数据app
数据可分为正样本和负样本。正样本即要检测的目标,负样本则不包含目标。ide
首先咱们要生成正负样本的索引(或称描述文件)。正样本描述文件官方文档中给了例子:wordpress
img/img1.jpg 1 140 100 45 45
img/img2.jpg 2 100 200 50 50 50 30 25 25svn
依次为文件名,目标个数,目标坐标。既然是基于统计的方法,样本天然要求不少(通常以千为单位),所以不少时候这一步是劳力活。固然,勤劳勇敢的码农们写了各类工具来解放生产力。这些描述文件能够人肉生成,也可用object marker(http://inflomatik.com/)来圈,而后自动生成。除此以外还有些其它工具:函数
http://code.google.com/p/opencv-haar-cascade-positive-image-builder/工具
http://code.google.com/p/imageclipper/学习
http://code.google.com/p/ml-object-marker/source/checkout
ffmpeg -i 能够将视频分解为图片
另外后面会讲到的createsamples工具还能够自动生成正样本。
负样本没这么麻烦了,描述文件只要包含文件路径便可,Windows中能够用dir /s /b生成,Linux下用find命令。
2. 建立vec文件
createsamples 工具可用于从正负样本描述文件生成训练程序须要的vec文件。如根据样本描述文件samples.txt生成samples.vec:
opencv_createsamples.exe -info samples.txt -vec samples.vec -w 20 -h 20
它还包含一个功能,经过distortion自动生成样本。如根据template.png和负样本描述文件negative.txt生成3000个样本。
opencv_createsamples.exe -img template.png -vec -num 3000 -bg negative.txt -vec samples.vec -w 20 -h 20
还有种很尴尬的状况,就是既没空圈那么多的正样本,又想检测多种目标,咋办?由于上面提到的经过distortion来自动生成样本的方法不支持多个目标。一种方法是先根据多个目标生成多个vec文件,再用mergevec(http://note.sonots.com/SciSoftware/haartraining/mergevec.cpp.html)这个工具合并vec文件。mergevec用最新的OpenCV编译不了,若是你和我同样懒不想移植的话就下个OpenCV 1.0(就下可执行文件包,3M多那个),把那坨dll放到PATH里,而后下mergevec.exe就能够跑了。如根据template1.png ~ template3.png分别生成三个vec文件:
opencv_createsamples.exe -img template1.png -num 1000 -bg negative -vec sample1.vec -w 20 -h 20
opencv_createsamples.exe -img template2.png -num 1000 -bg negative -vec sample2.vec -w 20 -h 20
opencv_createsamples.exe -img template3.png -num 1000 -bg negative -vec sample3.vec -w 20 -h 20
接着写vec的索引文件sample.txt:
sample1.vec
sample2.vec
sample3.vec
而后就能够生成最终的samples.vec文件了:
mergevec.exe sample.txt samples.vec -w 20 -h 20
另外,若是你的应用比较general,如从天然背景中找特定目标,网上有现成的负样本数据集:
svn checkout http://tutorial-haartraining.googlecode.com/svn/trunk/ tutorial-haartraining-read-only
3. 训练分类器
不少地方仍是用haartraining,官方手册中建议用新的traincascade。用法上参数什么的都差很少,不过仍是有差异。
根据刚才生成的样本描述文件进行训练,结果放在classifier目录里:
opencv_traincascade.exe -data classifier -vec samples.vec -bg negative.txt -numStages 25 -w 20 -h 20
其他有一坨参数,诸如maxFalseAlarmRate,minHitRate等想设就设下,不过默认的值大多数状况都是挺好的选择。
-featureType指定特征类型,默认为类Haar特征,还能够指定为LBP或HOG。基于Haar的级联分类器训练时间通常很长(以天为单位)。LBP,HOG则快得多。
注意这毕竟不是产品,不少时候参数一给很差就挂掉了。固然直接挂掉是最好的状况,最惨的是跑到中间hung住了,都不知道是由于hung住了仍是由于训练时间长。。。
注:不管是haartraining仍是traincascade,最终都会生成表示成xml文件的分类器。但若是你用的是haartraining而且想用中间Stage生成的分类器,能够用convert_cascade将中间结果整成xml文件。
4. 测试&验证
performance.exe能够对于给定的测试用例给出检测率报告。注意只对opencv_haartraining的结果适用。若是要写报告给数据这个颇有用。不过这里先不整这么抽象的东西,先写个程序直观地看看检测效果如何。官方例程中的objectdetection是从摄像头抓帧进行检测。这里咱们略微修改下从文件读取图片而后检测目标。其中关键函数为:
void CascadeClassifier::detectMultiScale(const Mat& image, vector<Rect>& objects, double scaleFactor=1.1, int minNeighbors=3, int flags=0, Size minSize=Size(), Size maxSize=Size())
其中的参数对于检测结果会有较大影响,如:
minNeighbors:其实分类器给出的结果是不少个矩形,那些被多个矩阵覆盖的区域被保留,而那些个孤立的矩阵被抛弃。这个参数决定了保留仍是抛弃的阈值。(http://www.cognotics.com/opencv/servo_2007_series/part_2/page_2.html)。
minSize :检测目标size的阀值,小于它的不会被检测出来。
这里拿”愤怒的小鸟“做个简单的例子,由于每一个关卡中笼子里的鸟虽不彻底相同,但都相似。这里以一关中笼子中的鸟为训练正样本,让其学习并检测其它关卡中哪些是笼中鸟。
在一些case中仍是有很多false alarm的。直观上可能会以为这种动画图片的检测会更容易,但动画图片因为背景形状规则,色块均匀,做为负样本并很差,因此负样本尽量仍是要取得变化丰富些。
一些案例和参考资料:
Tutorial: OpenCV haartraining (Rapid Object Detection With A Cascade of Boosted Classifiers Based on Haar-like Features) http://note.sonots.com/SciSoftware/haartraining.html Haar-feature Object Detection in C# http://www.codeproject.com/Articles/441226/Haar-feature-Object-Detection-in-Csharp Ivan Laptev | INRIA Paris - Rocquencourt, France http://www.di.ens.fr/~laptev/download.html#objectdetection OBJECT DETECTION IN OPENCV USING HAARTRAINING http://achuwilson.wordpress.com/2011/02/13/object-detection-using-opencv-using-haartraining/ Ultra Rapid Object Detection in Computer Vision Applications with Haar-like Wavelet Features http://www.codeproject.com/Articles/27125/Ultra-Rapid-Object-Detection-in-Computer-Vision-Ap HaarTraining for Pedestrian Detection http://se.cs.ait.ac.th/cvwiki/opencv:tutorial:haartraining#step_1dataset A simple object detector with boosting http://people.csail.mit.edu/torralba/shortCourseRLOC/boosting/boosting.html OpenCV Object Detection Howto http://opencv.willowgarage.com/wiki/ObjectDetection How to use HaarTraining in OpenCV http://kang.blog.com/2009/08/12/how-to-use-haartraining-in-opencv/ Create Your Own Haar Classifier for Detecting objects in OpenCV http://achuwilson.wordpress.com/2011/07/01/create-your-own-haar-classifier-for-detecting-objects-in-opencv/ How-to build a cascade of boosted classifiers based on Haar-like features http://opencv.willowgarage.com/wiki/ObjectDetection Face Detection using OpenCV http://opencv.willowgarage.com/wiki/FaceDetection Seeing With OpenCV http://www.cognotics.com/opencv/servo_2007_series/part_1/index.html FAQ for OpenCV haartraining http://www.computer-vision-software.com/blog/2009/11/faq-opencv-haartraining/ Simple Qt interface to try OpenCV implementations of SIFT, SURF, FAST, BRIEF and other feature detectors and descriptors http://code.google.com/p/find-object/ 《The OpenCV User Guide》 Chapter 4 Cascade classifier training 《Learning.OpenCV.Computer.Vision.with.the.OpenCV.Library》Chapter 13 Machine learning