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 }
如果您认为这篇文章还不错或者有所收获,您可以通过扫描一下下面的支付宝二维码 打赏我一杯咖啡【物质支持】,也可以点击右下角的【推荐】按钮【精神支持】,因为这两种支持都是我继续写作,分享的最大动力
、
opencv 之 icvCreateHidHaarClassifierCascade 分类器信息初始化函数部分详细代码注释。...相关推荐
- python random函数_详细代码实战讲解:如何用 Python让自己变成天选之子
今天为大家带来的内容是:详细代码讲解:如何用 Python让自己变成天选之子 话不多说直接上代码: 请大家猜一猜下面这段代码的运行效果: 你是不是以为这段代码运行以后,结果如下图所示? 但实际上,我可 ...
- OpenCV中响应鼠标信息cvSetMouseCallback函数的使用
转自:http://blog.csdn.net/haihong84/article/details/6599838 程序代碼如下: #include <cv.h> #include < ...
- 用标准C语言初始化线性表,跪求:线性表初始化函数的详细解释(c语言)
满意答案 shenytom 2013.11.30 采纳率:51% 等级:12 已帮助:126万人 函数中不会修改main()函数中定义的变量,修改如下: //------------------ ...
- 利用python数据分析,获取双色球历史中奖信息!(内含详细代码)
前言: 毫无例外,基本上是所有人都有一颗中奖的心,不管是有钱的,还是没钱的!你们说对吗? 对于技术人员来说,通过技术分析,可以增加中奖几率,现使用python语言收集历史双色球中奖信息,之后进行预测分 ...
- OpenCV 学习资料分享:中文、图文、代码注释并茂,建议收藏
最近在学习 OpenCV 的过程中发现了很不错的学习资料,分享给你. 我是优先看官方英文版: OpenCV-Python-Tutorial-英文版[1] 如果看不懂,就会通过翻译软件,或者看看对应的中 ...
- 利用OpenCV的级联分类器类CascadeClassifier和Haar特征实现人脸区域的检测
级联分类器是将若干个分类器进行连接,从而构成一种多项式级的强分类器.级联分类器使用前要先进行训练,怎么训练呢?用目标的特征值去训练,对于人脸来说,通常使用Haar特征进行训练. Haar特征是由M.O ...
- 【pytorch 】nn.init 中实现的初始化函数 normal, Xavier==》为了保证数据的分布(均值方差一致)是一样的,类似BN
为什么要输入和输出的方差相同?有利于信息的传递 为了使得网络中信息更好的流动,每一层输出的方差应该尽量相等.在考虑线性激活函数的情况下, 在初始化的时候使各层神经元的方差保持不变, 即使各层有着相同的 ...
- Python+OpenCV:级联分类器(Cascade Classifier)
Python+OpenCV:级联分类器(Cascade Classifier) 目标 We will learn how the Haar cascade object detection works ...
- 字符串查找函数和错误信息报告函数
前言: 本博客介绍了字符串查找函数(strstr.strtok)和错误信息报告函数(strerror) 字符串查找函数(strstr.strtok)的介绍及其应用: strstr函数的介绍及其模拟实现 ...
- 基于OpenCV自带分类器识别人脸
基于OpenCV自带分类器识别人脸 在VS2019下要安装适用于桌面的VC++ 2015(2017) v14 00(v14)工具集. 访问网站:https://visualstudio.microso ...
最新文章
- PyTorch基础-使用LSTM神经网络实现手写数据集识别-08
- 模态对话框和非模态对话框的消息循环分析
- Python 进程互斥锁 Lock - Python零基础入门教程
- 寄存器(内存访问)07 - 零基础入门学习汇编语言19
- 推荐系统经典模型 Wide Deep 论文剖析
- selenium ie 模拟request pahonjs
- Windows Driver开发_NT Driver框架:The driver is not in a state to accept this command
- mysql备份恢复中的常见错误
- ldconfig清理缓存
- php兼容net的md5,解决c# md5与php md5加密不一致的问题(md5(unicode))
- 【资源】About Face4交互设计精髓,英文原版,彩色pdf下载
- 网吧游戏服务器制作教程,网吧服务器系统环境部署
- 光纤通道网络FC vs 以太网光纤通道FCoE
- Java的中文转换拼音、五笔简码
- 服务器CPU经常跑高是什么原因
- 帝国cms ajax,jquery.ajax制作帝国cms6.6快速登录插件
- 本科生掀起“科研热”?该校本科生连发SCI,其中2篇顶刊
- luogu4182 [USACO18JAN] Lifeguards P (单调队列优化dp)
- 功能性需求和非功能性需求
- GYM 100827 A.Runes(水~)
热门文章
- synchronized中重量级锁、偏向锁和轻量级锁的区别
- TDAE:Hallucinating Very Low-Resolution Unaligned and Noisy Face Images by T
- 决策树之随机森林和GBDT
- DBSCAN聚类算法C++实现
- MapReduce如何使用多路输出
- 【生信进阶练习1000days】day11day12-GEO data mining
- MATLAB dsolve 函数求解偏微分方程一例
- 【ide】myeclipse项目右键没有configure
- linux开机进入不了系统安装软件,揭秘linux系统启动流程,面试官问起来再也不怕了...
- 使用MVC2模式创建新闻网站