转载自: 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;
其他情况均用默认值。
关于maxWeakCount、stageThreshold和weakClassifiers,如下:
- voidCvCascadeBoost::write(FileStorage&fs,constMat&featureMap)const
- {
- CvCascadeBoostTree*weakTree;
- fs<<CC_WEAK_COUNT<<weak->total;
- fs<<CC_STAGE_THRESHOLD<<threshold;
- fs<<CC_WEAK_CLASSIFIERS<<"[";
- for(intwi=0;wi<weak->total;wi++)
- {
- weakTree=*((CvCascadeBoostTree**)cvGetSeqElem(weak,wi));
- weakTree->write(fs,featureMap);
- }
- fs<<"]";
- }
关于weakClassifiers的internalNodes和leafValues参数,如下:
- voidCvCascadeBoostTree::write(FileStorage&fs,constMat&featureMap)
- {
- intmaxCatCount=((CvCascadeBoostTrainData*)data)->featureEvaluator->getMaxCatCount();
- intsubsetN=(maxCatCount+31)/32;
- queue<CvDTreeNode*>internalNodesQueue;
- intsize=(int)pow(2.f,(float)ensemble->get_params().max_depth);
- Ptr<float>leafVals=newfloat[size];
- intleafValIdx=0;
- intinternalNodeIdx=1;
- CvDTreeNode*tempNode;
- CV_DbgAssert(root);
- internalNodesQueue.push(root);
- fs<<"{";
- fs<<CC_INTERNAL_NODES<<"[:";
- while(!internalNodesQueue.empty())
- {
- tempNode=internalNodesQueue.front();
- CV_Assert(tempNode->left);
- if(!tempNode->left->left&&!tempNode->left->right)
- {
- leafVals[-leafValIdx]=(float)tempNode->left->value;
- fs<<leafValIdx--;
- }
- else
- {
- internalNodesQueue.push(tempNode->left);
- fs<<internalNodeIdx++;
- }
- CV_Assert(tempNode->right);
- if(!tempNode->right->left&&!tempNode->right->right)
- {
- leafVals[-leafValIdx]=(float)tempNode->right->value;
- fs<<leafValIdx--;
- }
- else
- {
- internalNodesQueue.push(tempNode->right);
- fs<<internalNodeIdx++;
- }
- intfidx=tempNode->split->var_idx;
- fidx=featureMap.empty()?fidx:featureMap.at<int>(0,fidx);
- fs<<fidx;
- if(!maxCatCount)
- fs<<tempNode->split->ord.c;
- else
- for(inti=0;i<subsetN;i++)
- fs<<tempNode->split->subset[i];
- internalNodesQueue.pop();
- }
- fs<<"]";
- fs<<CC_LEAF_VALUES<<"[:";
- for(intni=0;ni<-leafValIdx;ni++)
- fs<<leafVals[ni];
- fs<<"]";
- fs<<"}";
- }
即:internalNodes中四个变量代表一个node,分别为node中的left/right标记、特征池中的ID和threshold。leafValues中两个变量代表一个node,分别为left leaf的值和right leaf的值。
补充threshold:
- inti,count=data->sample_count,nz_count=0;
- doublesum,threshold;
- if(params.weight_trim_rate<=0.||params.weight_trim_rate>=1.)
- EXIT;
- cvCopy(weights,weak_eval);
- icvSort_64f(weak_eval->data.db,count,0);
- sum=1.-params.weight_trim_rate;
- for(i=0;i<count;i++)
- {
- doublew=weak_eval->data.db[i];
- if(sum<=0)
- break;
- sum-=w;
- }
- threshold=i<count?weak_eval->data.db[i]:DBL_MAX;
关于features:
- void_writeFeatures(conststd::vector<Feature>features,cv::FileStorage&fs,constcv::Mat&featureMap)
- {
- fs<<FEATURES<<"[";
- constcv::Mat_<int>&featureMap_=(constcv::Mat_<int>&)featureMap;
- for(intfi=0;fi<featureMap.cols;fi++)
- if(featureMap_(0,fi)>=0)
- {
- fs<<"{";
- features[fi].write(fs);
- fs<<"}";
- }
- fs<<"]";
- }
其中的rects:
- voidCvHaarEvaluator::Feature::write(FileStorage&fs)const
- {
- fs<<CC_RECTS<<"[";
- for(intri=0;ri<CV_HAAR_FEATURE_MAX&&rect[ri].r.width!=0;++ri)
- {
- fs<<"[:"<<rect[ri].r.x<<rect[ri].r.y<<
- rect[ri].r.width<<rect[ri].r.height<<rect[ri].weight<<"]";
- }
- fs<<"]"<<CC_TILTED<<tilted;
- }
说明:opencv learning书中有提到(550页),我们使用1个特征(一个只有一个分裂的树),最多3个。
类haar特征的tilted取法如下(包括特征计算)
- voidCvHaarEvaluator::generateFeatures()
- {
- intmode=((constCvHaarFeatureParams*)((CvFeatureParams*)featureParams))->mode;
- intoffset=winSize.width+1;
- for(intx=0;x<winSize.width;x++)
- {
- for(inty=0;y<winSize.height;y++)
- {
- for(intdx=1;dx<=winSize.width;dx++)
- {
- for(intdy=1;dy<=winSize.height;dy++)
- {
- if((x+dx*2<=winSize.width)&&(y+dy<=winSize.height))
- {
- features.push_back(Feature(offset,false,x,y,dx*2,dy,
- x+dx,dx,+2));
- }
- if((x+dx<=winSize.width)&&(y+dy*2<=winSize.height))
- {
- features.push_back(Feature(offset,
- x,dy*2,
- x,y+dy,+2));
- }
- if((x+dx*3<=winSize.width)&&(y+dy<=winSize.height))
- {
- features.push_back(Feature(offset,
- x,dx*3,
- x+dx,+3));
- }
- if((x+dx<=winSize.width)&&(y+dy*3<=winSize.height))
- {
- features.push_back(Feature(offset,dy*3,+3));
- }
- if(mode!=CvHaarFeatureParams::BASIC)
- {
- if((x+dx*4<=winSize.width)&&(y+dy<=winSize.height))
- {
- features.push_back(Feature(offset,dx*4,+2));
- }
- if((x+dx<=winSize.width)&&(y+dy*4<=winSize.height))
- {
- features.push_back(Feature(offset,dy*4,+2));
- }
- }
- if((x+dx*2<=winSize.width)&&(y+dy*2<=winSize.height))
- {
- features.push_back(Feature(offset,+2,+2));
- }
- if(mode!=CvHaarFeatureParams::BASIC)
- {
- if((x+dx*3<=winSize.width)&&(y+dy*3<=winSize.height))
- {
- features.push_back(Feature(offset,+9));
- }
- }
- if(mode==CvHaarFeatureParams::ALL)
- {
- if((x+2*dx<=winSize.width)&&(y+2*dx+dy<=winSize.height)&&(x-dy>=0))
- {
- features.push_back(Feature(offset,true,
- x,
- x,+2));
- }
- if((x+dx<=winSize.width)&&(y+dx+2*dy<=winSize.height)&&(x-2*dy>=0))
- {
- features.push_back(Feature(offset,2*dy,+2));
- }
- if((x+3*dx<=winSize.width)&&(y+3*dx+dy<=winSize.height)&&(x-dy>=0))
- {
- features.push_back(Feature(offset,y+dx,+3));
- }
- if((x+dx<=winSize.width)&&(y+dx+3*dy<=winSize.height)&&(x-3*dy>=0))
- {
- features.push_back(Feature(offset,3*dy,
- x-dy,+3));
- }
- if((x+4*dx<=winSize.width)&&(y+4*dx+dy<=winSize.height)&&(x-dy>=0))
- {
- features.push_back(Feature(offset,+2));
- }
- if((x+dx<=winSize.width)&&(y+dx+4*dy<=winSize.height)&&(x-4*dy>=0))
- {
- features.push_back(Feature(offset,4*dy,+2));
- }
- }
- }
- }
- }
- }
- numFeatures=(int)features.size();
- }
其中的Feature构造如下:
- CvHaarEvaluator::Feature::Feature(intoffset,bool_tilted,
- intx0,inty0,intw0,inth0,floatwt0,
- intx1,inty1,intw1,inth1,floatwt1,
- intx2,inty2,intw2,inth2,floatwt2)
- {
- tilted=_tilted;
- rect[0].r.x=x0;
- rect[0].r.y=y0;
- rect[0].r.width=w0;
- rect[0].r.height=h0;
- rect[0].weight=wt0;
- rect[1].r.x=x1;
- rect[1].r.y=y1;
- rect[1].r.width=w1;
- rect[1].r.height=h1;
- rect[1].weight=wt1;
- rect[2].r.x=x2;
- rect[2].r.y=y2;
- rect[2].r.width=w2;
- rect[2].r.height=h2;
- rect[2].weight=wt2;
- if(!tilted)
- {
- for(intj=0;j<CV_HAAR_FEATURE_MAX;j++)
- {
- if(rect[j].weight==0.0F)
- break;
- CV_SUM_OFFSETS(fastRect[j].p0,fastRect[j].p1,fastRect[j].p2,fastRect[j].p3,rect[j].r,offset)
- }
- }
- else
- {
- for(intj=0;j<CV_HAAR_FEATURE_MAX;j++)
- {
- if(rect[j].weight==0.0F)
- break;
- CV_TILTED_OFFSETS(fastRect[j].p0,offset)
- }
- }
- }
另外,是不是觉得参数输入与输出不配,其实如下:(人家是有默认输入的)
- Feature(intoffset,
- intx2=0,inty2=0,intw2=0,inth2=0,floatwt2=0.0F);
其中的CV_SUM_OFFSETS和CV_TILTED_OFFSETS如下:
- #defineCV_SUM_OFFSETS(p0,p1,p2,p3,rect,step)
- (p0)=(rect).x+(step)*(rect).y;
- (p1)=(rect).x+(rect).width+(step)*(rect).y;
- (p2)=(rect).x+(step)*((rect).y+(rect).height);
- (p3)=(rect).x+(rect).width+(step)*((rect).y+(rect).height);
- #defineCV_TILTED_OFFSETS(p0,y)*/
- (p0)=(rect).x+(step)*(rect).y;
- (p1)=(rect).x-(rect).height+(step)*((rect).y+(rect).height);
- (p2)=(rect).x+(rect).width+(step)*((rect).y+(rect).width);
- (p3)=(rect).x+(rect).width-(rect).height
- +(step)*((rect).y+(rect).width+(rect).height);
Feature类组成如下:
- classFeature
- {
- public:
- Feature();
- Feature(intoffset,floatwt2=0.0F);
- floatcalc(constcv::Mat&sum,constcv::Mat&tilted,size_ty)const;
- voidwrite(cv::FileStorage&fs)const;
- booltilted;
- struct
- {
- cv::Rectr;
- floatweight;
- }rect[CV_HAAR_FEATURE_MAX];
- struct
- {
- intp0,p3;
- }fastRect[CV_HAAR_FEATURE_MAX];
- };
- inlinefloatCvHaarEvaluator::operator()(intfeatureIdx,intsampleIdx)const
- {
- floatnf=normfactor.at<float>(0,sampleIdx);
- return!nf?0.0f:(features[featureIdx].calc(sum,tilted,sampleIdx)/nf);
- }
- inlinefloatCvHaarEvaluator::Feature::calc(constcv::Mat&_sum,constcv::Mat&_tilted,size_ty)const
- {
- constint*img=tilted?_tilted.ptr<int>((int)y):_sum.ptr<int>((int)y);
- floatret=rect[0].weight*(img[fastRect[0].p0]-img[fastRect[0].p1]-img[fastRect[0].p2]+img[fastRect[0].p3])+
- rect[1].weight*(img[fastRect[1].p0]-img[fastRect[1].p1]-img[fastRect[1].p2]+img[fastRect[1].p3]);
- if(rect[2].weight!=0.0f)
- ret+=rect[2].weight*(img[fastRect[2].p0]-img[fastRect[2].p1]-img[fastRect[2].p2]+img[fastRect[2].p3]);
- returnret;
- }
补充
HOG计算:
- voidCvHOGEvaluator::generateFeatures()
- {
- intoffset=winSize.width+1;
- SizeblockStep;
- intx,t,w,h;
- for(t=8;t<=winSize.width/2;t+=8)
- {
- blockStep=Size(4,4);
- w=2*t;
- h=2*t;
- for(x=0;x<=winSize.width-w;x+=blockStep.width)
- {
- for(y=0;y<=winSize.height-h;y+=blockStep.height)
- {
- features.push_back(Feature(offset,t));
- }
- }
- w=2*t;
- h=4*t;
- for(x=0;x<=winSize.width-w;x+=blockStep.width)
- {
- for(y=0;y<=winSize.height-h;y+=blockStep.height)
- {
- features.push_back(Feature(offset,2*t));
- }
- }
- w=4*t;
- h=2*t;
- for(x=0;x<=winSize.width-w;x+=blockStep.width)
- {
- for(y=0;y<=winSize.height-h;y+=blockStep.height)
- {
- features.push_back(Feature(offset,2*t,t));
- }
- }
- }
- numFeatures=(int)features.size();
- }
- CvHOGEvaluator::Feature::Feature(intoffset,intx,inty,intcellW,intcellH)
- {
- rect[0]=Rect(x,cellW,cellH);
- rect[1]=Rect(x+cellW,cellH);
- rect[2]=Rect(x,y+cellH,cellH);
- rect[3]=Rect(x+cellW,cellH);
- for(inti=0;i<N_CELLS;i++)
- {
- CV_SUM_OFFSETS(fastRect[i].p0,fastRect[i].p1,fastRect[i].p2,fastRect[i].p3,rect[i],offset);
- }
- }
LBP计算:
- voidCvLBPEvaluator::generateFeatures()
- {
- intoffset=winSize.width+1;
- for(intx=0;x<winSize.width;x++)
- for(inty=0;y<winSize.height;y++)
- for(intw=1;w<=winSize.width/3;w++)
- for(inth=1;h<=winSize.height/3;h++)
- if((x+3*w<=winSize.width)&&(y+3*h<=winSize.height))
- features.push_back(Feature(offset,h));
- numFeatures=(int)features.size();
- }
- CvLBPEvaluator::Feature::Feature(intoffset,int_blockWidth,int_blockHeight)
- {
- Recttr=rect=cvRect(x,_blockWidth,_blockHeight);
- CV_SUM_OFFSETS(p[0],p[1],p[4],p[5],tr,offset)
- tr.x+=2*rect.width;
- CV_SUM_OFFSETS(p[2],p[3],p[6],p[7],offset)
- tr.y+=2*rect.height;
- CV_SUM_OFFSETS(p[10],p[11],p[14],p[15],offset)
- tr.x-=2*rect.width;
- CV_SUM_OFFSETS(p[8],p[9],p[12],p[13],offset)
- }
(编辑:李大同)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|