使用OpenCV作图像检测, Adaboost+haar决策过程,其中一部分源代码如下:

函数调用堆栈的底层为:

1、使用有序决策桩进行预测

template<class FEval>
inline int predictOrderedStump( CascadeClassifier& cascade, Ptr<FeatureEvaluator> &_featureEvaluator, double& sum )
{int nodeOfs = 0, leafOfs = 0;FEval& featureEvaluator = (FEval&)*_featureEvaluator;float* cascadeLeaves = &cascade.data.leaves[0];CascadeClassifier::Data::DTreeNode* cascadeNodes = &cascade.data.nodes[0];CascadeClassifier::Data::Stage* cascadeStages = &cascade.data.stages[0];//每一层进行计算,第一次训练为19层 nstages=19//int nstages = (int)cascade.data.stages.size();for( int stageIdx = 0; stageIdx < nstages; stageIdx++ ){CascadeClassifier::Data::Stage& stage = cascadeStages[stageIdx];sum = 0.0;//每一层树的个数int ntrees = stage.ntrees;for( int i = 0; i < ntrees; i++, nodeOfs++, leafOfs+= 2 ){CascadeClassifier::Data::DTreeNode& node = cascadeNodes[nodeOfs];//收集累积和//没有显示否定的特性?double value = featureEvaluator(node.featureIdx);sum += cascadeLeaves[ value < node.threshold ? leafOfs : leafOfs + 1 ];}if( sum < stage.threshold )return -stageIdx;}return 1;
}

2.上层调用:在某个点之处进行计算

int CascadeClassifier::runAt( Ptr<FeatureEvaluator>& evaluator, Point pt, double& weight )
{CV_Assert( oldCascade.empty() );assert( data.featureType == FeatureEvaluator::HAAR ||data.featureType == FeatureEvaluator::LBP ||data.featureType == FeatureEvaluator::HOG );if( !evaluator->setWindow(pt) )return -1;if( data.isStumpBased ){//若使用haar特征,则进行haar检测过程 wishchin if( data.featureType == FeatureEvaluator::HAAR )return predictOrderedStump<HaarEvaluator>( *this, evaluator, weight );else if( data.featureType == FeatureEvaluator::LBP )return predictCategoricalStump<LBPEvaluator>( *this, evaluator, weight );else if( data.featureType == FeatureEvaluator::HOG )return predictOrderedStump<HOGEvaluator>( *this, evaluator, weight );elsereturn -2;}else{if( data.featureType == FeatureEvaluator::HAAR )return predictOrdered<HaarEvaluator>( *this, evaluator, weight );else if( data.featureType == FeatureEvaluator::LBP )return predictCategorical<LBPEvaluator>( *this, evaluator, weight );else if( data.featureType == FeatureEvaluator::HOG )return predictOrdered<HOGEvaluator>( *this, evaluator, weight );elsereturn -2;}
}

3. CascadeClassifierInvoker初始化时产生的 CascadeClassifier,

其中 每个inVoker继承于并行循环的body:例如 class CascadeClassifier : public ParallelLoopBody,完成并行计算过程

其初始化过程,完成检测。

    void operator()(const Range& range) const{Ptr<FeatureEvaluator> evaluator = classifier->featureEvaluator->clone();Size winSize(cvRound(classifier->data.origWinSize.width * scalingFactor), cvRound(classifier->data.origWinSize.height * scalingFactor));int y1 = range.start * stripSize;int y2 = min(range.end * stripSize, processingRectSize.height);for( int y = y1; y < y2; y += yStep ){for( int x = 0; x < processingRectSize.width; x += yStep ){if ( (!mask.empty()) && (mask.at<uchar>(Point(x,y))==0)) {continue;}double gypWeight;//作为起始点检测图像是否为目标!!! wishchin 2017 03 20int result = classifier->runAt(evaluator, Point(x, y), gypWeight);#if defined (LOG_CASCADE_STATISTIC)logger.setPoint(Point(x, y), result);
#endifif( rejectLevels ){if( result == 1 )result =  -(int)classifier->data.stages.size();if( classifier->data.stages.size() + result < 4 ){mtx->lock();rectangles->push_back(Rect(cvRound(x*scalingFactor), cvRound(y*scalingFactor), winSize.width, winSize.height));rejectLevels->push_back(-result);levelWeights->push_back(gypWeight);mtx->unlock();}}else if( result > 0 ){mtx->lock();rectangles->push_back(Rect(cvRound(x*scalingFactor), cvRound(y*scalingFactor),winSize.width, winSize.height));mtx->unlock();}if( result == 0 )x += yStep;}}}CascadeClassifier* classifier;vector<Rect>* rectangles;Size processingRectSize;int stripSize, yStep;double scalingFactor;vector<int> *rejectLevels;vector<double> *levelWeights;Mat mask;Mutex* mtx;
};

4.使用多尺度计算过程,对每一层进行单层结果计算

bool CascadeClassifier::detectSingleScale( const Mat& image, int stripCount, Size processingRectSize,int stripSize, int yStep, double factor, vector<Rect>& candidates,vector<int>& levels, vector<double>& weights, bool outputRejectLevels )
{if( !featureEvaluator->setImage( image, data.origWinSize ) )return false;#if defined (LOG_CASCADE_STATISTIC)logger.setImage(image);
#endifMat currentMask;if (!maskGenerator.empty()) {currentMask=maskGenerator->generateMask(image);}vector<Rect> candidatesVector;vector<int>      rejectLevels;vector<double>   levelWeights;Mutex mtx;if( outputRejectLevels ){parallel_for_(Range(0, stripCount), CascadeClassifierInvoker( *this, processingRectSize, stripSize, yStep, factor,candidatesVector, rejectLevels, levelWeights, true, currentMask, &mtx));levels.insert( levels.end(), rejectLevels.begin(), rejectLevels.end() );weights.insert( weights.end(), levelWeights.begin(), levelWeights.end() );}else{//并行处理过程,对每一层初始化一个CascadeClassifierInvoker,完成计算parallel_for_(Range(0, stripCount), CascadeClassifierInvoker( *this, processingRectSize, stripSize, yStep, factor,candidatesVector, rejectLevels, levelWeights, false, currentMask, &mtx));}candidates.insert( candidates.end(), candidatesVector.begin(), candidatesVector.end() );#if defined (LOG_CASCADE_STATISTIC)logger.write();
#endifreturn true;
}

5. 进行多尺度检测

void CascadeClassifier::detectMultiScale( const Mat& image, vector<Rect>& objects,vector<int>& rejectLevels,vector<double>& levelWeights,double scaleFactor, int minNeighbors,int flags, Size minObjectSize, Size maxObjectSize,bool outputRejectLevels )
{const double GROUP_EPS = 0.2;CV_Assert( scaleFactor > 1 && image.depth() == CV_8U );if( empty() )return;if( isOldFormatCascade() ){MemStorage storage(cvCreateMemStorage(0));CvMat _image = image;CvSeq* _objects = cvHaarDetectObjectsForROC( &_image, oldCascade, storage, rejectLevels, levelWeights, scaleFactor,minNeighbors, flags, minObjectSize, maxObjectSize, outputRejectLevels );vector<CvAvgComp> vecAvgComp;Seq<CvAvgComp>(_objects).copyTo(vecAvgComp);objects.resize(vecAvgComp.size());std::transform(vecAvgComp.begin(), vecAvgComp.end(), objects.begin(), getRect());return;}objects.clear();if (!maskGenerator.empty()) {maskGenerator->initializeMask(image);}if( maxObjectSize.height == 0 || maxObjectSize.width == 0 )maxObjectSize = image.size();Mat grayImage = image;if( grayImage.channels() > 1 ){Mat temp;cvtColor(grayImage, temp, CV_BGR2GRAY);grayImage = temp;}Mat imageBuffer(image.rows + 1, image.cols + 1, CV_8U);vector<Rect> candidates;for( double factor = 1; ; factor *= scaleFactor ){Size originalWindowSize = getOriginalWindowSize();Size windowSize( cvRound(originalWindowSize.width*factor), cvRound(originalWindowSize.height*factor) );Size scaledImageSize( cvRound( grayImage.cols/factor ), cvRound( grayImage.rows/factor ) );Size processingRectSize( scaledImageSize.width - originalWindowSize.width, scaledImageSize.height - originalWindowSize.height );if( processingRectSize.width <= 0 || processingRectSize.height <= 0 )break;if( windowSize.width > maxObjectSize.width || windowSize.height > maxObjectSize.height )break;if( windowSize.width < minObjectSize.width || windowSize.height < minObjectSize.height )continue;Mat scaledImage( scaledImageSize, CV_8U, imageBuffer.data );resize( grayImage, scaledImage, scaledImageSize, 0, 0, CV_INTER_LINEAR );int yStep;if( getFeatureType() == cv::FeatureEvaluator::HOG ){yStep = 4;}else{yStep = factor > 2. ? 1 : 2;}int stripCount, stripSize;const int PTS_PER_THREAD = 1000;stripCount = ((processingRectSize.width/yStep)*(processingRectSize.height + yStep-1)/yStep + PTS_PER_THREAD/2)/PTS_PER_THREAD;stripCount = std::min(std::max(stripCount, 1), 100);stripSize = (((processingRectSize.height + stripCount - 1)/stripCount + yStep-1)/yStep)*yStep;//对每一个尺度进行目标检测 wishchin 2017 03 21 if( !detectSingleScale( scaledImage, stripCount, processingRectSize, stripSize, yStep, factor, candidates,rejectLevels, levelWeights, outputRejectLevels ) )break;}objects.resize(candidates.size());std::copy(candidates.begin(), candidates.end(), objects.begin());if( outputRejectLevels ){groupRectangles( objects, rejectLevels, levelWeights, minNeighbors, GROUP_EPS );}else{groupRectangles( objects, minNeighbors, GROUP_EPS );}
}

以上为objectDetect过程的OpenCV的源代码,外层调用的使用函数接口可以为:

    // 人眼检测m_cascade.detectMultiScale(smallImg,eyes,fAdaBoostScale, // originally 1.1, 4 is faster 2, //minNeighbors//|CV_HAAR_FIND_BIGGEST_OBJECT//|CV_HAAR_DO_ROUGH_SEARCHCV_HAAR_DO_CANNY_PRUNING,Size(48, 32));//cout << "eyes size=:" << eyes.size() << endl;

总结:

上述过程即是Haar+Adaboost检测计算大致的函数调用堆栈。

OpenCV:OpenCV目标检测Adaboost+haar源代码分析相关推荐

  1. OpenCV:OpenCV目标检测Hog+SWindow源代码分析

    参考文章:OpenCV中的HOG+SVM物体分类 此文主要描述出HOG分类的调用堆栈. 使用OpenCV作图像检测, 使用HOG检测过程,其中一部分源代码如下: 1.HOG 检测底层栈的检测计算代码: ...

  2. 使用opencv训练目标检测模型基于cascade模型

    使用opencv训练目标检测模型基于cascade模型 基于Haar特征的cascade分类器(classifiers) 是Paul Viola和 Michael Jone在2001年,论文" ...

  3. python目标检测与识别_Python 使用Opencv实现目标检测与识别的示例代码

    在上章节讲述到图像特征检测与匹配 ,本章节是讲述目标检测与识别.后者是在前者的基础上进一步完善. 在本章中,我们使用HOG算法,HOG和SIFT.SURF同属一种类型的描述符.功能代码如下: impo ...

  4. python数据挖掘视频_python+opencv实时视频目标检测

    python+opencv实时视频目标检测 opencv环境 1.访问Python Extension Packages for Windows,下载python对应版本的opencv. 比如小编下载 ...

  5. pythonopencv目标检测_Python 使用Opencv实现目标检测与识别的示例代码

    本章节是讲述目标检测与识别.后者是在前者的基础上进一步完善. 在本章中,我们使用HOG算法,HOG和SIFT.SURF同属一种类型的描述符.功能代码如下: import cv2 def is_insi ...

  6. Interview:算法岗位面试—11.17下午上海某网**软件公司(上市)技术面之比赛考察、目标检测算法、视频分析算法考点

    Interview:算法岗位面试-11.17下午上海某网**软件公司(上市)技术面之比赛考察.目标检测算法.视频分析算法考点 导读:邀约的下午14.30,到的时候前边有两个学生在等待,当轮到我的时候, ...

  7. 【OpenCV】目标检测

      OpenCV支持的目标检测的方法是利用样本的Haar特征进行的分类器训练,得到的级联boosted分类器(Cascade Classification).haar支持的目标有人脸.眼.嘴.鼻.身体 ...

  8. 10分钟学会使用YOLO及Opencv实现目标检测

    点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转自:新机器视觉 计算机视觉领域中,目标检测一直是工业应用上比 ...

  9. python opencv输出mp4_10分钟学会使用YOLO及Opencv实现目标检测

    点击边框调出视频工具条 计算机视觉领域中,目标检测一直是工业应用上比较热门且成熟的应用领域,比如人脸识别.行人检测等,国内的旷视科技.商汤科技等公司在该领域占据行业领先地位.相对于图像分类任务而言,目 ...

最新文章

  1. C++ string字符串的比较是否相等
  2. js截屏 video_js获取video任意时间的画面截图
  3. [Sdoi2010]古代猪文
  4. 数据仓库专题(6)-数据仓库、主题域、主题概念与定义
  5. yarn的配置 -- 无法将“yo”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。
  6. 基于Taro开发小程序笔记--04路由跳转的几种方式
  7. Exp4恶意软件分析 20154326杨茜
  8. python基于大数据的招聘信息实时数据分析系统的设计与实现
  9. cocos2d-html5 仿微信打飞机游戏
  10. opencv实现靶纸弹孔识别计数功能
  11. 300句子与7000单词
  12. java npv_java 实现Excel irr计算(改进版)
  13. 负雪明烛开通公众号啦~ 欢迎关注「负雪明烛」
  14. mybatis type-aliases-package
  15. springboot+vue酒店电子商务平台
  16. 模型量化从1bit到8bit,二值到三值
  17. Linux学习(六):proftpd搭建,完美解决vsftpd中文引号bug
  18. 百度网盘漏洞,2019年不限速方法,一直享受高速加速下载!
  19. 在MFC中手动添加消息处理函数PreTranslateMessage
  20. HTTP请求错误 2xx 3xx 4xx 5xx

热门文章

  1. 面试题:谈谈你对hibernate的理解
  2. inode与ln命令
  3. 华为呼叫中心解决方案学习笔记一(方案概述)
  4. 20款Notepad++插件下载和介绍
  5. 从网游策划谈《梦幻西游》的成功之道
  6. Hacking techniques automation
  7. Java 基于 UDP 实现 Socket中的多客户端通信
  8. pycharm设置字体和背景色
  9. 小程序外接web-view坑------alert显示域名
  10. decode函数的使用