/* 检测函数 */ void POIDetecter::detectMultiScale( const Mat& image, vector<OutBlock>& objects, vector<int>& rejectLevels, vector<double>& levelWeights, double scaleFactor, int minNeighbors, Size minObjectSize, Size maxObjectSize, bool outputRejectLevels ) { const double GROUP_EPS = 0.2; CV_Assert( scaleFactor > 1 && image.depth() == CV_8U ); if( empty() ) return; objects.clear(); if( maxObjectSize.height == 0 || maxObjectSize.width == 0 ) { maxObjectSize.width = image.size().width/2; maxObjectSize.height = image.size().height/2; } Mat grayImage = image; if( grayImage.channels() > 1 ) { Mat temp; cvtColor(grayImage, temp, CV_BGR2GRAY); grayImage = temp; } std::map<int ,vector<CascadeClassifier> > scaleClassifiers; /* 不同分类器多个尺度 */ vector<Rect> candidates; map<int , vector<Rect> > hz_rect; double factor = 1; if(image.rows * image.cols < 1e6) { /* 100万像素一下的扩大一下 */ /* factor = 24/32*/ factor = 0.75; } Mat imageBuffer(image.rows/factor + 2, image.cols/factor + 2, CV_8U); /* 计算步长 */ int yStep = 4; double theFactor = scaleFactor; for( ; ; factor *= theFactor ) { //if(factor < 1.0) // theFactor = 1.17; // 0.625*1.17*1.17*1.17=1 //else // theFactor = scaleFactor; scaleClassifiers.clear(); Size scaledImageSize( cvRound( grayImage.cols/factor ), cvRound( grayImage.rows/factor ) ); /* 处理各个字符的分类器 */ for(std::map<int ,vector<CascadeClassifier> >::iterator it = classifierUsed.begin(); it != classifierUsed.end(); it++) { int keylabel = it->first; vector<CascadeClassifier> classifiers = it->second; for(size_t i =0; i < classifiers.size(); i++) { CascadeClassifier classifier = classifiers[i]; Size originalWindowSize = classifier.getOriginalWindowSize(); Size windowSize( cvRound(originalWindowSize.width*factor), cvRound(originalWindowSize.height*factor) ); Size processingRectSize( scaledImageSize.width - originalWindowSize.width, scaledImageSize.height - originalWindowSize.height ); if( processingRectSize.width <= 0 || processingRectSize.height <= 0 )/* 扩大后图像的尺寸小于分类器窗尺寸 */ continue; if( windowSize.width > maxObjectSize.width || windowSize.height > maxObjectSize.height ) continue; if( windowSize.width < minObjectSize.width && windowSize.height < minObjectSize.height )/* 最小尺寸的设置在多宽高比下要谨慎 */ continue; scaleClassifiers[keylabel].push_back(classifier); } } /* 改尺寸下不存在任何分类器 */ if(scaleClassifiers.empty()) { break; } /* 缩放图片 */ Mat scaledImage( scaledImageSize, CV_8U, imageBuffer.data ); resize( grayImage, scaledImage, scaledImageSize, 0, 0, CV_INTER_LINEAR ); int stripCount, stripSize; /* 得到haar所需要的积分图 */ int cn = scaledImageSize.width +1, rn = scaledImageSize.height+1; Mat sum_scale = Mat(rn, cn, CV_32S); Mat sqsum_scale = Mat(rn, cn, CV_64F); Mat tilted_scale = Mat(rn, cn, CV_32S); //integral(scaledImage, sum_scale, sqsum_scale, tilted_scale); //hog vector<Mat> hist_scale; hist_scale.clear(); for( int bin = 0; bin < HOGEvaluator::Feature::BIN_NUM; bin++ ) { hist_scale.push_back( Mat(rn, cn, CV_32FC1) ); } Mat normSum_scale; normSum_scale.create( rn, cn, CV_32FC1 ); integralHistogram( scaledImage, hist_scale, normSum_scale, HOGEvaluator::Feature::BIN_NUM ); const int PTS_PER_THREAD = 1000; //double t0 = (double)getTickCount(); //tt = 0.0; for(std::map<int ,vector<CascadeClassifier> >::iterator it = scaleClassifiers.begin(); it != scaleClassifiers.end(); it++) { int keylabel = it->first; vector<CascadeClassifier> classifiers = it->second; for(size_t i =0; i < classifiers.size(); i++) { CascadeClassifier classifier = classifiers[i]; Size originalWindowSize = classifier.getOriginalWindowSize(); Size processingRectSize( scaledImageSize.width - originalWindowSize.width, scaledImageSize.height - originalWindowSize.height ); /* 并行个数以及大小,按照列进行并行处理,确实是列 */ 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; /* 调用单尺度检测函数进行检测 */ /* yStep是步长,factor是因子 */ candidates.clear(); /* candidates是结果 */ if( !classifier.detectSingleScale( &sum_scale, &sqsum_scale, &tilted_scale, hist_scale, normSum_scale, scaledImage, stripCount, processingRectSize, stripSize, yStep, factor, candidates, rejectLevels, levelWeights, outputRejectLevels) ) continue; /* 返回的结果 */ for(size_t m=0; m< candidates.size(); m++) { hz_rect[keylabel].push_back(candidates[m]); } } } //double exec_time = ((double)getTickCount() - t0)/getTickFrequency(); //cout << "time: " << exec_time << endl; } //objects.resize(candidates.size()); //std::copy(candidates.begin(), candidates.end(), objects.begin()); /* 合并检测结果 */ for(map<int, vector<Rect> >::iterator it = hz_rect.begin(); it != hz_rect.end(); it++) { int key = it->first; //vector<Rect> key_vec = it->second; groupRectangles( it->second, minNeighbors, GROUP_EPS ); } for(map<int, vector<Rect> >::iterator it = hz_rect.begin(); it != hz_rect.end(); it++) { int key = it->first; string hz; getWord(key, hz); vector<Rect> key_vec = it->second; for(size_t m = 0; m< key_vec.size(); m++) { objects.push_back(OutBlock(key_vec[m], key, hz)); } } }