微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

cascade.xml参数解析

转载自: http://blog.csdn.net/wuxiaoyao12/article/details/48088999

上图显示的参数,大多与opencv_traincascade.exe的输入参数已知。其中maxCatCount和featSize定义如下

maxCatCount:int maxCatCount; // 0 in case of numerical features
featSize:int featSize; // 1 in case of simple features (HAAR,LBP) and N_BINS(9)*N_CELLS(4) in case of Dalal's HOG features

feature结构对于上两值认的是:

CvFeatureParams::CvFeatureParams() : maxCatCount( 0 ),featSize( 1 ) {...};

其中

LBP:maxCatCount = 256;

HOG:featSize = N_BINS * N_CELLS;

其他情况均用认值。


关于maxWeakCountstageThresholdweakClassifiers,如下:

  1. voidCvCascadeBoost::write(FileStorage&fs,constMat&featureMap)const
  2. {
  3. CvCascadeBoostTree*weakTree;
  4. fs<<CC_WEAK_COUNT<<weak->total;//弱分类器总数
  5. fs<<CC_STAGE_THRESHOLD<<threshold;//见后续补充
  6. fs<<CC_WEAK_CLASSIFIERS<<"[";
  7. for(intwi=0;wi<weak->total;wi++)
  8. {
  9. weakTree=*((CvCascadeBoostTree**)cvGetSeqElem(weak,wi));
  10. weakTree->write(fs,featureMap);
  11. }
  12. fs<<"]";
  13. }
关于weakClassifiers的internalNodesleafValues参数,如下:
  1. voidCvCascadeBoostTree::write(FileStorage&fs,constMat&featureMap)
  2. {
  3. intmaxCatCount=((CvCascadeBoostTrainData*)data)->featureEvaluator->getMaxCatCount();
  4. intsubsetN=(maxCatCount+31)/32;
  5. queue<CvDTreeNode*>internalNodesQueue;
  6. intsize=(int)pow(2.f,(float)ensemble->get_params().max_depth);
  7. Ptr<float>leafVals=newfloat[size];
  8. intleafValIdx=0;
  9. intinternalNodeIdx=1;
  10. CvDTreeNode*tempNode;
  11. CV_DbgAssert(root);
  12. internalNodesQueue.push(root);
  13. fs<<"{";
  14. fs<<CC_INTERNAL_NODES<<"[:";
  15. while(!internalNodesQueue.empty())
  16. {
  17. tempNode=internalNodesQueue.front();
  18. CV_Assert(tempNode->left);//左分支存在
  19. if(!tempNode->left->left&&!tempNode->left->right)//leftnodeisleaf左分支是叶子节点
  20. {
  21. leafVals[-leafValIdx]=(float)tempNode->left->value;
  22. fs<<leafValIdx--;//0-1-2...
  23. }
  24. else//左分支不是叶子节点
  25. {
  26. internalNodesQueue.push(tempNode->left);
  27. fs<<internalNodeIdx++;//123...
  28. }
  29. CV_Assert(tempNode->right);//右分支存在
  30. if(!tempNode->right->left&&!tempNode->right->right)//rightnodeisleaf右分支是叶子节点
  31. {
  32. leafVals[-leafValIdx]=(float)tempNode->right->value;
  33. fs<<leafValIdx--;//0,-1,-2...
  34. }
  35. else//右分支不是叶子节点
  36. {
  37. internalNodesQueue.push(tempNode->right);
  38. fs<<internalNodeIdx++;//123...
  39. }
  40. intfidx=tempNode->split->var_idx;//var_idx:分裂中所用到的变量的索引
  41. fidx=featureMap.empty()?fidx:featureMap.at<int>(0,fidx);
  42. fs<<fidx;
  43. if(!maxCatCount)
  44. fs<<tempNode->split->ord.c;//c:用在数值变量的分裂上的阈值。规则如下:如果var_value<c,那么next_node<-left,否则next_node<-right。
  45. else
  46. for(inti=0;i<subsetN;i++)
  47. fs<<tempNode->split->subset[i];//subset:二值集合,用在在类别向量的分裂上。规则如下:如果var_value在subset里,那么next_node<-left,否则next_node<-right。
  48. internalNodesQueue.pop();
  49. }
  50. fs<<"]";//CC_INTERNAL_NODES
  51. fs<<CC_LEAF_VALUES<<"[:";
  52. for(intni=0;ni<-leafValIdx;ni++)
  53. fs<<leafVals[ni];//即从上面得到的节点value
  54. fs<<"]";//CC_LEAF_VALUES
  55. fs<<"}";
  56. }
:internalNodes中四个变量代表一个node,分别为node中的left/right标记、特征池中的ID和threshold。leafValues中两个变量代表一个node,分别为left leaf的值和right leaf的值。

补充threshold

  1. inti,count=data->sample_count,nz_count=0;
  2. doublesum,threshold;
  3. if(params.weight_trim_rate<=0.||params.weight_trim_rate>=1.)
  4. EXIT;
  5. //useweak_evalastemporarybufferforsortedweights
  6. cvcopy(weights,weak_eval);
  7. icvSort_64f(weak_eval->data.db,count,0);
  8. //asweighttrimming(调整)occursimmediatelyafterupdatingtheweights,
  9. //wheretheyarerenormalized,weassumethattheweightsum=1.
  10. sum=1.-params.weight_trim_rate;
  11. for(i=0;i<count;i++)
  12. {
  13. doublew=weak_eval->data.db[i];
  14. if(sum<=0)
  15. break;
  16. sum-=w;
  17. }
  18. threshold=i<count?weak_eval->data.db[i]:DBL_MAX;


关于features

  1. void_writeFeatures(conststd::vector<Feature>features,cv::FileStorage&fs,constcv::Mat&featureMap)
  2. {
  3. fs<<FEATURES<<"[";
  4. constcv::Mat_<int>&featureMap_=(constcv::Mat_<int>&)featureMap;
  5. for(intfi=0;fi<featureMap.cols;fi++)//个数即featureMap.cols
  6. if(featureMap_(0,fi)>=0)
  7. {
  8. fs<<"{";
  9. features[fi].write(fs);
  10. fs<<"}";
  11. }
  12. fs<<"]";
  13. }
其中的rects
  1. voidCvHaarEvaluator::Feature::write(FileStorage&fs)const
  2. {
  3. fs<<CC_RECTS<<"[";
  4. for(intri=0;ri<CV_HAAR_FEATURE_MAX&&rect[ri].r.width!=0;++ri)//CV_HAAR_FEATURE_MAX=3,上图就表示了我们只用了一个特征
  5. {
  6. fs<<"[:"<<rect[ri].r.x<<rect[ri].r.y<<
  7. rect[ri].r.width<<rect[ri].r.height<<rect[ri].weight<<"]";
  8. }
  9. fs<<"]"<<CC_TILTED<<tilted;//bool型
  10. }
说明:opencv learning书中有提到(550页),我们使用1个特征(一个只有一个分裂的树),最多3个。

类haar特征的tilted取法如下(包括特征计算)

  1. voidCvHaarEvaluator::generateFeatures()
  2. {
  3. intmode=((constCvHaarFeatureParams*)((CvFeatureParams*)featureParams))->mode;
  4. intoffset=winSize.width+1;
  5. for(intx=0;x<winSize.width;x++)
  6. {
  7. for(inty=0;y<winSize.height;y++)
  8. {
  9. for(intdx=1;dx<=winSize.width;dx++)
  10. {
  11. for(intdy=1;dy<=winSize.height;dy++)
  12. {
  13. //haar_x2
  14. if((x+dx*2<=winSize.width)&&(y+dy<=winSize.height))
  15. {
  16. features.push_back(Feature(offset,false,x,y,dx*2,dy,//开始tilted都是false
  17. x+dx,dx,+2));
  18. }
  19. //haar_y2
  20. if((x+dx<=winSize.width)&&(y+dy*2<=winSize.height))
  21. {
  22. features.push_back(Feature(offset,
  23. x,dy*2,
  24. x,y+dy,+2));
  25. }
  26. //haar_x3
  27. if((x+dx*3<=winSize.width)&&(y+dy<=winSize.height))
  28. {
  29. features.push_back(Feature(offset,
  30. x,dx*3,
  31. x+dx,+3));
  32. }
  33. //haar_y3
  34. if((x+dx<=winSize.width)&&(y+dy*3<=winSize.height))
  35. {
  36. features.push_back(Feature(offset,dy*3,+3));
  37. }
  38. if(mode!=CvHaarFeatureParams::BASIC)
  39. {
  40. //haar_x4
  41. if((x+dx*4<=winSize.width)&&(y+dy<=winSize.height))
  42. {
  43. features.push_back(Feature(offset,dx*4,+2));
  44. }
  45. //haar_y4
  46. if((x+dx<=winSize.width)&&(y+dy*4<=winSize.height))
  47. {
  48. features.push_back(Feature(offset,dy*4,+2));
  49. }
  50. }
  51. //x2_y2
  52. if((x+dx*2<=winSize.width)&&(y+dy*2<=winSize.height))
  53. {
  54. features.push_back(Feature(offset,+2,+2));
  55. }
  56. if(mode!=CvHaarFeatureParams::BASIC)
  57. {
  58. if((x+dx*3<=winSize.width)&&(y+dy*3<=winSize.height))
  59. {
  60. features.push_back(Feature(offset,+9));
  61. }
  62. }
  63. if(mode==CvHaarFeatureParams::ALL)
  64. {
  65. //tiltedhaar_x2
  66. if((x+2*dx<=winSize.width)&&(y+2*dx+dy<=winSize.height)&&(x-dy>=0))
  67. {
  68. features.push_back(Feature(offset,true,//这里开始tilted是true
  69. x,
  70. x,+2));
  71. }
  72. //tiltedhaar_y2
  73. if((x+dx<=winSize.width)&&(y+dx+2*dy<=winSize.height)&&(x-2*dy>=0))
  74. {
  75. features.push_back(Feature(offset,2*dy,+2));
  76. }
  77. //tiltedhaar_x3
  78. if((x+3*dx<=winSize.width)&&(y+3*dx+dy<=winSize.height)&&(x-dy>=0))
  79. {
  80. features.push_back(Feature(offset,y+dx,+3));
  81. }
  82. //tiltedhaar_y3
  83. if((x+dx<=winSize.width)&&(y+dx+3*dy<=winSize.height)&&(x-3*dy>=0))
  84. {
  85. features.push_back(Feature(offset,3*dy,
  86. x-dy,+3));
  87. }
  88. //tiltedhaar_x4
  89. if((x+4*dx<=winSize.width)&&(y+4*dx+dy<=winSize.height)&&(x-dy>=0))
  90. {
  91. features.push_back(Feature(offset,+2));
  92. }
  93. //tiltedhaar_y4
  94. if((x+dx<=winSize.width)&&(y+dx+4*dy<=winSize.height)&&(x-4*dy>=0))
  95. {
  96. features.push_back(Feature(offset,4*dy,+2));
  97. }
  98. }
  99. }
  100. }
  101. }
  102. }
  103. numFeatures=(int)features.size();
  104. }
其中的Feature构造如下:
  1. CvHaarEvaluator::Feature::Feature(intoffset,bool_tilted,
  2. intx0,inty0,intw0,inth0,floatwt0,
  3. intx1,inty1,intw1,inth1,floatwt1,
  4. intx2,inty2,intw2,inth2,floatwt2)
  5. {
  6. tilted=_tilted;
  7. rect[0].r.x=x0;
  8. rect[0].r.y=y0;
  9. rect[0].r.width=w0;
  10. rect[0].r.height=h0;
  11. rect[0].weight=wt0;
  12. rect[1].r.x=x1;
  13. rect[1].r.y=y1;
  14. rect[1].r.width=w1;
  15. rect[1].r.height=h1;
  16. rect[1].weight=wt1;
  17. rect[2].r.x=x2;
  18. rect[2].r.y=y2;
  19. rect[2].r.width=w2;
  20. rect[2].r.height=h2;
  21. rect[2].weight=wt2;
  22. if(!tilted)
  23. {
  24. for(intj=0;j<CV_HAAR_FEATURE_MAX;j++)
  25. {
  26. if(rect[j].weight==0.0F)
  27. break;
  28. CV_SUM_OFFSETS(fastRect[j].p0,fastRect[j].p1,fastRect[j].p2,fastRect[j].p3,rect[j].r,offset)
  29. }
  30. }
  31. else
  32. {
  33. for(intj=0;j<CV_HAAR_FEATURE_MAX;j++)
  34. {
  35. if(rect[j].weight==0.0F)
  36. break;
  37. CV_TILTED_OFFSETS(fastRect[j].p0,offset)
  38. }
  39. }
  40. }

另外,是不是觉得参数输入与输出不配,其实如下:(人家是有认输入的)

  1. Feature(intoffset,
  2. intx2=0,inty2=0,intw2=0,inth2=0,floatwt2=0.0F);
其中的CV_SUM_OFFSETSCV_TILTED_OFFSETS如下:
  1. #defineCV_SUM_OFFSETS(p0,p1,p2,p3,rect,step)\
  2. /*(x,y)*/\
  3. (p0)=(rect).x+(step)*(rect).y;\
  4. /*(x+w,y)*/\
  5. (p1)=(rect).x+(rect).width+(step)*(rect).y;\
  6. /*(x,y+h)*/\
  7. (p2)=(rect).x+(step)*((rect).y+(rect).height);\
  8. /*(x+w,y+h)*/\
  9. (p3)=(rect).x+(rect).width+(step)*((rect).y+(rect).height);
  10. #defineCV_TILTED_OFFSETS(p0,y)*/\
  11. (p0)=(rect).x+(step)*(rect).y;\
  12. /*(x-h,y+h)*/\
  13. (p1)=(rect).x-(rect).height+(step)*((rect).y+(rect).height);\
  14. /*(x+w,y+w)*/\
  15. (p2)=(rect).x+(rect).width+(step)*((rect).y+(rect).width);\
  16. /*(x+w-h,y+w+h)*/\
  17. (p3)=(rect).x+(rect).width-(rect).height\
  18. +(step)*((rect).y+(rect).width+(rect).height);

Feature类组成如下:

  1. classFeature
  2. {
  3. public:
  4. Feature();
  5. Feature(intoffset,floatwt2=0.0F);
  6. floatcalc(constcv::Mat&sum,constcv::Mat&tilted,size_ty)const;
  7. voidwrite(cv::FileStorage&fs)const;
  8. booltilted;
  9. struct
  10. {
  11. cv::Rectr;
  12. floatweight;
  13. }rect[CV_HAAR_FEATURE_MAX];
  14. struct
  15. {
  16. intp0,p3;
  17. }fastRect[CV_HAAR_FEATURE_MAX];
  18. };
  1. inlinefloatCvHaarEvaluator::operator()(intfeatureIdx,intsampleIdx)const
  2. {
  3. floatnf=normfactor.at<float>(0,sampleIdx);
  4. return!nf?0.0f:(features[featureIdx].calc(sum,tilted,sampleIdx)/nf);
  5. }
  6. inlinefloatCvHaarEvaluator::Feature::calc(constcv::Mat&_sum,constcv::Mat&_tilted,size_ty)const
  7. {
  8. constint*img=tilted?_tilted.ptr<int>((int)y):_sum.ptr<int>((int)y);
  9. floatret=rect[0].weight*(img[fastRect[0].p0]-img[fastRect[0].p1]-img[fastRect[0].p2]+img[fastRect[0].p3])+
  10. rect[1].weight*(img[fastRect[1].p0]-img[fastRect[1].p1]-img[fastRect[1].p2]+img[fastRect[1].p3]);
  11. if(rect[2].weight!=0.0f)
  12. ret+=rect[2].weight*(img[fastRect[2].p0]-img[fastRect[2].p1]-img[fastRect[2].p2]+img[fastRect[2].p3]);
  13. returnret;
  14. }



补充

HOG计算:

  1. voidCvHOGEvaluator::generateFeatures()
  2. {
  3. intoffset=winSize.width+1;
  4. SizeblockStep;
  5. intx,t,w,h;
  6. for(t=8;t<=winSize.width/2;t+=8)//t=sizeofacell.blocksize=4*cellSize
  7. {
  8. blockStep=Size(4,4);
  9. w=2*t;//widthofablock
  10. h=2*t;//heightofablock
  11. for(x=0;x<=winSize.width-w;x+=blockStep.width)
  12. {
  13. for(y=0;y<=winSize.height-h;y+=blockStep.height)
  14. {
  15. features.push_back(Feature(offset,t));
  16. }
  17. }
  18. w=2*t;
  19. h=4*t;
  20. for(x=0;x<=winSize.width-w;x+=blockStep.width)
  21. {
  22. for(y=0;y<=winSize.height-h;y+=blockStep.height)
  23. {
  24. features.push_back(Feature(offset,2*t));
  25. }
  26. }
  27. w=4*t;
  28. h=2*t;
  29. for(x=0;x<=winSize.width-w;x+=blockStep.width)
  30. {
  31. for(y=0;y<=winSize.height-h;y+=blockStep.height)
  32. {
  33. features.push_back(Feature(offset,2*t,t));
  34. }
  35. }
  36. }
  37. numFeatures=(int)features.size();
  38. }
  1. CvHOGEvaluator::Feature::Feature(intoffset,intx,inty,intcellW,intcellH)
  2. {
  3. rect[0]=Rect(x,cellW,cellH);//cell0
  4. rect[1]=Rect(x+cellW,cellH);//cell1
  5. rect[2]=Rect(x,y+cellH,cellH);//cell2
  6. rect[3]=Rect(x+cellW,cellH);//cell3
  7. for(inti=0;i<N_CELLS;i++)
  8. {
  9. CV_SUM_OFFSETS(fastRect[i].p0,fastRect[i].p1,fastRect[i].p2,fastRect[i].p3,rect[i],offset);
  10. }
  11. }
LBP计算:
  1. voidCvLBPEvaluator::generateFeatures()
  2. {
  3. intoffset=winSize.width+1;
  4. for(intx=0;x<winSize.width;x++)
  5. for(inty=0;y<winSize.height;y++)
  6. for(intw=1;w<=winSize.width/3;w++)
  7. for(inth=1;h<=winSize.height/3;h++)
  8. if((x+3*w<=winSize.width)&&(y+3*h<=winSize.height))
  9. features.push_back(Feature(offset,h));
  10. numFeatures=(int)features.size();
  11. }
  1. CvLBPEvaluator::Feature::Feature(intoffset,int_blockWidth,int_blockHeight)
  2. {
  3. Recttr=rect=cvRect(x,_blockWidth,_blockHeight);
  4. CV_SUM_OFFSETS(p[0],p[1],p[4],p[5],tr,offset)
  5. tr.x+=2*rect.width;
  6. CV_SUM_OFFSETS(p[2],p[3],p[6],p[7],offset)
  7. tr.y+=2*rect.height;
  8. CV_SUM_OFFSETS(p[10],p[11],p[14],p[15],offset)
  9. tr.x-=2*rect.width;
  10. CV_SUM_OFFSETS(p[8],p[9],p[12],p[13],offset)
  11. }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。