OpenCV学习笔记A.docx
《OpenCV学习笔记A.docx》由会员分享,可在线阅读,更多相关《OpenCV学习笔记A.docx(46页珍藏版)》请在冰豆网上搜索。
OpenCV学习笔记A
分类器(模式识别)
目标检测方法最初由PaulViola[Viola01]提出,并由RainerLienhart[Lienhart02]对这一方法
进行了改善.首先,利用样本(大约几百幅样本图片)的harr特征进行分类器训练,得到一个级
联的boosted分类器。
训练样本分为正例样本和反例样本,其中正例样本是指待检目标样本(例如人
脸或汽车等),反例样本指其它任意图片,所有的样本图片都被归一化为同样的尺寸大小(例如,
20x20)。
分类器训练完以后,就可以应用于输入图像中的感兴趣区域(与训练样本相同的尺寸)的检测。
检测
到目标区域(汽车或人脸)分类器输出为1,否则输出为0。
为了检测整副图像,可以在图像中移动搜
索窗口,检测每一个位置来确定可能的目标。
为了搜索不同大小的目标物体,分类器被设计为可以
进行尺寸改变,这样比改变待检图像的尺寸大小更为有效。
所以,为了在图像中检测未知大小的目
标物体,扫描程序通常需要用不同比例大小的搜索窗口对图片进行几次扫描。
分类器中的“级联”是指最终的分类器是由几个简单分类器级联组成。
在图像检测中,被检窗口依
次通过每一级分类器,这样在前面几层的检测中大部分的候选区域就被排除了,全部通过每一级分
类器检测的区域即为目标区域。
目前支持这种分类器的boosting技术有四种:
Discrete
Adaboost,RealAdaboost,GentleAdaboostandLogitboost。
"boosted"即指级联分类器的每一
层都可以从中选取一个boosting算法(权重投票),并利用基础分类器的自我训练得到。
基础分类器
是至少有两个叶结点的决策树分类器。
Haar特征是基础分类器的输入,主要描述如下。
目前的算法
主要利用下面的Harr特征。
每个特定分类器所使用的特征用形状、感兴趣区域中的位置以及比例系数(这里的比例系数跟检测
时候采用的比例系数是不一样的,尽管最后会取两个系数的乘积值)来定义。
例如在第三行特征
(2c)的情况下,响应计算为复盖全部特征整个矩形框(包括两个白色矩形框和一个黑色矩形框)象素
的和减去黑色矩形框内象素和的三倍。
每个矩形框内的象素和都可以通过积分图象很快的计算出来
。
(察看下面和对cvIntegral的描述).
通过HaarFaceDetect的演示版可以察看目标检测的工作情况。
下面只是检测部分的参考手册。
haartraining是它的一个单独的应用,可以用来对系列样本训练级
联的boosted分类器。
详细察看opencv/apps/haartraining。
CvHaarFeature,CvHaarClassifier,CvHaarStageClassifier,CvHaarClassifierCascade
BoostedHaar分类器结构
#defineCV_HAAR_FEATURE_MAX 3
/*一个harr特征由2-3个具有相应权重的矩形组成ahaarfeatureconsistsof2-3
rectangleswithappropriateweights*/
typedefstructCvHaarFeature
{
int tilted; /*0meansup-rightfeature,1means45--rotatedfeature*/
/*2-3rectangleswithweightsofoppositesignsand
withabsolutevaluesinverselyproportionaltotheareasoftherectangles.
ifrect[2].weight!
=0,then
thefeatureconsistsof3rectangles,otherwiseitconsistsof2*/
struct
{
CvRectr;
floatweight;
}rect[CV_HAAR_FEATURE_MAX];
}
CvHaarFeature;
/*asingletreeclassifier(stumpinthesimplestcase)thatreturnstheresponsefor
thefeature
attheparticularimagelocation(i.e.pixelsumoversubrectanglesofthewindow)
andgivesout
avaluedependingontheresponce*/
typedefstructCvHaarClassifier
{
intcount; /*numberofnodesinthedecisiontree*/
/*theseare"parallel"arrays.Everyindexi
correspondstoanodeofthedecisiontree(roothas0-thindex).
left[i]-indexoftheleftchild(ornegatedindexiftheleftchildisaleaf)
right[i]-indexoftherightchild(ornegatedindexiftherightchildisa
leaf)
threshold[i]-branchthreshold.iffeatureresponceis<=threshold,left
branch
ischosen,otherwiserightbranchischosed.
alpha[i]-outputvaluecorrepondingtotheleaf.*/
CvHaarFeature*haar_feature;
float*threshold;
int*left;
int*right;
float*alpha;
}
CvHaarClassifier;
/*aboostedbatteryofclassifiers(=stageclassifier):
thestageclassifierreturns1
ifthesumoftheclassifiers'responces
isgreaterthanthresholdand0otherwise*/
typedefstructCvHaarStageClassifier
{
int count; /*numberofclassifiersinthebattery*/
floatthreshold;/*thresholdfortheboostedclassifier*/
CvHaarClassifier*classifier;/*arrayofclassifiers*/
/*thesefieldsareusedfororganizingtreesofstageclassifiers,
ratherthanjuststrightcascades*/
intnext;
intchild;
intparent;
}
CvHaarStageClassifier;
typedefstructCvHidHaarClassifierCascadeCvHidHaarClassifierCascade;
/*cascadeortreeofstageclassifiers*/
typedefstructCvHaarClassifierCascade
{
int flags;/*signature*/
int count;/*numberofstages*/
CvSizeorig_window_size;/*originalobjectsize(thecascadeistrainedfor)*/
/*thesetwoparametersaresetbycvSetImagesForHaarClassifierCascade*/
CvSizereal_window_size;/*currentobjectsize*/
doublescale;/*currentscale*/
CvHaarStageClassifier*stage_classifier;/*arrayofstageclassifiers*/
CvHidHaarClassifierCascade*hid_cascade;/*hiddenoptimizedrepresentationofthe
cascade,
createdby
cvSetImagesForHaarClassifierCascade*/
}
CvHaarClassifierCascade;
所有的结构都代表一个级联boostedHaar分类器。
级联有下面的等级结构:
Cascade:
Stage1:
Classifier11:
Feature11
Classifier12:
Feature12
...
Stage2:
Classifier21:
Feature21
...
...
整个等级可以手工构建,也可以利用函数cvLoadHaarClassifierCascade从已有的磁盘文件或嵌入式
基中导入。
cvLoadHaarClassifierCascade
从文件中装载训练好的级联分类器或者从OpenCV中嵌入的分类器数据库中导入
CvHaarClassifierCascade*cvLoadHaarClassifierCascade(
constchar*directory,
CvSizeorig_window_size);
directory
训练好的级联分类器的路径
orig_window_size
级联分类器训练中采用的检测目标的尺寸。
因为这个信息没有在级联分类器中存储,所有要单独指
出。
函数cvLoadHaarClassifierCascade用于从文件中装载训练好的利用海尔特征的级联分类器,或者
从OpenCV中嵌入的分类器数据库中导入。
分类器的训练可以应用函数haartraining(详细察看
opencv/apps/haartraining)这个数值是在训练分类器时就确定好的,修改它并不能改变检测的范
围或精度。
需要注意的是,这个函数已经过时了。
现在的目标检测分类器通常存储在XML或YAML文件中,而
不是通过路径导入。
从文件中导入分类器,可以使用函数cvLoad。
cvReleaseHaarClassifierCascade
释放haarclassifiercascade。
voidcvReleaseHaarClassifierCascade(CvHaarClassifierCascade**cascade);
cascade
双指针类型指针指向要释放的cascade.指针由函数声明。
函数cvReleaseHaarClassifierCascade释放cascade的动态内存,其中cascade的动态内存或者是
手工创建,或者通过函数cvLoadHaarClassifierCascade或cvLoad分配。
cvHaarDetectObjects
检测图像中的目标
typedefstructCvAvgComp
{
CvRectrect;/*boundingrectanglefortheobject(averagerectangleofagroup)*/
intneighbors;/*numberofneighborrectanglesinthegroup*/
}
CvAvgComp;
CvSeq*cvHaarDetectObjects(constCvArr*image,CvHaarClassifierCascade*cascade,
CvMemStorage*storage,doublescale_factor=1.1,
intmin_neighbors=3,intflags=0,
CvSizemin_size=cvSize(0,0));
image
被检图像
cascade
harr分类器级联的内部标识形式
storage
用来存储检测到的一序列候选目标矩形框的内存区域。
scale_factor
在前后两次相继的扫描中,搜索窗口的比例系数。
例如1.1指将搜索窗口依次扩大10%。
min_neighbors
构成检测目标的相邻矩形的最小个数(缺省-1)。
如果组成检测目标的小矩形的个数和小于
min_neighbors-1都会被排除。
如果min_neighbors为0,则函数不做任何操作就返回所有的被检
候选矩形框,这种设定值一般用在用户自定义对检测结果的组合程序上。
flags
操作方式。
当前唯一可以定义的操作方式是CV_HAAR_DO_CANNY_PRUNING。
如果被设定,函数利用
Canny边缘检测器来排除一些边缘很少或者很多的图像区域,因为这样的区域一般不含被检目标。
人
脸检测中通过设定阈值使用了这种方法,并因此提高了检测速度。
min_size
检测窗口的最小尺寸。
缺省的情况下被设为分类器训练时采用的样本尺寸(人脸检测中缺省大小是
~20×20)。
函数cvHaarDetectObjects使用针对某目标物体训练的级联分类器在图像中找到包含目标物体
的矩形区域,并且将这些区域作为一序列的矩形框返回。
函数以不同比例大小的扫描窗口对图像进
行几次搜索(察看cvSetImagesForHaarClassifierCascade)。
每次都要对图像中的这些重叠区域利
用cvRunHaarClassifierCascade进行检测。
有时候也会利用某些继承(heuristics)技术以减少分
析的候选区域,例如利用Canny裁减(prunning)方法。
函数在处理和收集到候选的方框(全部
通过级联分类器各层的区域)之后,接着对这些区域进行组合并且返回一系列各个足够大的组合中的
平均矩形。
调节程序中的缺省参数(scale_factor=1.1,min_neighbors=3,flags=0)用于对目标进
行更精确同时也是耗时较长的进一步检测。
为了能对视频图像进行更快的实时检测,参数设置通常
是:
scale_factor=1.2,min_neighbors=2,flags=CV_HAAR_DO_CANNY_PRUNING,
min_size=(例如,对于视频会议的图像区域).
例子:
利用级联的Haarclassifiers寻找检测目标(e.g.faces).
#include"cv.h"
#include"highgui.h"
CvHaarClassifierCascade*load_object_detector(constchar*cascade_path)
{
return(CvHaarClassifierCascade*)cvLoad(cascade_path);
}
voiddetect_and_draw_objects(IplImage*image,
CvHaarClassifierCascade*cascade,
intdo_pyramids)
{
IplImage*small_image=image;
CvMemStorage*storage=cvCreateMemStorage(0);
CvSeq*faces;
inti,scale=1;
/*iftheflagisspecified,down-scalethe输入图像togeta
performanceboostw/oloosingquality(perhaps)*/
if(do_pyramids)
{
small_image=cvCreateImage(cvSize(image->width/2,image->height/2),
IPL_DEPTH_8U,3);
cvPyrDown(image,small_image,CV_GAUSSIAN_5x5);
scale=2;
}
/*usethefastestvariant*/
faces=cvHaarDetectObjects(small_image,cascade,storage,1.2,2,
CV_HAAR_DO_CANNY_PRUNING);
/*drawalltherectangles*/
for(i=0;itotal;i++)
{
/*extracttherectanlgesonly*/
CvRectface_rect=*(CvRect*)cvGetSeqElem(faces,i,0);
cvRectangle(image,cvPoint(face_rect.x*scale,face_rect.y*scale),
cvPoint((face_rect.x+face_rect.width)*scale,
(face_rect.y+face_rect.height)*scale),
CV_RGB(255,0,0),3);
}
if(small_image!
=image)
cvReleaseImage(&small_image);
cvReleaseMemStorage(&storage);
}
/*takesimagefilenameandcascadepathfromthecommandline*/
intmain(intargc,char**argv)
{
IplImage*image;
if(argc==3&&(image=cvLoadImage(argv[1],1))!
=0)
{
CvHaarClassifierCascade*cascade=load_object_detector(argv[2]);
detect_and_draw_objects(image,cascade,1);
cvNamedWindow("test",0);
cvShowImage("test",image);
cvWaitKey(0);
cvReleaseHaarClassifierCascade(&cascade);
cvReleaseImage(&image);
}
return0;
}
cvSetImagesForHaarClassifierCascade
为隐藏的cascade(hiddencascade)指定图像
voidcvSetImagesForHaarClassifierCascade(CvHaarClassifierCascade*cascade,
constCvArr*sum,constCvArr*sqsum,
constCvArr*tilted_sum,doublescale);
cascade
隐藏Harr分类器级联(HiddenHaarclassifiercascade),由函数
cvCreateHidHaarClassifierCascade生成
sum
32-比特,单通道图像的积分图像(Integral(sum)单通道imageof32-比特integerformat)
.这幅图像以及随后的两幅用于对快速特征的评价和亮度/对比度的归一化。
它们都可以利用函数
cvIntegral从8-比特或浮点数单通道的输入图像中得到。
sqsum
单通道64比特图像的平方和图像
tilted_sum
单通道32比特整数格式的图像的倾斜和(Tiltedsum)
scale
cascade的窗口比例.如果scale=1,就只用原始窗口尺寸检测(只检测同样尺寸大小的目标物体)
-原始窗口尺寸在函数cvLoadHaarClassifierCascade中定义(在""中缺
省为24x24),如果scale=2,使用的窗口是上面的两倍(在facecascade中缺省值是48x48)。
这样
尽管可以将检测速度提高四倍,但同时尺寸小于48x48的人脸将不能被检测到