opencv 之 icvCreateHidHaarClassifierCascade 分类器信息初始化函数部分详细代码注释。

请看注释。这个函数,是人脸识别主函数,里面出现过的函数之一,作用是初始化分类器的数据,就是一个xml文件的数据初始化。


  1 static CvHidHaarClassifierCascade* icvCreateHidHaarClassifierCascade( CvHaarClassifierCascade* cascade )
  2 {
  3     CvRect* ipp_features = 0;//定义一个矩形框指针
  4     float *ipp_weights = 0, *ipp_thresholds = 0, *ipp_val1 = 0, *ipp_val2 = 0;//单精度浮点数指针4个
  5     int* ipp_counts = 0;//整形指针1个
  6
  7     CvHidHaarClassifierCascade* out = 0;//最终返回的值
  8
  9     int i, j, k, l;//for循环的控制变量
 10     int datasize;//数据大小
 11     int total_classifiers = 0;//总的分类器数目
 12     int total_nodes = 0;
 13     char errorstr[1000];//错误信息数组
 14     CvHidHaarClassifier* haar_classifier_ptr;//级联分类器指针
 15     CvHidHaarTreeNode* haar_node_ptr;
 16     CvSize orig_window_size;//提取窗口的大小
 17     int has_tilted_features = 0;
 18     int max_count = 0;
 19
 20     if( !CV_IS_HAAR_CLASSIFIER(cascade) )//判断传进来的分类器文件是否真正确
 21         CV_Error( !cascade ? CV_StsNullPtr : CV_StsBadArg, "Invalid classifier pointer" );
 22
 23     if( cascade->hid_cascade )//判断改分类器xml文件是否已经被初始化了
 24         CV_Error( CV_StsError, "hid_cascade has been already created" );
 25
 26     if( !cascade->stage_classifier )//如果没有阶级分类器,报错
 27         CV_Error( CV_StsNullPtr, "" );
 28
 29     if( cascade->count <= 0 )//如果分类器的阶级数<=0,报错
 30         CV_Error( CV_StsOutOfRange, "Negative number of cascade stages" );
 31
 32     orig_window_size = cascade->orig_window_size;//获取识别窗口的大小
 33
 34     /* check input structure correctness and calculate total memory size needed for
 35        internal representation of the classifier cascade */
 36
 37     for( i = 0; i < cascade->count; i++ )//对xml文件里面的每阶段的stage进行循环提取相关数据
 38     {
 39         CvHaarStageClassifier* stage_classifier = cascade->stage_classifier + i;
 40         //获取每次进入循环的后阶段的子分类器,以haarcascade_upperbody.xml 为例子,count是30,stage_classifier的count是20
 41
 42         if( !stage_classifier->classifier ||//判断阶段分类器、子分类器及其stage 层数 是否合法
 43             stage_classifier->count <= 0 )
 44         {
 45             sprintf( errorstr, "header of the stage classifier #%d is invalid "
 46                      "(has null pointers or non-positive classfier count)", i );
 47             CV_Error( CV_StsError, errorstr );
 48         }
 49
 50         max_count = MAX( max_count, stage_classifier->count );//获取子分类器stage的数目,以haarcascade_upperbody.xml为例,是20
 51         total_classifiers += stage_classifier->count;//统计出总的子分类器的stage数目,即tree,再统计
 52
 53         for( j = 0; j < stage_classifier->count; j++ )
 54         //这个for循环主要是进入到子分类器tree里面的数据提取并且对其正确性的判断,
 55         //循环条件为字stage数目,以haarcascade_upperbody.xml为例,为20
 56         {
 57             CvHaarClassifier* classifier = stage_classifier->classifier + j;//同上,找到此时循环的tree
 58
 59             total_nodes += classifier->count;//计算出此时循环的tree子分类器的root node 数目,再统计。以haarcascade_upperbody.xml为例,每个tree的node是1
 60             for( l = 0; l < classifier->count; l++ )
 61                 //这个是关键循环,主数据的获取
 62                 //以haarcascade_upperbody.xml为例,此时classifier->count=1,循环一次,进入里面获取关键数据
 63             {
 64                 for( k = 0; k < CV_HAAR_FEATURE_MAX; k++ )//CV_HAAR_FEATURE_MAX = 3,循环三次,feature的最大数目,以haarcascade_upperbody.xml为例,只有1个
 65                 {
 66                     if( classifier->haar_feature[l].rect[k].r.width )
 67                         //逐层递归,先找feature,再找它里面的rect标签里面的矩阵row,行的宽度
 68                         //以haarcascade_upperbody.xml为例,是2
 69                     {
 70                         CvRect r = classifier->haar_feature[l].rect[k].r;//把此时row矩阵框赋给r
 71                         int tilted = classifier->haar_feature[l].tilted;//获取xml标签tited的值
 72                         has_tilted_features |= tilted != 0;//|是位运算,例如0|1=1,这行的作用是判断has和tilted那个是1,还不知道其意义何在
 73                         if( r.width < 0 || r.height < 0 || r.y < 0 ||
 74                             r.x + r.width > orig_window_size.width
 75                             ||
 76                             (!tilted &&
 77                             (r.x < 0 || r.y + r.height > orig_window_size.height))
 78                             ||
 79                             (tilted && (r.x - r.height < 0 ||
 80                             r.y + r.width + r.height > orig_window_size.height)))
 81                             //这个if语句是对feature里面的数据矩形的各方面判断,包括矩形的宽、高、等
 82                             //矩形# %d的分类器# %d”“级分类器# %d是不是在里面”“参考(原创)级联窗口”
 83                         {
 84                             sprintf( errorstr, "rectangle #%d of the classifier #%d of "
 85                                      "the stage classifier #%d is not inside "
 86                                      "the reference (original) cascade window", k, j, i );
 87                             CV_Error( CV_StsNullPtr, errorstr );
 88                         }
 89                     }
 90                 }
 91             }
 92         }
 93     }
 94     //上面数据的判断结束后,到这里
 95
 96     datasize = sizeof(CvHidHaarClassifierCascade) +//获取整个分类器,xml文件的数据大小
 97                sizeof(CvHidHaarStageClassifier)*cascade->count +
 98                sizeof(CvHidHaarClassifier) * total_classifiers +
 99                sizeof(CvHidHaarTreeNode) * total_nodes +
100                sizeof(void*)*(total_nodes + total_classifiers);
101
102     out = (CvHidHaarClassifierCascade*)cvAlloc( datasize );//给最终返回的变量分配内存大小
103     memset( out, 0, sizeof(*out) );//对变量初始化,全部填充0
104
105     //下面是逐个赋值,初始化头部
106     /* init header */
107     out->count = cascade->count;//新分类器out的stage数目
108     out->stage_classifier = (CvHidHaarStageClassifier*)(out + 1);//子分类器tree的数目
109     haar_classifier_ptr = (CvHidHaarClassifier*)(out->stage_classifier + cascade->count);//tree指针
110     haar_node_ptr = (CvHidHaarTreeNode*)(haar_classifier_ptr + total_classifiers);//tree里面node的指针
111
112     out->isStumpBased = 1;//布尔类型,true
113     out->has_tilted_features = has_tilted_features;
114     out->is_tree = 0;
115
116     /* initialize internal representation */
117     for( i = 0; i < cascade->count; i++ )
118     {
119         CvHaarStageClassifier* stage_classifier = cascade->stage_classifier + i;
120         CvHidHaarStageClassifier* hid_stage_classifier = out->stage_classifier + i;
121
122         hid_stage_classifier->count = stage_classifier->count;
123         hid_stage_classifier->threshold = stage_classifier->threshold - icv_stage_threshold_bias;
124         hid_stage_classifier->classifier = haar_classifier_ptr;
125         hid_stage_classifier->two_rects = 1;
126         haar_classifier_ptr += stage_classifier->count;
127
128         hid_stage_classifier->parent = (stage_classifier->parent == -1)
129             ? NULL : out->stage_classifier + stage_classifier->parent;
130         hid_stage_classifier->next = (stage_classifier->next == -1)
131             ? NULL : out->stage_classifier + stage_classifier->next;
132         hid_stage_classifier->child = (stage_classifier->child == -1)
133             ? NULL : out->stage_classifier + stage_classifier->child;
134
135         out->is_tree |= hid_stage_classifier->next != NULL;
136
137         for( j = 0; j < stage_classifier->count; j++ )
138         {
139             CvHaarClassifier* classifier = stage_classifier->classifier + j;
140             CvHidHaarClassifier* hid_classifier = hid_stage_classifier->classifier + j;
141             int node_count = classifier->count;
142             float* alpha_ptr = (float*)(haar_node_ptr + node_count);
143
144             hid_classifier->count = node_count;
145             hid_classifier->node = haar_node_ptr;
146             hid_classifier->alpha = alpha_ptr;
147
148             for( l = 0; l < node_count; l++ )
149             {
150                 CvHidHaarTreeNode* node = hid_classifier->node + l;
151                 CvHaarFeature* feature = classifier->haar_feature + l;
152                 memset( node, -1, sizeof(*node) );
153                 node->threshold = classifier->threshold[l];
154                 node->left = classifier->left[l];
155                 node->right = classifier->right[l];
156
157                 if( fabs(feature->rect[2].weight) < DBL_EPSILON ||
158                     feature->rect[2].r.width == 0 ||
159                     feature->rect[2].r.height == 0 )
160                     memset( &(node->feature.rect[2]), 0, sizeof(node->feature.rect[2]) );
161                 else
162                     hid_stage_classifier->two_rects = 0;
163             }
164
165             memcpy( alpha_ptr, classifier->alpha, (node_count+1)*sizeof(alpha_ptr[0]));
166             haar_node_ptr =
167                 (CvHidHaarTreeNode*)cvAlignPtr(alpha_ptr+node_count+1, sizeof(void*));
168
169             out->isStumpBased &= node_count == 1;
170         }
171     }
172 /*
173 #ifdef HAVE_IPP
174     int can_use_ipp = !out->has_tilted_features && !out->is_tree && out->isStumpBased;
175
176     if( can_use_ipp )
177     {
178         int ipp_datasize = cascade->count*sizeof(out->ipp_stages[0]);
179         float ipp_weight_scale=(float)(1./((orig_window_size.width-icv_object_win_border*2)*
180             (orig_window_size.height-icv_object_win_border*2)));
181
182         out->ipp_stages = (void**)cvAlloc( ipp_datasize );
183         memset( out->ipp_stages, 0, ipp_datasize );
184
185         ipp_features = (CvRect*)cvAlloc( max_count*3*sizeof(ipp_features[0]) );
186         ipp_weights = (float*)cvAlloc( max_count*3*sizeof(ipp_weights[0]) );
187         ipp_thresholds = (float*)cvAlloc( max_count*sizeof(ipp_thresholds[0]) );
188         ipp_val1 = (float*)cvAlloc( max_count*sizeof(ipp_val1[0]) );
189         ipp_val2 = (float*)cvAlloc( max_count*sizeof(ipp_val2[0]) );
190         ipp_counts = (int*)cvAlloc( max_count*sizeof(ipp_counts[0]) );
191
192         for( i = 0; i < cascade->count; i++ )
193         {
194             CvHaarStageClassifier* stage_classifier = cascade->stage_classifier + i;
195             for( j = 0, k = 0; j < stage_classifier->count; j++ )
196             {
197                 CvHaarClassifier* classifier = stage_classifier->classifier + j;
198                 int rect_count = 2 + (classifier->haar_feature->rect[2].r.width != 0);
199
200                 ipp_thresholds[j] = classifier->threshold[0];
201                 ipp_val1[j] = classifier->alpha[0];
202                 ipp_val2[j] = classifier->alpha[1];
203                 ipp_counts[j] = rect_count;
204
205                 for( l = 0; l < rect_count; l++, k++ )
206                 {
207                     ipp_features[k] = classifier->haar_feature->rect[l].r;
208                     //ipp_features[k].y = orig_window_size.height - ipp_features[k].y - ipp_features[k].height;
209                     ipp_weights[k] = classifier->haar_feature->rect[l].weight*ipp_weight_scale;
210                 }
211             }
212
213             if( ippiHaarClassifierInitAlloc_32f( (IppiHaarClassifier_32f**)&out->ipp_stages[i],
214                 (const IppiRect*)ipp_features, ipp_weights, ipp_thresholds,
215                 ipp_val1, ipp_val2, ipp_counts, stage_classifier->count ) < 0 )
216                 break;
217         }
218
219         if( i < cascade->count )
220         {
221             for( j = 0; j < i; j++ )
222                 if( out->ipp_stages[i] )
223                     ippiHaarClassifierFree_32f( (IppiHaarClassifier_32f*)out->ipp_stages[i] );
224             cvFree( &out->ipp_stages );
225         }
226     }
227 #endif
228 */
229     cascade->hid_cascade = out;
230     assert( (char*)haar_node_ptr - (char*)out <= datasize );
231
232     cvFree( &ipp_features );
233     cvFree( &ipp_weights );
234     cvFree( &ipp_thresholds );
235     cvFree( &ipp_val1 );
236     cvFree( &ipp_val2 );
237     cvFree( &ipp_counts );
238
239     return out;
240 }
时间: 2024-11-03 17:40:35

opencv 之 icvCreateHidHaarClassifierCascade 分类器信息初始化函数部分详细代码注释。的相关文章

OpenCV中响应鼠标信息cvSetMouseCallback函数的使用

转自:http://blog.csdn.net/haihong84/article/details/6599838 程序代碼如下: #include <cv.h> #include <highgui.h> #include <stdio.h void onMouse(int event,int x,int y,int flags,void* param ); int main(int argc, char** argv) { CvCapture *capture; IplIm

atitit &#160;opencv apiattilax总结&#160;约500个函数 .xlsx

atitit  opencv apiattilax总结 约500个函数 .xlsx 1.1. CxCore中文参考手册 1 1.2. 机器学习中文参考手册  knn  svm  1 1.3. CvAux中文参考手册 立体匹配   3D Tracking PCA) Markov Models    \3 1.4. 图像处理  1 梯度.边缘和角点  2 采样.插值和几何变换  3 形态学操作 4 滤波器与色彩空间变换 5 金字塔及其应用  6 连接部件   7 图像与轮廓矩 8 特殊图像变换 9

opencv之adaboost中的cvCreateMTStumpClassifier函数详解~

cvCreateMTStumpClassifier函数出自opencv中的haartraining程序,在adaboost(cvCreateTreeCascadeClassifier)的强分类器(icvCreateCARTStageClassifier)中被两次调用,该函数用于寻找最优弱分类器,或者说成计算最优haar特征.功能很明确,但是大家都知道的,opencv的代码绝大部分写的让人真心看不懂,这个函数算是haartraining中比较难以看懂的函数,局部变量达到20个之多,童鞋我也是不甘心

iOS: 聊聊 Designated Initializer(指定初始化函数)

iOS: 聊聊 Designated Initializer(指定初始化函数) 一.iOS的对象创建和初始化 iOS 中对象创建是分两步完成: 分配内存 初始化对象的成员变量 我们最熟悉的创建NSObject对象的过程: 苹果官方有一副图片更生动的描述了这个过程: 对象的初始化是一个很重要的过程,通常在初始化的时候我们会支持成员变量的初始状态,创建关联的对象等.例如对于如下对象: 1 @interface ViewController : UIViewController 2 3 @end 4

第3阶段——内核启动分析之start_kernel初始化函数(5)

内核启动分析之start_kernel初始化函数(init/main.c) stext函数启动内核后,就开始进入start_kernel初始化各个函数, 下面只是浅尝辄止的描述一下函数的功能,很多函数真正理解需要对linux相关体系有很深的了解后才能明白 代码如下: asmlinkage void __init start_kernel(void) { char * command_line; extern struct kernel_param __start___param[], __sto

《扩展和嵌入python解释器》1.4 模块方法表和初始化函数

<扩展和嵌入python解释器>1.4 模块方法表和初始化函数 1.4 模块方法表和初始化函数 下面,我演示如何从Python程序调用spam_system().首先,我们需要在’方法表’列出名称和地址: [cpp] view plaincopy static PyMethodDef SpamMethods[] = { ... {"system",  spam_system, METH_VARARGS, "Execute a shell command."

关于何时使用构造函数,何时使用初始化函数

选择的区别,就在于 构造函数,在构造的时候,完成了对象的相关基本属性. 初始化函数,就是在构造了之后,还可以进行其他主要参数的设定. 构造函数,生成对象的时候,只能发生一次 初始化函数,原则上可以发生很多次. 举个例子,一个人,生下来,就是构造函数起了作用,比如是男是女 初始化函数好比在户口信息没有了,没有办法,到公安局重新办了一个.原则上这个是可以多次办的,只要人没有死.虽然政策不允许. 好了下面讲讲关于,bean,dbTable,db的构造函数和初始化函数的使用. 他们的关系是 db->db

iOS: Designated Initializer(指定初始化函数)

一.iOS的对象创建和初始化 iOS 中对象创建是分两步完成: 分配内存 初始化对象的成员变量 我们最熟悉的创建NSObject对象的过程: 苹果官方有一副图片更生动的描述了这个过程: 对象的初始化是一个很重要的过程,通常在初始化的时候我们会支持成员变量的初始状态,创建关联的对象等.例如对于如下对象: Test ViewController 上面的VC中有一个成员变量XXService,在viewWillAppear的时候发起网络请求获取数据填充VC. 大家觉得上面的代码有没有什么问题? 带着这

OC语言中的便利初始化函数和便利构造器

便利遍历初始化函数与便利构造器(以Student类为例): main函数 Student.h(声明) ................... Student.m(实现) .................