diff --git a/apps/sft/fpool.cpp b/apps/sft/fpool.cpp index 1bfde2cf9..185ed62ab 100644 --- a/apps/sft/fpool.cpp +++ b/apps/sft/fpool.cpp @@ -43,6 +43,8 @@ #include #include +#include + #include // ========= FeaturePool ========= // diff --git a/apps/sft/sft.cpp b/apps/sft/sft.cpp index f7e36e26e..971dbe587 100644 --- a/apps/sft/sft.cpp +++ b/apps/sft/sft.cpp @@ -43,6 +43,7 @@ // Trating application for Soft Cascades. #include +#include #include #include @@ -127,22 +128,24 @@ int main(int argc, char** argv) cv::Rect boundingBox = cfg.bbox(it); std::cout << "Object bounding box" << boundingBox << std::endl; - cv::SoftCascadeOctave boost(boundingBox, npositives, nnegatives, *it, shrinkage); + typedef cv::SoftCascadeOctave Octave; + + cv::Ptr boost = Octave::create(boundingBox, npositives, nnegatives, *it, shrinkage); std::string path = cfg.trainPath; sft::ScaledDataset dataset(path, *it); - if (boost.train(&dataset, &pool, cfg.weaks, cfg.treeDepth)) + if (boost->train(&dataset, &pool, cfg.weaks, cfg.treeDepth)) { CvFileStorage* fout = cvOpenFileStorage(cfg.resPath(it).c_str(), 0, CV_STORAGE_WRITE); - boost.write(fout, cfg.cascadeName); + boost->write(fout, cfg.cascadeName); cvReleaseFileStorage( &fout); cv::Mat thresholds; - boost.setRejectThresholds(thresholds); + boost->setRejectThresholds(thresholds); - boost.write(fso, &pool, thresholds); + boost->write(fso, &pool, thresholds); cv::FileStorage tfs(("thresholds." + cfg.resPath(it)).c_str(), cv::FileStorage::WRITE); tfs << "thresholds" << thresholds; diff --git a/modules/softcascade/include/opencv2/softcascade/softcascade.hpp b/modules/softcascade/include/opencv2/softcascade/softcascade.hpp index 24455cf7e..ad5586858 100644 --- a/modules/softcascade/include/opencv2/softcascade/softcascade.hpp +++ b/modules/softcascade/include/opencv2/softcascade/softcascade.hpp @@ -44,7 +44,6 @@ #define __OPENCV_SOFTCASCADE_HPP__ #include "opencv2/core/core.hpp" -#include "opencv2/ml/ml.hpp" namespace cv { @@ -90,7 +89,7 @@ public: // ========================================================================== // -// Implementation of Integral Channel Feature. +// Public Interface for Integral Channel Feature. // ========================================================================== // class CV_EXPORTS_W ChannelFeatureBuilder : public Algorithm @@ -155,12 +154,11 @@ private: }; // ========================================================================== // -// Implementation of singe soft (stageless) cascade octave training. +// Public Interface for singe soft (stageless) cascade octave training. // ========================================================================== // -class CV_EXPORTS SoftCascadeOctave : public cv::Boost +class CV_EXPORTS SoftCascadeOctave : public Algorithm { public: - enum { // Direct backward pruning. (Cha Zhang and Paul Viola) @@ -171,39 +169,14 @@ public: HEURISTIC = 4 }; - SoftCascadeOctave(cv::Rect boundingBox, int npositives, int nnegatives, int logScale, int shrinkage); - virtual bool train(const Dataset* dataset, const FeaturePool* pool, int weaks, int treeDepth); - virtual void setRejectThresholds(OutputArray thresholds); - virtual void write( CvFileStorage* fs, string name) const; - virtual void write( cv::FileStorage &fs, const FeaturePool* pool, InputArray thresholds) const; - virtual float predict( InputArray _sample, InputArray _votes, bool raw_mode, bool return_sum ) const; virtual ~SoftCascadeOctave(); -protected: - virtual bool train( const cv::Mat& trainData, const cv::Mat& responses, const cv::Mat& varIdx=cv::Mat(), - const cv::Mat& sampleIdx=cv::Mat(), const cv::Mat& varType=cv::Mat(), const cv::Mat& missingDataMask=cv::Mat()); + static cv::Ptr create(cv::Rect boundingBox, int npositives, int nnegatives, + int logScale, int shrinkage); - void processPositives(const Dataset* dataset, const FeaturePool* pool); - void generateNegatives(const Dataset* dataset, const FeaturePool* pool); - - float predict( const Mat& _sample, const cv::Range range) const; -private: - void traverse(const CvBoostTree* tree, cv::FileStorage& fs, int& nfeatures, int* used, const double* th) const; - virtual void initial_weights(double (&p)[2]); - - int logScale; - cv::Rect boundingBox; - - int npositives; - int nnegatives; - - int shrinkage; - - Mat integrals; - Mat responses; - - CvBoostParams params; - - Mat trainData; + virtual bool train(const Dataset* dataset, const FeaturePool* pool, int weaks, int treeDepth) = 0; + virtual void setRejectThresholds(OutputArray thresholds) = 0; + virtual void write( cv::FileStorage &fs, const FeaturePool* pool, InputArray thresholds) const = 0; + virtual void write( CvFileStorage* fs, string name) const = 0; }; CV_EXPORTS bool initModule_softcascade(void); diff --git a/modules/softcascade/src/precomp.hpp b/modules/softcascade/src/precomp.hpp index 28771c073..270631921 100644 --- a/modules/softcascade/src/precomp.hpp +++ b/modules/softcascade/src/precomp.hpp @@ -52,6 +52,7 @@ #include "opencv2/imgproc/imgproc_c.h" #include "opencv2/core/core_c.h" #include "opencv2/core/internal.hpp" +#include "opencv2/ml/ml.hpp" #include "opencv2/opencv_modules.hpp" diff --git a/modules/softcascade/src/soft_cascade_octave.cpp b/modules/softcascade/src/soft_cascade_octave.cpp index 9fb92357d..8cd9becc7 100644 --- a/modules/softcascade/src/soft_cascade_octave.cpp +++ b/modules/softcascade/src/soft_cascade_octave.cpp @@ -42,6 +42,7 @@ #include "precomp.hpp" #include +#include #define WITH_DEBUG_OUT @@ -122,10 +123,56 @@ struct Random } #endif +using cv::Dataset; +using cv::FeaturePool; +using cv::InputArray; +using cv::OutputArray; +using cv::Mat; + cv::FeaturePool::~FeaturePool(){} cv::Dataset::~Dataset(){} -cv::SoftCascadeOctave::SoftCascadeOctave(cv::Rect bb, int np, int nn, int ls, int shr) +class BoostedSoftCascadeOctave : public cv::Boost, public cv::SoftCascadeOctave +{ +public: + + BoostedSoftCascadeOctave(cv::Rect boundingBox = cv::Rect(), int npositives = 0, int nnegatives = 0, int logScale = 0, int shrinkage = 1); + virtual ~BoostedSoftCascadeOctave(); + virtual cv::AlgorithmInfo* info() const; + virtual bool train(const Dataset* dataset, const FeaturePool* pool, int weaks, int treeDepth); + virtual void setRejectThresholds(OutputArray thresholds); + virtual void write( cv::FileStorage &fs, const FeaturePool* pool, InputArray thresholds) const; + virtual void write( CvFileStorage* fs, std::string name) const; +protected: + virtual float predict( InputArray _sample, InputArray _votes, bool raw_mode, bool return_sum ) const; + virtual bool train( const cv::Mat& trainData, const cv::Mat& responses, const cv::Mat& varIdx=cv::Mat(), + const cv::Mat& sampleIdx=cv::Mat(), const cv::Mat& varType=cv::Mat(), const cv::Mat& missingDataMask=cv::Mat()); + + void processPositives(const Dataset* dataset, const FeaturePool* pool); + void generateNegatives(const Dataset* dataset, const FeaturePool* pool); + + float predict( const Mat& _sample, const cv::Range range) const; +private: + void traverse(const CvBoostTree* tree, cv::FileStorage& fs, int& nfeatures, int* used, const double* th) const; + virtual void initial_weights(double (&p)[2]); + + int logScale; + cv::Rect boundingBox; + + int npositives; + int nnegatives; + + int shrinkage; + + Mat integrals; + Mat responses; + + CvBoostParams params; + + Mat trainData; +}; + +BoostedSoftCascadeOctave::BoostedSoftCascadeOctave(cv::Rect bb, int np, int nn, int ls, int shr) : logScale(ls), boundingBox(bb), npositives(np), nnegatives(nn), shrinkage(shr) { int maxSample = npositives + nnegatives; @@ -155,9 +202,9 @@ cv::SoftCascadeOctave::SoftCascadeOctave(cv::Rect bb, int np, int nn, int ls, in params = _params; } -cv::SoftCascadeOctave::~SoftCascadeOctave(){} +BoostedSoftCascadeOctave::~BoostedSoftCascadeOctave(){} -bool cv::SoftCascadeOctave::train( const cv::Mat& _trainData, const cv::Mat& _responses, const cv::Mat& varIdx, +bool BoostedSoftCascadeOctave::train( const cv::Mat& _trainData, const cv::Mat& _responses, const cv::Mat& varIdx, const cv::Mat& sampleIdx, const cv::Mat& varType, const cv::Mat& missingDataMask) { bool update = false; @@ -165,7 +212,7 @@ bool cv::SoftCascadeOctave::train( const cv::Mat& _trainData, const cv::Mat& _re update); } -void cv::SoftCascadeOctave::setRejectThresholds(cv::OutputArray _thresholds) +void BoostedSoftCascadeOctave::setRejectThresholds(cv::OutputArray _thresholds) { dprintf("set thresholds according to DBP strategy\n"); @@ -212,7 +259,7 @@ void cv::SoftCascadeOctave::setRejectThresholds(cv::OutputArray _thresholds) } } -void cv::SoftCascadeOctave::processPositives(const Dataset* dataset, const FeaturePool* pool) +void BoostedSoftCascadeOctave::processPositives(const Dataset* dataset, const FeaturePool* pool) { int w = boundingBox.width; int h = boundingBox.height; @@ -259,7 +306,7 @@ void cv::SoftCascadeOctave::processPositives(const Dataset* dataset, const Featu #undef USE_LONG_SEEDS -void cv::SoftCascadeOctave::generateNegatives(const Dataset* dataset, const FeaturePool* pool) +void BoostedSoftCascadeOctave::generateNegatives(const Dataset* dataset, const FeaturePool* pool) { // ToDo: set seed, use offsets sft::Random::engine eng(DX_DY_SEED); @@ -308,7 +355,7 @@ template int sgn(T val) { return (T(0) < val) - (val < T(0)); } -void cv::SoftCascadeOctave::traverse(const CvBoostTree* tree, cv::FileStorage& fs, int& nfeatures, int* used, const double* th) const +void BoostedSoftCascadeOctave::traverse(const CvBoostTree* tree, cv::FileStorage& fs, int& nfeatures, int* used, const double* th) const { std::queue nodes; nodes.push( tree->get_root()); @@ -365,7 +412,7 @@ void cv::SoftCascadeOctave::traverse(const CvBoostTree* tree, cv::FileStorage& f fs << "}"; } -void cv::SoftCascadeOctave::write( cv::FileStorage &fso, const FeaturePool* pool, InputArray _thresholds) const +void BoostedSoftCascadeOctave::write( cv::FileStorage &fso, const FeaturePool* pool, InputArray _thresholds) const { CV_Assert(!_thresholds.empty()); cv::Mat used( 1, weak->total * ( (int)pow(2.f, params.max_depth) - 1), CV_32SC1); @@ -397,14 +444,14 @@ void cv::SoftCascadeOctave::write( cv::FileStorage &fso, const FeaturePool* pool << "}"; } -void cv::SoftCascadeOctave::initial_weights(double (&p)[2]) +void BoostedSoftCascadeOctave::initial_weights(double (&p)[2]) { double n = data->sample_count; p[0] = n / (2. * (double)(nnegatives)); p[1] = n / (2. * (double)(npositives)); } -bool cv::SoftCascadeOctave::train(const Dataset* dataset, const FeaturePool* pool, int weaks, int treeDepth) +bool BoostedSoftCascadeOctave::train(const Dataset* dataset, const FeaturePool* pool, int weaks, int treeDepth) { CV_Assert(treeDepth == 2); CV_Assert(weaks > 0); @@ -458,7 +505,7 @@ bool cv::SoftCascadeOctave::train(const Dataset* dataset, const FeaturePool* poo } -float cv::SoftCascadeOctave::predict( cv::InputArray _sample, cv::InputArray _votes, bool raw_mode, bool return_sum ) const +float BoostedSoftCascadeOctave::predict( cv::InputArray _sample, cv::InputArray _votes, bool raw_mode, bool return_sum ) const { cv::Mat sample = _sample.getMat(); CvMat csample = sample; @@ -472,13 +519,24 @@ float cv::SoftCascadeOctave::predict( cv::InputArray _sample, cv::InputArray _vo } } -float cv::SoftCascadeOctave::predict( const Mat& _sample, const cv::Range range) const +float BoostedSoftCascadeOctave::predict( const Mat& _sample, const cv::Range range) const { CvMat sample = _sample; return CvBoost::predict(&sample, 0, 0, range, false, true); } -void cv::SoftCascadeOctave::write( CvFileStorage* fs, string name) const +void BoostedSoftCascadeOctave::write( CvFileStorage* fs, std::string _name) const { - CvBoost::write(fs, name.c_str()); + CvBoost::write(fs, _name.c_str()); +} + +CV_INIT_ALGORITHM(BoostedSoftCascadeOctave, "SoftCascadeOctave.BoostedSoftCascadeOctave", ); + +cv::SoftCascadeOctave::~SoftCascadeOctave(){} + +cv::Ptr cv::SoftCascadeOctave::create(cv::Rect boundingBox, int npositives, int nnegatives, + int logScale, int shrinkage) +{ + cv::Ptr octave(new BoostedSoftCascadeOctave(boundingBox, npositives, nnegatives, logScale, shrinkage)); + return octave; }