提交 e863c3d5 编写于 作者: A Alexey Kazakov

Added to objdetect module: meanshift grouping (groupRectangles_meanshift(...)...

Added to objdetect module: meanshift grouping (groupRectangles_meanshift(...) for input rectangles); new pedestrian detection model, trained on the Daimler base (getDaimlerPeopleDetector(...) ).
Some changes in the HOGDescriptor class interface(objdetect.hpp) (added useMeanShiftGrouping parameter to the detectMultiScale(...) function)
上级 2057f2c4
......@@ -275,6 +275,41 @@ namespace cv
CV_EXPORTS_W void groupRectangles(vector<Rect>& rectList, int groupThreshold, double eps=0.2);
CV_EXPORTS_W void groupRectangles(vector<Rect>& rectList, CV_OUT vector<int>& weights, int groupThreshold, double eps=0.2);
CV_EXPORTS void groupRectangles(vector<Rect>& rectList, vector<double>& resultWeights, int groupThreshold = 2, double eps=0.2);
CV_EXPORTS void groupRectangles_meanshift(vector<Rect>& rectList, vector<double>& foundWeights, vector<double>& foundScales,
double detectThreshold = 0.0, Size winDetSize = Size(64, 128));
class MeanshiftGrouping
{
public:
MeanshiftGrouping(const Point3d& densKer, const vector<Point3d>& posV,
const vector<double>& wV, double modeEps = 1e-4,
int maxIt = 20);
void getModes(vector<Point3d>& modesV, vector<double>& resWeightsV, const double eps);
protected:
vector<Point3d> positionsV;
vector<double> weightsV;
Point3d densityKernel;
int positionsCount;
vector<Point3d> meanshiftV;
vector<Point3d> distanceV;
int iterMax;
double modeEps;
Point3d getNewValue(const Point3d& inPt) const;
double getResultWeight(const Point3d& inPt) const;
Point3d moveToMode(Point3d aPt) const;
double getDistance(Point3d p1, Point3d p2) const;
};
class CV_EXPORTS FeatureEvaluator
{
......@@ -312,7 +347,10 @@ public:
double scaleFactor=1.1,
int minNeighbors=3, int flags=0,
Size minSize=Size(),
Size maxSize=Size() );
Size maxSize=Size(),
bool outputRejectLevels = false,
vector<int>& rejectLevels = vector<int>(0));
bool isOldFormatCascade() const;
virtual Size getOriginalWindowSize() const;
......@@ -321,7 +359,8 @@ public:
protected:
virtual bool detectSingleScale( const Mat& image, int stripCount, Size processingRectSize,
int stripSize, int yStep, double factor, vector<Rect>& candidates );
int stripSize, int yStep, double factor, vector<Rect>& candidates,
bool outputRejectLevels = false, vector<int>& rejectLevels = vector<int>(0) );
protected:
enum { BOOST = 0 };
......@@ -387,6 +426,35 @@ protected:
Data data;
Ptr<FeatureEvaluator> featureEvaluator;
Ptr<CvHaarClassifierCascade> oldCascade;
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
public:
int getNumStages()
{
int numStages;
if( !isOldFormatCascade() )
{
numStages = data.stages.size();
}
else
{
numStages = this->oldCascade->count;
}
return numStages;
}
void setNumStages(int stageCount)
{
if( !isOldFormatCascade() )
{
if( stageCount )
data.stages.resize(stageCount);
}
else
if( stageCount )
this->oldCascade->count = stageCount;
}
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
};
//////////////// HOG (Histogram-of-Oriented-Gradients) Descriptor and Object Detector //////////////
......@@ -438,23 +506,38 @@ public:
CV_WRAP virtual bool load(const String& filename, const String& objname=String());
CV_WRAP virtual void save(const String& filename, const String& objname=String()) const;
virtual void copyTo(HOGDescriptor& c) const;
CV_WRAP virtual void compute(const Mat& img,
CV_OUT vector<float>& descriptors,
Size winStride=Size(), Size padding=Size(),
const vector<Point>& locations=vector<Point>()) const;
//with found weights output
CV_WRAP virtual void detect(const Mat& img, CV_OUT vector<Point>& foundLocations,
vector<double>& weights,
double hitThreshold=0, Size winStride=Size(),
Size padding=Size(),
const vector<Point>& searchLocations=vector<Point>()) const;
//without found weights output
CV_WRAP virtual void detect(const Mat& img, CV_OUT vector<Point>& foundLocations,
double hitThreshold=0, Size winStride=Size(),
Size padding=Size(),
const vector<Point>& searchLocations=vector<Point>()) const;
CV_WRAP virtual void detectMultiScale(const Mat& img, CV_OUT vector<Rect>& foundLocations,
double hitThreshold=0, Size winStride=Size(),
Size padding=Size(), double scale=1.05,
int groupThreshold=2) const;
//with result weights output
CV_WRAP virtual void detectMultiScale(const Mat& img, CV_OUT vector<Rect>& foundLocations,
vector<double>& foundWeights, double hitThreshold=0,
Size winStride=Size(), Size padding=Size(), double scale=1.05,
double finalThreshold=2.0,bool useMeanshiftGrouping = false) const;
//without found weights output
CV_WRAP virtual void detectMultiScale(const Mat& img, CV_OUT vector<Rect>& foundLocations,
double hitThreshold=0, Size winStride=Size(),
Size padding=Size(), double scale=1.05,
double finalThreshold=2.0, bool useMeanshiftGrouping = false) const;
CV_WRAP virtual void computeGradient(const Mat& img, CV_OUT Mat& grad, CV_OUT Mat& angleOfs,
Size paddingTL=Size(), Size paddingBR=Size()) const;
static vector<float> getDefaultPeopleDetector();
static vector<float> getDaimlerPeopleDetector();
CV_PROP Size winSize;
CV_PROP Size blockSize;
......
......@@ -63,7 +63,7 @@ public:
};
static void groupRectangles(vector<Rect>& rectList, int groupThreshold, double eps, vector<int>* weights)
static void groupRectangles(vector<Rect>& rectList, int groupThreshold, double eps, vector<int>* weights, vector<double>* foundWeights)
{
if( groupThreshold <= 0 || rectList.empty() )
{
......@@ -82,6 +82,7 @@ static void groupRectangles(vector<Rect>& rectList, int groupThreshold, double e
vector<Rect> rrects(nclasses);
vector<int> rweights(nclasses, 0);
vector<double> outWeights(nclasses, 0.0);
int i, j, nlabels = (int)labels.size();
for( i = 0; i < nlabels; i++ )
{
......@@ -92,6 +93,14 @@ static void groupRectangles(vector<Rect>& rectList, int groupThreshold, double e
rrects[cls].height += rectList[i].height;
rweights[cls]++;
}
if ( foundWeights && !foundWeights->empty() )
{
for( i = 0; i < nlabels; i++ )
{
int cls = labels[i];
outWeights[cls] = outWeights[cls] + (*foundWeights)[i];
}
}
for( i = 0; i < nclasses; i++ )
{
......@@ -106,11 +115,14 @@ static void groupRectangles(vector<Rect>& rectList, int groupThreshold, double e
rectList.clear();
if( weights )
weights->clear();
if( foundWeights )
foundWeights->clear();
for( i = 0; i < nclasses; i++ )
{
Rect r1 = rrects[i];
int n1 = rweights[i];
double w1 = outWeights[i];
if( n1 <= groupThreshold )
continue;
// filter out small face rectangles inside large rectangles
......@@ -139,19 +151,76 @@ static void groupRectangles(vector<Rect>& rectList, int groupThreshold, double e
rectList.push_back(r1);
if( weights )
weights->push_back(n1);
if( foundWeights )
foundWeights->push_back(w1);
}
}
}
//new grouping function with using meanshift
static void groupRectangles_meanshift(vector<Rect>& rectList, double detectThreshold, vector<double>* foundWeights,
vector<double>& scales, Size winDetSize)
{
int detectionCount = rectList.size();
vector<Point3d> hits(detectionCount), resultHits;
vector<double> hitWeights(detectionCount), resultWeights;
Point2d hitCenter;
for (int i=0; i < detectionCount; i++)
{
hitWeights[i] = (*foundWeights)[i];
hitCenter = (rectList[i].tl() + rectList[i].br())*(0.5); //center of rectangles
hits[i] = Point3d(hitCenter.x, hitCenter.y, std::log(scales[i]));
}
rectList.clear();
if (foundWeights)
foundWeights->clear();
double logZ = std::log(1.3);
Point3d smothing(8, 16, logZ);
MeanshiftGrouping msGrouping(smothing, hits, hitWeights, 1e-5, 100);
msGrouping.getModes(resultHits, resultWeights, 1);
for (unsigned i=0; i < resultHits.size(); ++i)
{
double scale = exp(resultHits[i].z);
hitCenter.x = resultHits[i].x;
hitCenter.y = resultHits[i].y;
Size s( int(winDetSize.width * scale), int(winDetSize.height * scale) );
Rect resultRect( int(hitCenter.x-s.width/2), int(hitCenter.y-s.height/2),
int(s.width), int(s.height) );
if (resultWeights[i] > detectThreshold)
{
rectList.push_back(resultRect);
foundWeights->push_back(resultWeights[i]);
}
}
}
void groupRectangles(vector<Rect>& rectList, int groupThreshold, double eps)
{
groupRectangles(rectList, groupThreshold, eps, 0);
groupRectangles(rectList, groupThreshold, eps, 0, 0);
}
void groupRectangles(vector<Rect>& rectList, vector<int>& weights, int groupThreshold, double eps)
{
groupRectangles(rectList, groupThreshold, eps, &weights);
groupRectangles(rectList, groupThreshold, eps, &weights, 0);
}
void groupRectangles(vector<Rect>& rectList, vector<double>& foundWeights, int groupThreshold, double eps)
{
groupRectangles(rectList, groupThreshold, eps, 0, &foundWeights);
}
void groupRectangles_meanshift(vector<Rect>& rectList, vector<double>& foundWeights,
vector<double>& foundScales, double detectThreshold, Size winDetSize)
{
groupRectangles_meanshift(rectList, detectThreshold, &foundWeights, foundScales, winDetSize);
}
......@@ -802,7 +871,8 @@ bool CascadeClassifier::setImage( Ptr<FeatureEvaluator>& featureEvaluator, const
struct CascadeClassifierInvoker
{
CascadeClassifierInvoker( CascadeClassifier& _cc, Size _sz1, int _stripSize, int _yStep, double _factor, ConcurrentRectVector& _vec )
CascadeClassifierInvoker( CascadeClassifier& _cc, Size _sz1, int _stripSize, int _yStep, double _factor,
ConcurrentRectVector& _vec, vector<int>& _levels, bool outputLevels = false )
{
classifier = &_cc;
processingRectSize = _sz1;
......@@ -810,6 +880,7 @@ struct CascadeClassifierInvoker
yStep = _yStep;
scalingFactor = _factor;
rectangles = &_vec;
rejectLevels = outputLevels ? &_levels : 0;
}
void operator()(const BlockedRange& range) const
......@@ -824,7 +895,17 @@ struct CascadeClassifierInvoker
for( int x = 0; x < processingRectSize.width; x += yStep )
{
int result = classifier->runAt(evaluator, Point(x, y));
if( result > 0 )
if( rejectLevels )
{
if( result == 1 )
result = -1*classifier->data.stages.size();
if( classifier->data.stages.size() + result < 6 )
{
rectangles->push_back(Rect(cvRound(x*scalingFactor), cvRound(y*scalingFactor), winSize.width, winSize.height));
rejectLevels->push_back(-result);
}
}
else if( result > 0 )
rectangles->push_back(Rect(cvRound(x*scalingFactor), cvRound(y*scalingFactor),
winSize.width, winSize.height));
if( result == 0 )
......@@ -838,18 +919,31 @@ struct CascadeClassifierInvoker
Size processingRectSize;
int stripSize, yStep;
double scalingFactor;
vector<int> *rejectLevels;
};
struct getRect { Rect operator ()(const CvAvgComp& e) const { return e.rect; } };
bool CascadeClassifier::detectSingleScale( const Mat& image, int stripCount, Size processingRectSize,
int stripSize, int yStep, double factor, vector<Rect>& candidates )
int stripSize, int yStep, double factor, vector<Rect>& candidates,
bool outputRejectLevels, vector<int>& levels )
{
if( !featureEvaluator->setImage( image, data.origWinSize ) )
return false;
ConcurrentRectVector concurrentCandidates;
parallel_for(BlockedRange(0, stripCount), CascadeClassifierInvoker( *this, processingRectSize, stripSize, yStep, factor, concurrentCandidates));
vector<int> rejectLevels;
if( outputRejectLevels )
{
parallel_for(BlockedRange(0, stripCount), CascadeClassifierInvoker( *this, processingRectSize, stripSize, yStep, factor,
concurrentCandidates, rejectLevels, true));
levels.insert( levels.end(), rejectLevels.begin(), rejectLevels.end() );
}
else
{
parallel_for(BlockedRange(0, stripCount), CascadeClassifierInvoker( *this, processingRectSize, stripSize, yStep, factor,
concurrentCandidates, rejectLevels, false));
}
candidates.insert( candidates.end(), concurrentCandidates.begin(), concurrentCandidates.end() );
return true;
......@@ -877,7 +971,8 @@ bool CascadeClassifier::setImage(const Mat& image)
void CascadeClassifier::detectMultiScale( const Mat& image, vector<Rect>& objects,
double scaleFactor, int minNeighbors,
int flags, Size minObjectSize, Size maxObjectSize )
int flags, Size minObjectSize, Size maxObjectSize,
bool outputRejectLevels, vector<int>& rejectLevels )
{
const double GROUP_EPS = 0.2;
......@@ -946,14 +1041,16 @@ void CascadeClassifier::detectMultiScale( const Mat& image, vector<Rect>& object
stripSize = processingRectSize.height;
#endif
if( !detectSingleScale( scaledImage, stripCount, processingRectSize, stripSize, yStep, factor, candidates ) )
if( !detectSingleScale( scaledImage, stripCount, processingRectSize, stripSize, yStep, factor, candidates,
outputRejectLevels, rejectLevels ) )
break;
}
objects.resize(candidates.size());
std::copy(candidates.begin(), candidates.end(), objects.begin());
groupRectangles( objects, minNeighbors, GROUP_EPS );
groupRectangles( objects, rejectLevels, minNeighbors, GROUP_EPS );
}
bool CascadeClassifier::Data::read(const FileNode &root)
......
此差异已折叠。
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
using namespace cv;
MeanshiftGrouping::MeanshiftGrouping(const Point3d& densKer, const vector<Point3d>& posV,
const vector<double>& wV, double modeEps, int maxIter):
densityKernel(densKer), weightsV(wV), positionsV(posV), positionsCount(posV.size()),
meanshiftV(positionsCount), distanceV(positionsCount), modeEps(modeEps),
iterMax (maxIter)
{
for (unsigned i=0; i<positionsV.size(); i++)
{
meanshiftV[i] = getNewValue(positionsV[i]);
distanceV[i] = moveToMode(meanshiftV[i]);
meanshiftV[i] -= positionsV[i];
}
}
void MeanshiftGrouping::getModes(vector<Point3d>& modesV, vector<double>& resWeightsV, double eps)
{
for (size_t i=0; i <distanceV.size(); i++)
{
bool is_found = false;
for(size_t j=0; j<modesV.size(); j++)
{
if ( getDistance(distanceV[i], modesV[j]) < eps)
{
is_found=true;
break;
}
}
if (!is_found)
{
modesV.push_back(distanceV[i]);
}
}
resWeightsV.resize(modesV.size());
for (size_t i=0; i<modesV.size(); i++)
{
resWeightsV[i] = getResultWeight(modesV[i]);
}
}
Point3d MeanshiftGrouping::moveToMode(Point3d aPt) const
{
Point3d bPt;
for (int i = 0; i<iterMax; i++)
{
bPt = aPt;
aPt = getNewValue(bPt);
if ( getDistance(aPt, bPt) <= modeEps )
{
break;
}
}
return aPt;
}
Point3d MeanshiftGrouping::getNewValue(const Point3d& inPt) const
{
Point3d resPoint(.0);
Point3d ratPoint(.0);
for (size_t i=0; i<positionsV.size(); i++)
{
Point3d aPt= positionsV[i];
Point3d bPt = inPt;
Point3d sPt = densityKernel;
sPt.x *= exp(aPt.z);
sPt.y *= exp(aPt.z);
aPt.x /= sPt.x;
aPt.y /= sPt.y;
aPt.z /= sPt.z;
bPt.x /= sPt.x;
bPt.y /= sPt.y;
bPt.z /= sPt.z;
double w = (weightsV[i])*std::exp(-((aPt-bPt).dot(aPt-bPt))/2)/std::sqrt(sPt.dot(Point3d(1,1,1)));
resPoint += w*aPt;
ratPoint.x += w/sPt.x;
ratPoint.y += w/sPt.y;
ratPoint.z += w/sPt.z;
}
resPoint.x /= ratPoint.x;
resPoint.y /= ratPoint.y;
resPoint.z /= ratPoint.z;
return resPoint;
}
double MeanshiftGrouping::getResultWeight(const Point3d& inPt) const
{
double sumW=0;
for (size_t i=0; i<positionsV.size(); i++)
{
Point3d aPt = positionsV[i];
Point3d sPt = densityKernel;
sPt.x *= exp(aPt.z);
sPt.y *= exp(aPt.z);
aPt -= inPt;
aPt.x /= sPt.x;
aPt.y /= sPt.y;
aPt.z /= sPt.z;
sumW+=(weightsV[i])*std::exp(-(aPt.dot(aPt))/2)/std::sqrt(sPt.dot(Point3d(1,1,1)));
}
return sumW;
}
double MeanshiftGrouping::getDistance(Point3d p1, Point3d p2) const
{
Point3d ns = densityKernel;
ns.x *= exp(p2.z);
ns.y *= exp(p2.z);
p2 -= p1;
p2.x /= ns.x;
p2.y /= ns.y;
p2.z /= ns.z;
return p2.dot(p2);
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册