zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    php 5.3新特性
    php:// — 访问各个输入/输出流(I/O streams)
    php 二维数组排序
    js 面向对象式编程
    jQuery 源码学习笔记
    c++ 指针(二)
    c++ 指针(一)
    visual studio 2012 的制作ActiveX、打包和发布
    用linqPad帮助你快速学习LINQ
    Caliburn.Micro学习笔记(五)----协同IResult
  • 原文地址:https://www.cnblogs.com/linguanh/p/4267441.html
Copyright © 2011-2022 走看看