OpenCV训练分类器Adaboost使用方法

上传人:jin****ng 文档编号:110347796 上传时间:2022-06-18 格式:DOC 页数:24 大小:151KB
返回 下载 相关 举报
OpenCV训练分类器Adaboost使用方法_第1页
第1页 / 共24页
OpenCV训练分类器Adaboost使用方法_第2页
第2页 / 共24页
OpenCV训练分类器Adaboost使用方法_第3页
第3页 / 共24页
亲,该文档总共24页,到这儿已超出免费预览范围,如果喜欢就下载吧!
资源描述
OpenCV训练分类器一、简介目标检测方法最初由Paul Viola ViolaO 1提出,并由Rainer Lienhart Lienhart02对这一方 法进行了改善。该方法的基本步骤为: 首先,利用样本(大约几百幅样本图片)的 harr 特 征进行分类器训练,得到一个级联的boosted分类器。分类器中的级联是指最终的分类器是由几个简单分类器级联组成。在图像检测中,被 检窗口依次通过每一级分类器, 这样在前面几层的检测中大部分的候选区域就被排除了, 全部通过每一级分类器检测的区域即为目标区域。分类器训练完以后,就可以应用于输入图像中的感兴趣区域(与训练样本相同的尺寸)的检 测。检测到目标区域(汽车或人脸)分类器输出为1,否则输出为0。为了检测整副图像,可 以在图像中移动搜索窗口,检测每一个位置来确定可能的目标。为了搜索不同大小的目标物 体,分类器被设计为可以进行尺寸改变,这样比改变 待检图像的尺寸大小更为有效。所以, 为了在图像中检测未知大小的目标物体,扫描程序通常需要用不同比例大小的搜索窗口对图 片进行几次扫描。目前支持这种分类器的 boosting 技术有四种: Discrete Adaboost, Real Adaboost, Gentle Adaboost and Logitboost。boosted即指级联分类器的每一层都可以从中选取一个boosting算法(权重投票),并利用基 础分类器的自我训练得到。根据上面的分析,目标检测分为三个步骤:1 、 样本的创建2、训练分类器3、利用训练好的分类器进行目标检测。二、样本创建训练样本分为正例样本和反例样本,其中正例样本是指待检目标样本 (例如人脸或汽车等),反例样本指其它任意图片,所有的样本图片都被归一化为同样的尺寸大小(例如,20x20)。 负样本负样本可以来自于任意的图片,但这些图片不能包含目标特征。负样本由背景描述文件 来描述。背景描述文件是一个文本文件,每一行包含了一个负样本图片的文件名(基于描述 文件的相对路径)。该文件必须手工创建。e.g: 负样本描述文件的一个例子:假定目录结构如下:/imgimg1.jpgimg2.jpgbg.txt则背景描述文件bg.txt的内容为:img/img1.jpgimg/img2.jpg正样本正样本由程序craatesample程序来创建。该程序的源代码由OpenCV给出,并且在bin 目录下包含了这个可执行的程序。正样本可以由单个的目标图片或者一系列的事先标记好的图片来创建。Createsamples 程序的命令行参数:命令行参数:vec 训练好的正样本的输出文件名。img 源目标图片(例如:一个公司图标)bg 背景描述文件。num 要产生的正样本的数量,和正样本图片数目相同。bgcolor 背景色(假定当前图片为灰度图)。背景色制定了透明色。对于压缩图片,颜色方差 量由 bgthresh 参数来指定。则在 bgcolorbgthresh 和 bgcolorbgthresh 中间的像素被认为是 透明的。bgthreshinv如果指定,颜色会反色randinv如果指定,颜色会任意反色maxidev背景色最大的偏离度。maxangelmaxangle, maxzangle 最大旋转角度,以弧度为单位。show如果指定,每个样本会被显示出来,按下esc会关闭这一开关,即不显示样本图片, 而创建过程继续。这是个有用的 debug 选项。w 输出样本的宽度(以像素为单位)hsample_height 输出样本的高度,以像素为单位。注:正样本也可以从一个预先标记好的图像集合中获取。这个集合由一个文本文件来描述, 类似于背景描述文件。每一个文本行对应一个图片。每行的第一个元素是图片文件名,第二 个元素是对象实体的个数。后面紧跟着的是与之匹配的矩形框(x, y,宽度,高度)。下面是一个创建样本的例子:假定我们要进行人脸的检测,有5个正样本图片文件imgl.bmp,.img5.bmp;有2个背景图 片文件:bgl.bmp,bg2.bmp,文件目录结构如下:positiveimgl.bmpImg5.bmpnegativebgl.bmpbg2.bmpinfo.dat bg.txt正样本描述文件 info.dat 的内容如下Positive/imag1.bmp 1 0 0 24 28Positive/imag5.bmp 1 0 0 24 28图片 img1.bmp 包含了单个目标对象实体,矩形为(0,0,24,28)。 注意:要从图片集中创建正样本,要用一info参数而不是用一img参数。 info 标记特征的图片集合的描述文件。 背景(负样本)描述文件的内容如下:nagative/bg1.bmpnagative/bg2.bmp 我们用一个批处理文件 run.bat 来进行正样本的创建:该文件的内容如下: cd e:facebinCreateSamples -vec e:facea.vec-info e:faceinfo.dat-bg e:facebg.txt-num 5-show-w 24-h 28其中e:facebin目录包含了 createsamples可执行程序,生成的正样本文件a.vec在e:face目 录下。三、训练分类器样本创建之后,接下来要训练分类器,这个过程是由haartraining程序来实现的。该程序 源码由OpenCV自带,且可执行程序在OpenCV安装目录的bin目录下。Haartraining 的命令行参数如下:一 data存放训练好的分类器的路径名。一 vec正样本文件名(由 trainingssamples 程序或者由其他的方法创建的)一 bg背景描述文件。一 npos,一 nneg 用来训练每一个分类器阶段的正/负样本。合理的值是: nPos = 7000;nNeg = 3000一 nstages训练的阶段数。一 nsplits决定用于阶段分类器的弱分类器。如果1,则一个简单的stump classifier被使用。如果是 2或者更多,则带有number_of_splits个内部节点的CART分类器被使用。一 mem预先计算的以MB为单位的可用内存。内存越大则训练的速度越快。sym(default)nonsym 指定训练的目标对象是否垂直对称。垂直对称提高目标的训练速度。例如,正面部是垂 直对称的。minhitratemin_hit_rate 每个阶段分类器需要的最小的命中率。总的命中率为 min_hit_rate 的 number_of_stages 次 方。maxfalsealarm没 有 阶 段 分类 器 的 最 大 错 误报 警 率 。 总 的错 误 警 告 率 为 max_false_alarm_rate 的 number_of_stages 次方。weighttrimming 指定是否使用权修正和使用多大的权修正。一个基本的选择是 0.9eqwmode选择用来训练的haar特征集的种类。basic仅仅使用垂直特征。all使用垂直和45度角旋 转特征。wsample_widthhsample_height 训练样本的尺寸,(以像素为单位)。必须和训练样本创建的尺寸相同。一个训练分类器的例子:同上例,分类器训练的过程用一个批处理文件run2.bat来完成:cd e:facebinhaartraining -data e:facedata-vec e:facea.vec-bg e:facebg.txt-npos 5-nneg 2-w 24-h 28训练结束后,会在目录data下生成一些子目录,即为训练好的分类器。注:OpenCv的某些版本可以将这些目录中的分类器直接转换成xml文件。但在实际的操作 中,haartraining程序却好像永远不会停止,而且没有生成xml文 件,后来在OpenCV的yahoo 论坛上找到一个haarconv的程序,才将分类器转换为xml文件,其中的原因尚待研究。OpenCV学习笔记(三)人脸检测的代码分析转自htt p:/ ntryOpenCV 学习笔记(三)人脸检测的代码分析 一、预备知识:1 、动态内存存储及操作函数CvMemStoragetypedef struct CvMemStoragestruct CvMemBlock* bottom;/* first allocated block */ structCvMemBlock*top;/*thecurrentmemoryblock-topofthestack */struct CvMemStorage* parent; /* borrows new blocks from */int block_size; /* block size */int free_space; /* free space in the top block (in bytes) */ CvMemStorage;内存存储器是一个可用来存储诸如序列,轮廓,图形,子划分等动态增长数据结 构的底层结构。它是由一系列以同等大小的内存块构成,呈列表型 -bottom 域 指的是列首,top域指的是当前指向的块但未必是列尾在bottom和top之间所 有的块(包括bottom,不包括top)被完全占据了空间;在top和列尾之间所有 的块(包括块尾,不包括top)则是空的;而top块本身则被占据了部分空间一 free_space 指的是 top 块剩余的空字节数。新分配的内存缓冲区(或显示的通 过 cvMemStorageAlloc 函数分配,或隐示的通过 cvSeqPush, cvGraphAddEdge 等高级函数分配)总是起始于当前块(即top块)的剩余那部分,如果剩余那部 分能满足要求(够分配的大小)。分配 后, free_space 就减少了新分配的那部 分内存大小,外加一些用来保存适当列型的附加大小。当top块的剩余空间无法 满足被分配的块(缓冲区)大小时,top块的下一个存储 块被置为当前块(新 的 top 块) - free_space 被置为先前分配的整个块的大小。如果已经不存在 空的存储块(即:top块已是列尾),则必须再分配一个新的块(或从pare nt 那继承,见cvCrea teCh il dMemS torage )并将该块加到列尾上去。于是,存储器(memory storage)就如同栈(Stack)那样,bottom 指向栈底,(top, free_space) 对指向栈顶。栈顶可通过 cvSaveMemStoragePos 保存,通过 cvRestoreMemStoragePos 恢复指向, 通过 cvClearStorage 重置。 CvMemBlock 内存存储块结构 typedef struct CvMemBlockstruct CvMemBlock* prev;struct CvMemBlock* next; CvMemBlock;CvMemBlock 代表一个单独的内存存储块结构。 内存存储块中的实际数据存储在 header 块 之后(即:存在一个头指针 head 指向的块 header ,该块不存储数 据),于是,内存块的第 i 个字节可以通过表达式 (char*)(mem_block_ptr+1)i 获得。然而,通常没必要直接去获得存储结构 的域。CvMemStoragePos 内存存储块地址 typedef struct CvMemStoragePos CvMemBlock* top; int free_space; CvMemStoragePos; 该结构(如以下所说)保存栈顶的地址,栈顶可以通过 cvSaveMemStoragePos 保 存,也可以通过 cvRestoreMemStoragePos 恢复。cvCreateMemStorage创建内存块CvMemStorage* cvCreateMemStorage( int block_size=0 );block_size :存储块的大小以字节表示。如果大小是 0 byte, 则将该块设置成 默认值 当前默认大小为 64k.函数 cvCreateMemStorage 创建一内存块并返回指向块首的指针。起初,存储块 是空的。头部(即:header)的所有域值都为0,除了 block_size夕卜.cvCreateChildMemStorage创建子内存块CvMemStorage* cvCreateChildMemStorage( CvMemStorage* parent );parent 父内存块函数 cvCreateChildMemStorage 创建一类似于普通内存块的子内存块,除了内 存分配/释放机制不同夕。当一个子存储块需要一个新的块加入时,它就试图从 parent 那得到这样一个块。如果 parent 中 还未被占据空间的那些块中的第一 个块是可获得的,就获取第一个块(依此类推),再将该块从 parent 那里去 除。如果不存在这样的块,则paren t要么分配一个,要么从它自己pare nt (即: parent 的 parent) 那借个过来。换句话说,完全有可能形成一个链或更为复杂 的结构,其中的内存存储块互为 child/ parent 关系(父子关系)。当子存储 结构被释放或清除,它就把所有的块还给各自的 parent. 在其他方面,子存储 结构同普通存储结构一样。子存储结 构在下列情况中是非常有用的。想象一下,如果用户需要处理存储在 某个块中的动态数据,再将处理的结果存放在该块中。在使用了最简单的方法处 理后,临时数据 作为输入和输出数据被存放在了同一个存储块中,于是该存储 块看上去就类似下面处理后的样子: Dynamicdataprocessingwithoutusing child storage. 结果,在存储块中,出现了垃圾(临时数据)。然而,如果在 开始处理数据前就先建立一个子存储块,将临时数据写入子存储块中并在最后释 放子存储块,那么最终 在 源/目的存储块(source/destination storage)中 就不会出现垃圾,于是该存储块看上去应该是如下形式:Dynamic data processing using a child storage.cvReleaseMemStorage释放内存块void cvReleaseMemStorage( CvMemStorage* storage );storage: 指向被释放了的存储块的指针函数 cvReleaseMemStorage 释放所有的存储(内存)块 或者 将它们返回给各 自的parent (如果需要的话)。接下来再释放header块(即:释放头指针head 指向的块二free(head)并清除指向该块的指针(即:head = NULL)。在释放 作为 parent 的块之前,先清除各自的 child 块。cvClearMemStorage清空内存存储块void cvClearMemStorage( CvMemStorage* storage );st orage:存储存储块函数 cvClearMemStorage 将存储块的 top 置到存储块的头部(注:清空存储块 中的存储内容)。该函数并不释放内存(仅清空内存)。假使该内存块有一个父 内存块(即:存在一内存块与其有父子关系),则函数就将所有的块返回给其 parent.cvMemStorageAlloc在存储块中分配以内存缓冲区void* cvMemStorageAlloc( CvMemStorage* storage, size_t size );storage:内存块.size :缓冲区的大小.函数 cvMemStorageAlloc 在存储块中分配一内存缓冲区。该缓冲区的大小不能 超过内存块的大小,否则就会导致运行时错误。缓冲区的地址被调整为 CV_STRUCT_ALIGN 字节 (当前为 sizeof(double).cvMemStorageAllocString在存储块中分配一文本字符串typedef struct CvStringint len;char* ptr;CvString;CvString cvMemStorageAllocString ( CvMemStorage* storage, const char* ptr, int len=-1 );sto rage:存储块ptr:字符串len:字符串的长度(不计算0)。如果参数为负数,函数就计算该字符串的 长度。函数 cvMemStorageAlloString 在存储块中创建了一字符串的拷贝。它返回一结 构,该结构包含字符串的长度(该长度或通过用户传递,或通过计算得到)和指 向被拷贝了的字符串的指针。cvSaveMemStoragePos保存内存块的位置(地址)void cvSaveMemStoragePos( const CvMemStorage* storage, CvMemStoragePos* pos );storage:内存块.pos:内存块顶部位置。函数 cvSaveMemStoragePos 将存储块的当前位置保存到参数 pos 中。 函数 cvRestoreMemStoragePos 可进一步获取该位置(地址)。cvRestoreMemStoragePos 恢复内存存储块的位置 void cvRestoreMemStoragePos( CvMemStorage* storage, CvMemStoragePos* pos );storage:内存块.pos:新的存储块的位置函数 cvRestoreMemStoragePos 通过参数 pos 恢复内存块的位置。该函数和函 数 cvClearMemStorage 是释放被占用内存块的唯一方法。注意:没有什么方法 可去释放存储块中被占用的部分内存。2、分类器结构及操作函数:CvHaarFeature#define CV_HAAR_FEATURE_MAX 3typedef struct CvHaarFeatureint tilted;structCvRect r;float weight; rectCV_HAAR_FEATURE_MAX;CvHaarFeature;一个 harr 特征由 23 个具有相应权重的矩形组成titled : /* 0 means up-right feature, 1 means 45-rotated feature */ rectCV_HAAR_FEATURE_MAX; /* 2-3 rectangles with weights of opposite signsandwithabsolutevaluesinverselyproportionaltotheareasoftherectangles.ifrect2.weight!=0,then the feature consists of 3 rectangles, otherwise it consists of 2 */CvHaarClassifiertypedef struct CvHaarClassifierint count;CvHaarFeature* haar_feature;float* threshold;int* left;int* right; float* alpha;CvHaarClassifier;/* a single tree classifier (stump in the simplest case) that returns the response for the feature at the particular image location (i.e. pixel sum over subrectangles of the window) and gives out a value depending on the responce */ int count; /* number of nodes in the decision tree */* these are parallel arrays. Every index i corresponds to a node of the decision tree (root has 0-th index).lefti - index of the left child (or negated index if the left child is a leaf)righti - index of the right child (or negated index if the right child is a leaf)thresholdi - branch threshold. if feature responce is = threshold, left branch is chosen, otherwise right branch is chosed. alphai - output value correponding to the leaf. */ CvHaarStageClassifier typedef struct CvHaarStageClassifierint count; /* number of classifiers in the battery */ float threshold; /* threshold for the boosted classifier */ CvHaarClassifier* classifier; /* array of classifiers */ /* these fields are used for organizing trees of stage classifiers, rather than just stright cascades */int next;int child; int parent; CvHaarStageClassifier;/* a boosted battery of classifiers(=stage classifier): the stage classifier returns 1 if the sum of the classifiers responces is greater than threshold and 0 otherwise */int count; /* number of classifiers in the battery */ float threshold; /* threshold for the boosted classifier */ CvHaarClassifier* classifier; /* array of classifiers */ /* these fields are used for organizing trees of stage classifiers, rather than just stright cascades */ CvHaarClassifierCascade typedef struct CvHidHaarClassifierCascade CvHidHaarClassifierCascade; typedef struct CvHaarClassifierCascadeint flags;int count;CvSize orig_window_size;CvSize real_window_size;double scale;CvHaarStageClassifier* stage_classifier; CvHidHaarClassifierCascade* hid_cascade;CvHaarClassifierCascade;/* cascade or tree of stage classifiers */int flags; /* signature */int count; /* number of stages */CvSize orig_window_size; /* original object size (the cascade is trained for) */* these two parameters are set by cvSetImagesForHaarClassifierCascade */CvSize real_window_size; /* current object size */ double scale; /* current scale */CvHaarStageClassifier* stage_classifier; /* array of stage classifiers */CvHidHaarClassifierCascade* hid_cascade; /* hidden optimized representation of the cascade, created by cvSetImagesForHaarClassifierCascade */ 所有的结构都代表一个级联 boosted Haar 分类器。级联有下面的等级结构:Cascade:Stage1:Classifier11:Feature11Classifier12:Feature12Stage2:Classifier21:Feature21整个等级可以手工构建,也可以利用函数 cvLoadHaarClassifierCascade 从已有 的磁盘文件或嵌入式基中导入。特征检测用到的函数:cvLoadHaarClassifierCascade从文件中装载训练好的级联分类器或者从OpenCV中嵌入的分类器数据库中导入CvHaarClassifierCascade* cvLoadHaarClassifierCascade(const char* directory,CvSize orig_window_size );directory :训练好的级联分类器的路径orig_window_size:级联分类器训练中采用的检测目标的尺寸。因为这个信息没 有在级联分类器中存储,所有要单独指出。函 数 cvLoadHaarClassifierCascade 用于从文件中装载训练好的利用海尔特 征的级联分类器,或者从OpenCV中嵌入的分类器数据库中导入。分类器的训练 可以应用函数 haartraining(详细察看 opencv/apps/haartraining) 函数 已经过时了。现在的目标检测分类器通常存储在 XML 或 YAML 文件中, 而不是通过路径导入。从文件中导入分类器,可以使用函数 cvLoad 。 cvReleaseHaarClassifierCascade 释放 haar classifier cascade。void cvReleaseHaarClassifierCascade( CvHaarClassifierCascade* cascade );cascade :双指针类型指针指向要释放的 cascade. 指针由函数声明。 函数 cvReleaseHaarClassifierCascade 释放 cascade 的动态内存,其中 cascade 的动态内存或者是手工创建,或者通过函数 cvLoadHaarClassifierCascade 或 cvLoad 分配。cvHaarDetectObjects 检测图像中的目标 typedef struct CvAvgCompCvRect rect; /* bounding rectangle for the object (average rectangle of a group) */int neighbors; /* number of neighbor rectangles in the group */CvAvgComp;CvSeq* cvHaarDetectObjects( const CvArr* image, CvHaarClassifierCascade* cascade,CvMemStorage* storage, double scale_factor=1.1, int min_neighbors=3, int flags=0, CvSize min_size=cvSize(0,0) );image 被检图像cascade harr 分类器级联的内部标识形式storage 用来存储检测到的一序列候选目标矩形框的内存区域。scale_factor 在前后两次相继的扫描中,搜索窗口的比例系数。例如 1.1指将 搜索窗口依次扩大 10%。min_neighbors 构成检测目标的相邻矩形的最小个数(缺省1)。如果组成检测 目标的小矩形的个数和小于min_neighbors-l都会被排除。如果min_neighbors 为 0, 则函数不做任何操作就返回所有的被检候选矩形框,这种设定值一般用在 用户自定义对检测结果的组合程序上。flags 操作方式。当前唯一可以定义的操作方式是 CV_HAAR_DO_CANNY_PRUNING。 如果被设定,函数利用 Canny 边缘检测器来排除一些边缘很少或者很多的图像区 域,因为这样的区域一 般不含被检目标。人脸检测中通过设定阈值使用了这种 方法,并因此提高了检测速度。min_size 检测窗口的最小尺寸。缺省的情况下被设为分类器训练时采用的样本 尺寸(人脸检测中缺省大小是20X20)。函 数 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= (例如, 对于视频会议的图像区域).cvSetImagesForHaarClassifierCascade为隐藏的cascade(hidden cascade)指定图像void cvSetImagesForHaarClassifierCascade( CvHaarClassifierCascade* cascade,const CvArr* sum, const CvArr* sqsum,const CvArr* tilted_sum, double scale );cascade 隐藏 Harr 分类器级联 (Hidden Haar classifier cascade) , 由函 数 cvCreateHidHaarClassifierCascade 生成sum 32一比特,单通道图像的积分图像(Integral (sum)单通道image of 32- 比特 integer format) . 这幅图像以及随后的两幅用于对快速特征的评价和亮 度/对比度的归一化。 它们都可以利用函数 cvIntegral 从 8-比特或浮点数 单 通道的输入图像中得到。sqsum 单通道 64 比特图像的平方和图像til ted_sum单通道32比特整数格式的图像的倾斜和(Til ted sum) scalecascade 的窗口比例. 如果 scale=1, 就只用原始窗口尺寸检测 (只检测 同样尺寸大小的目标物体) - 原始窗口尺寸在函数 cvLoadHaarClassifierCascade 中定义(在中缺省 为24x24),如果scale=2,使用的窗口是上面的两倍(在face cascade中缺省 值是48x48 )。这样尽管可以将检测速度提高四倍,但同时尺寸小于48x48的 人脸将不能被检测到。函数 cvSetImagesForHaarClassifierCascade 为 hidden classifier cascade 指定图像 and/or 窗口比例系数。 如果图像指针为空,会继续使用原来的图像 (i.e.NULLs 意味这不改变图像)。比例系数没有 protection 值,但是原来 的值可以通过函数 cvGetHaarClassifierCascadeScale 重新得到并使用。这个 函数用于对特定图像中检测特定目标尺寸的cascade分类器的设定。函数通过 cvHaarDetectObjects 进行内部调 用,但当需要在更低一层的函数 cvRunHaarClassifierCascade 中使用的时候,用户也可以自行调用。 cvRunHaarClassifierCascade 在给定位置的图像中运行 cascade of boosted classifier int cvRunHaarClassifierCascade( CvHaarClassifierCascade* cascade,CvPoint pt, int start_stage=0 ); cascade Haar 级联分类器 pt 待检测区域的左上角坐标。待检测区域大小为原始窗口尺寸乘以当前设定的 比例系数。当前窗口尺寸可以通过 cvGetHaarClassifierCascadeWindowSize 重 新得到。start_stage 级联层的初始下标值(从 0 开始计数)。函数假定前面所有每层的 分类器都已通过。这个特征通过函数 cvHaarDetectObjects 内部调用,用于更好 的处理器高速缓冲存储器。函 数 cvRunHaarHaarClassifierCascade 用于对单幅图片的检测。在函数调用 前首先利用 cvSetImagesForHaarClassifierCascade 设定积分图和合适的比例 系数 (= 窗口尺寸)。当分析的矩形框全部通过级联分类器每一层的时返回正值 (这是一个候选目标),否则返回 0 或负值。二、例程分析:例子:利用级联的Haar classifiers寻找检测目标(e.g. faces).#include cv.h#include highgui.h /读取训练好的分类器。CvHaarClassifierCascade* load_object_detector( const char* cascade_path )return (CvHaarClassifierCascade*)cvLoad( cascade_path );void detect_and_draw_objects( IplImage* image,CvHaarClassifierCascade* cascade, int do_pyramids )IplImage* small_image = image;CvMemStorage* storage = cvCreateMemStorage(0); /创建动态内存CvSeq* faces;int i, scale = 1;/* if the flag is specified, down-scale the 输入图像 to get a performance boost w/o loosing quality (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 ) ;/函数 cvPyrDown 使用 Gaussian 金字塔分解对输入图像向下采样。首先它对输入图像 用指定滤波器进行卷积,然后通过拒绝偶数的行与列来下采样图像。scale = 2;/* use the fastest variant */faces = cvHaarDetectObjects( small_image, cascade, storage, 1.2, 2, CV_HAAR_DO_CANNY_PRUNING );/* draw all the rectangles */for( i = 0; i total; i+ )/* extract the rectanlges only */CvRect face_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 ); / 释放动态内存/* takes image filename and cascade path from the command line */int main( int argc, char* argv )IplImage* image;if( argc=3 & (image = cvLoadImage( argv1, 1 ) != 0 )CvHaarClassifierCascade* cascade = load_object_detector(argv2);detect_and_draw_objects( image, cascade, 1 );cvNamedWindow( test, 0 );cvShowImage( test, image );cvWaitKey(0);cvReleaseHaarClassifierCascade( &cascade ); cvReleaseImage( &image );return 0;关键代码很简单,装载分类器,对输入图像进行金字塔采样,然后用cv的函数 进行检测目标,最后输出检测到的目标矩形。全局Haar-Like特征图像识别的C+实现cvdirectcascade.h:#inClude Cv.h struCt TWeakClassifierCvReCt ReCtangles2;struCt PtrWeakClassifierlong *tl0, *tr0, *bl0, *br0; long *tl1, *tr1, *bl1, *br1; int offset, size0, size1;int Threshold;struCt ListObjeCtTypeint x, y, width, height;int w;bool use;ListObjeCtType *next;struCt TLearnedObjeCtTWeakClassifier *Classifiers;PtrWeakClassifier *SCaleClassifiers; int ObjeCtWidth, ObjeCtHeight; int NClassifiers;struCt TDeteCtSettingsdouble SCaleRatio, OffsetX, OffsetY;int Ignore, MinW;int StartSubWindow, EndSubWindow; ;bool LoadDefaultSetting(Char *FileName, TDeteCtSettings &DS);void LearnClassifiers(unsigned Char *IptImage, TLearnedObjeCt &target, int IptWidth, int IptHeight);int DetectObject(TLearnedObject &target, unsigned char *FrameImage, int Width, int Height, TDetectSettings &DS, CvRect *&Objects);cvdirectcascade.cpp:#include #include #include #include #include #include #include cv.h#include cvdirectcascade.hbool Overlapped(ListObjectType *obj1, ListObjectType *obj2)int cx = obj1-x + obj1-width / 2;int cy = obj1-y + obj1-height / 2;if (cx obj2-x) & (cx x + obj2-width) & (cy obj2-y) & (cy y + obj2-height)return true;cx = obj2-x + obj2-width / 2;cy = obj2-y + obj2-height / 2;if (cx obj1-x) & (cx x + obj1-width) & (cy obj1-y) & (cy y + obj1-height)return true;return false;void RestoreImage(unsigned char *IptImage, long *&IntegralImage, int IptWidth, int IptHeight) IntegralImage = new long (IptWidth + 1) * (IptHeight + 1);long *pic = IntegralImage;for (int i = 0; i IptWidth + 1; i+)*pic = 0; pic+;for (int j = 0; j IptHeight; j+)*pic = 0; pic+=IptWidth + 1;unsigned char *pc = IptImage;long *picx, *picy, *picxy;picxy = IntegralImage;pic = picxy + IptWidth + 2;picx = picxy + IptWidth + 1;picy = picxy + 1;for (i = 0; i IptHeight; i+)for (j = 0; j IptWidth; j+)*pic = *pc + *p
展开阅读全文
相关资源
相关搜索

最新文档


当前位置:首页 > 办公文档 > 活动策划


copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!