Merge pull request #608 from cuda-geek:soft-cascade-hot-fixes
This commit is contained in:
commit
1c3cde110d
@ -69,6 +69,7 @@ void sft::Config::write(cv::FileStorage& fs) const
|
||||
<< "outXmlPath" << outXmlPath
|
||||
|
||||
<< "seed" << seed
|
||||
<< "featureType" << featureType
|
||||
<< "}";
|
||||
}
|
||||
|
||||
@ -99,6 +100,7 @@ void sft::Config::read(const cv::FileNode& node)
|
||||
outXmlPath = (std::string)node["outXmlPath"];
|
||||
|
||||
seed = (int)node["seed"];
|
||||
featureType = (std::string)node["featureType"];
|
||||
}
|
||||
|
||||
void sft::write(cv::FileStorage& fs, const string&, const Config& x)
|
||||
@ -153,7 +155,8 @@ std::ostream& sft::operator<<(std::ostream& out, const Config& m)
|
||||
|
||||
<< std::setw(14) << std::left << "cascadeName" << m.cascadeName << std::endl
|
||||
<< std::setw(14) << std::left << "outXmlPath" << m.outXmlPath << std::endl
|
||||
<< std::setw(14) << std::left << "seed" << m.seed << std::endl;
|
||||
<< std::setw(14) << std::left << "seed" << m.seed << std::endl
|
||||
<< std::setw(14) << std::left << "featureType" << m.featureType << std::endl;
|
||||
|
||||
return out;
|
||||
}
|
@ -121,6 +121,9 @@ struct Config
|
||||
// seed for random generation
|
||||
int seed;
|
||||
|
||||
// channel feature type
|
||||
string featureType;
|
||||
|
||||
// // bounding rectangle for actual example into example window
|
||||
// cv::Rect exampleWindow;
|
||||
};
|
||||
|
@ -104,7 +104,7 @@ int main(int argc, char** argv)
|
||||
fso << cfg.cascadeName
|
||||
<< "{"
|
||||
<< "stageType" << "BOOST"
|
||||
<< "featureType" << "ICF"
|
||||
<< "featureType" << cfg.featureType
|
||||
<< "octavesNum" << (int)cfg.octaves.size()
|
||||
<< "width" << cfg.modelWinSize.width
|
||||
<< "height" << cfg.modelWinSize.height
|
||||
@ -118,7 +118,12 @@ int main(int argc, char** argv)
|
||||
int nfeatures = cfg.poolSize;
|
||||
cv::Size model = cfg.model(it);
|
||||
std::cout << "Model " << model << std::endl;
|
||||
cv::Ptr<cv::FeaturePool> pool = cv::FeaturePool::create(model, nfeatures);
|
||||
|
||||
int nchannels = (cfg.featureType == "HOG6MagLuv") ? 10: 8;
|
||||
|
||||
std::cout << "number of feature channels is " << nchannels << std::endl;
|
||||
|
||||
cv::Ptr<cv::FeaturePool> pool = cv::FeaturePool::create(model, nfeatures, nchannels);
|
||||
nfeatures = pool->size();
|
||||
|
||||
|
||||
@ -130,7 +135,9 @@ int main(int argc, char** argv)
|
||||
|
||||
typedef cv::Octave Octave;
|
||||
|
||||
cv::Ptr<Octave> boost = Octave::create(boundingBox, npositives, nnegatives, *it, shrinkage, nfeatures);
|
||||
cv::Ptr<cv::ChannelFeatureBuilder> builder = cv::ChannelFeatureBuilder::create(cfg.featureType);
|
||||
std::cout << "Channel builder " << builder->info()->name() << std::endl;
|
||||
cv::Ptr<Octave> boost = Octave::create(boundingBox, npositives, nnegatives, *it, shrinkage, builder);
|
||||
|
||||
std::string path = cfg.trainPath;
|
||||
sft::ScaledDataset dataset(path, *it);
|
||||
|
@ -87,7 +87,7 @@ public:
|
||||
virtual void write( cv::FileStorage& fs, int index) const = 0;
|
||||
virtual ~FeaturePool();
|
||||
|
||||
static cv::Ptr<FeaturePool> create(const cv::Size& model, int nfeatures);
|
||||
static cv::Ptr<FeaturePool> create(const cv::Size& model, int nfeatures, int nchannels );
|
||||
};
|
||||
|
||||
// ========================================================================== //
|
||||
@ -128,7 +128,10 @@ public:
|
||||
// apply channels to source frame
|
||||
CV_WRAP_AS(compute) virtual void operator()(InputArray src, CV_OUT OutputArray channels, cv::Size channelsSize = cv::Size()) const = 0;
|
||||
|
||||
CV_WRAP static cv::Ptr<ChannelFeatureBuilder> create();
|
||||
CV_WRAP virtual int totalChannels() const = 0;
|
||||
virtual cv::AlgorithmInfo* info() const = 0;
|
||||
|
||||
CV_WRAP static cv::Ptr<ChannelFeatureBuilder> create(const std::string& featureType);
|
||||
};
|
||||
|
||||
// ========================================================================== //
|
||||
@ -199,7 +202,7 @@ public:
|
||||
|
||||
virtual ~Octave();
|
||||
static cv::Ptr<Octave> create(cv::Rect boundingBox, int npositives, int nnegatives,
|
||||
int logScale, int shrinkage, int poolSize);
|
||||
int logScale, int shrinkage, cv::Ptr<ChannelFeatureBuilder> builder);
|
||||
|
||||
virtual bool train(const Dataset* dataset, const FeaturePool* pool, int weaks, int treeDepth) = 0;
|
||||
virtual void setRejectThresholds(OutputArray thresholds) = 0;
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys, os, os.path, glob, math, cv2
|
||||
import sys, os, os.path, glob, math, cv2, sft
|
||||
from datetime import datetime
|
||||
from optparse import OptionParser
|
||||
import re
|
||||
|
@ -46,11 +46,15 @@ namespace {
|
||||
|
||||
using namespace cv::softcascade;
|
||||
|
||||
class ICFBuilder : public ChannelFeatureBuilder
|
||||
class HOG6MagLuv : public ChannelFeatureBuilder
|
||||
{
|
||||
virtual ~ICFBuilder() {}
|
||||
enum {N_CHANNELS = 10};
|
||||
public:
|
||||
virtual ~HOG6MagLuv() {}
|
||||
virtual cv::AlgorithmInfo* info() const;
|
||||
|
||||
virtual int totalChannels() const {return N_CHANNELS; }
|
||||
|
||||
virtual void operator()(cv::InputArray _frame, CV_OUT cv::OutputArray _integrals, cv::Size channelsSize) const
|
||||
{
|
||||
CV_Assert(_frame.type() == CV_8UC3);
|
||||
@ -60,16 +64,16 @@ class ICFBuilder : public ChannelFeatureBuilder
|
||||
int w = frame.cols;
|
||||
|
||||
if (channelsSize != cv::Size())
|
||||
_integrals.create(channelsSize.height * 10 + 1, channelsSize.width + 1, CV_32SC1);
|
||||
_integrals.create(channelsSize.height * N_CHANNELS + 1, channelsSize.width + 1, CV_32SC1);
|
||||
|
||||
if(_integrals.empty())
|
||||
_integrals.create(frame.rows * 10 + 1, frame.cols + 1, CV_32SC1);
|
||||
_integrals.create(frame.rows * N_CHANNELS + 1, frame.cols + 1, CV_32SC1);
|
||||
|
||||
cv::Mat& integrals = _integrals.getMatRef();
|
||||
|
||||
cv::Mat channels, gray;
|
||||
|
||||
channels.create(h * 10, w, CV_8UC1);
|
||||
channels.create(h * N_CHANNELS, w, CV_8UC1);
|
||||
channels.setTo(0);
|
||||
|
||||
cvtColor(frame, gray, CV_BGR2GRAY);
|
||||
@ -81,7 +85,7 @@ class ICFBuilder : public ChannelFeatureBuilder
|
||||
cv::cartToPolar(df_dx, df_dy, mag, angle, true);
|
||||
mag *= (1.f / (8 * sqrt(2.f)));
|
||||
|
||||
cv::Mat nmag;
|
||||
cv::Mat nmag = channels(cv::Rect(0, h * (N_CHANNELS - 4), w, h));
|
||||
mag.convertTo(nmag, CV_8UC1);
|
||||
|
||||
angle *= 6 / 360.f;
|
||||
@ -114,14 +118,13 @@ class ICFBuilder : public ChannelFeatureBuilder
|
||||
using cv::softcascade::ChannelFeatureBuilder;
|
||||
using cv::softcascade::ChannelFeature;
|
||||
|
||||
CV_INIT_ALGORITHM(ICFBuilder, "ChannelFeatureBuilder.ICFBuilder", );
|
||||
CV_INIT_ALGORITHM(HOG6MagLuv, "ChannelFeatureBuilder.HOG6MagLuv", );
|
||||
|
||||
ChannelFeatureBuilder::~ChannelFeatureBuilder() {}
|
||||
|
||||
cv::Ptr<ChannelFeatureBuilder> ChannelFeatureBuilder::create()
|
||||
cv::Ptr<ChannelFeatureBuilder> ChannelFeatureBuilder::create(const std::string& featureType)
|
||||
{
|
||||
cv::Ptr<ChannelFeatureBuilder> builder(new ICFBuilder());
|
||||
return builder;
|
||||
return Algorithm::create<ChannelFeatureBuilder>("ChannelFeatureBuilder." + featureType);
|
||||
}
|
||||
|
||||
ChannelFeature::ChannelFeature(int x, int y, int w, int h, int ch)
|
||||
@ -175,9 +178,9 @@ using namespace cv::softcascade;
|
||||
class ChannelFeaturePool : public FeaturePool
|
||||
{
|
||||
public:
|
||||
ChannelFeaturePool(cv::Size m, int n) : FeaturePool(), model(m)
|
||||
ChannelFeaturePool(cv::Size m, int n, int ch) : FeaturePool(), model(m), N_CHANNELS(ch)
|
||||
{
|
||||
CV_Assert(m != cv::Size() && n > 0);
|
||||
CV_Assert(m != cv::Size() && n > 0 && (ch == 10 || ch == 8));
|
||||
fill(n);
|
||||
}
|
||||
|
||||
@ -193,7 +196,7 @@ private:
|
||||
|
||||
cv::Size model;
|
||||
std::vector<ChannelFeature> pool;
|
||||
enum { N_CHANNELS = 10 };
|
||||
int N_CHANNELS;
|
||||
};
|
||||
|
||||
float ChannelFeaturePool::apply(int fi, int si, const cv::Mat& integrals) const
|
||||
@ -203,7 +206,8 @@ float ChannelFeaturePool::apply(int fi, int si, const cv::Mat& integrals) const
|
||||
|
||||
void ChannelFeaturePool::write( cv::FileStorage& fs, int index) const
|
||||
{
|
||||
CV_Assert((index > 0) && (index < (int)pool.size()));
|
||||
|
||||
CV_Assert((index >= 0) && (index < (int)pool.size()));
|
||||
fs << pool[index];
|
||||
}
|
||||
|
||||
@ -240,12 +244,12 @@ void ChannelFeaturePool::fill(int desired)
|
||||
// the old behavior:
|
||||
// http://www.boost.org/doc/libs/1_47_0/boost/random/uniform_int.hpp
|
||||
int w = 1 + wRand(
|
||||
eng,
|
||||
eng,
|
||||
// This extra "- 1" appears to be necessary, based on the Boost docs.
|
||||
Random::uniform::param_type(0, (model.width - x - 1) - 1));
|
||||
Random::uniform::param_type(0, (model.width - x - 1) - 1));
|
||||
int h = 1 + hRand(
|
||||
eng,
|
||||
Random::uniform::param_type(0, (model.height - y - 1) - 1));
|
||||
eng,
|
||||
Random::uniform::param_type(0, (model.height - y - 1) - 1));
|
||||
#else
|
||||
int w = 1 + wRand(eng, model.width - x - 1);
|
||||
int h = 1 + hRand(eng, model.height - y - 1);
|
||||
@ -270,8 +274,8 @@ void ChannelFeaturePool::fill(int desired)
|
||||
|
||||
}
|
||||
|
||||
cv::Ptr<FeaturePool> FeaturePool::create(const cv::Size& model, int nfeatures)
|
||||
cv::Ptr<FeaturePool> FeaturePool::create(const cv::Size& model, int nfeatures, int nchannels )
|
||||
{
|
||||
cv::Ptr<FeaturePool> pool(new ChannelFeaturePool(model, nfeatures));
|
||||
cv::Ptr<FeaturePool> pool(new ChannelFeaturePool(model, nfeatures, nchannels));
|
||||
return pool;
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ class BoostedSoftCascadeOctave : public cv::Boost, public Octave
|
||||
public:
|
||||
|
||||
BoostedSoftCascadeOctave(cv::Rect boundingBox = cv::Rect(), int npositives = 0, int nnegatives = 0, int logScale = 0,
|
||||
int shrinkage = 1, int poolSize = 0);
|
||||
int shrinkage = 1, cv::Ptr<ChannelFeatureBuilder> builder = ChannelFeatureBuilder::create("HOG6MagLuv"));
|
||||
virtual ~BoostedSoftCascadeOctave();
|
||||
virtual cv::AlgorithmInfo* info() const;
|
||||
virtual bool train(const Dataset* dataset, const FeaturePool* pool, int weaks, int treeDepth);
|
||||
@ -101,7 +101,8 @@ private:
|
||||
cv::Ptr<ChannelFeatureBuilder> builder;
|
||||
};
|
||||
|
||||
BoostedSoftCascadeOctave::BoostedSoftCascadeOctave(cv::Rect bb, int np, int nn, int ls, int shr, int poolSize)
|
||||
BoostedSoftCascadeOctave::BoostedSoftCascadeOctave(cv::Rect bb, int np, int nn, int ls, int shr,
|
||||
cv::Ptr<ChannelFeatureBuilder> _builder)
|
||||
: logScale(ls), boundingBox(bb), npositives(np), nnegatives(nn), shrinkage(shr)
|
||||
{
|
||||
int maxSample = npositives + nnegatives;
|
||||
@ -130,12 +131,12 @@ BoostedSoftCascadeOctave::BoostedSoftCascadeOctave(cv::Rect bb, int np, int nn,
|
||||
|
||||
params = _params;
|
||||
|
||||
builder = ChannelFeatureBuilder::create();
|
||||
builder = _builder;
|
||||
|
||||
int w = boundingBox.width;
|
||||
int h = boundingBox.height;
|
||||
|
||||
integrals.create(poolSize, (w / shrinkage + 1) * (h / shrinkage * 10 + 1), CV_32SC1);
|
||||
integrals.create(npositives + nnegatives, (w / shrinkage + 1) * (h / shrinkage * builder->totalChannels() + 1), CV_32SC1);
|
||||
}
|
||||
|
||||
BoostedSoftCascadeOctave::~BoostedSoftCascadeOctave(){}
|
||||
@ -204,7 +205,7 @@ void BoostedSoftCascadeOctave::processPositives(const Dataset* dataset)
|
||||
{
|
||||
cv::Mat sample = dataset->get( Dataset::POSITIVE, curr);
|
||||
|
||||
cv::Mat channels = integrals.row(total).reshape(0, h / shrinkage * 10 + 1);
|
||||
cv::Mat channels = integrals.row(total).reshape(0, h / shrinkage * builder->totalChannels() + 1);
|
||||
sample = sample(boundingBox);
|
||||
|
||||
_builder(sample, channels);
|
||||
@ -249,7 +250,7 @@ void BoostedSoftCascadeOctave::generateNegatives(const Dataset* dataset)
|
||||
|
||||
frame = frame(cv::Rect(dx, dy, boundingBox.width, boundingBox.height));
|
||||
|
||||
cv::Mat channels = integrals.row(i).reshape(0, h / shrinkage * 10 + 1);
|
||||
cv::Mat channels = integrals.row(i).reshape(0, h / shrinkage * builder->totalChannels() + 1);
|
||||
_builder(frame, channels);
|
||||
|
||||
// // if (predict(sum))
|
||||
@ -442,14 +443,14 @@ void BoostedSoftCascadeOctave::write( CvFileStorage* fs, std::string _name) cons
|
||||
|
||||
}
|
||||
|
||||
CV_INIT_ALGORITHM(BoostedSoftCascadeOctave, "SoftCascadeOctave.BoostedSoftCascadeOctave", );
|
||||
CV_INIT_ALGORITHM(BoostedSoftCascadeOctave, "Octave.BoostedSoftCascadeOctave", );
|
||||
|
||||
Octave::~Octave(){}
|
||||
|
||||
cv::Ptr<Octave> Octave::create(cv::Rect boundingBox, int npositives, int nnegatives,
|
||||
int logScale, int shrinkage, int poolSize)
|
||||
int logScale, int shrinkage, cv::Ptr<ChannelFeatureBuilder> builder)
|
||||
{
|
||||
cv::Ptr<Octave> octave(
|
||||
new BoostedSoftCascadeOctave(boundingBox, npositives, nnegatives, logScale, shrinkage, poolSize));
|
||||
new BoostedSoftCascadeOctave(boundingBox, npositives, nnegatives, logScale, shrinkage, builder));
|
||||
return octave;
|
||||
}
|
||||
|
@ -187,11 +187,12 @@ struct ChannelStorage
|
||||
|
||||
enum {HOG_BINS = 6, HOG_LUV_BINS = 10};
|
||||
|
||||
ChannelStorage(const cv::Mat& colored, int shr) : shrinkage(shr)
|
||||
ChannelStorage(const cv::Mat& colored, int shr, std::string featureTypeStr) : shrinkage(shr)
|
||||
{
|
||||
model_height = cvRound(colored.rows / (float)shrinkage);
|
||||
if (featureTypeStr == "ICF") featureTypeStr = "HOG6MagLuv";
|
||||
|
||||
builder = ChannelFeatureBuilder::create();
|
||||
builder = ChannelFeatureBuilder::create(featureTypeStr);
|
||||
(*builder)(colored, hog, cv::Size(cvRound(colored.cols / (float)shrinkage), model_height));
|
||||
|
||||
step = hog.step1();
|
||||
@ -201,8 +202,8 @@ struct ChannelStorage
|
||||
{
|
||||
const int *ptr = hog.ptr<const int>(0) + model_height * channel * step + offset;
|
||||
|
||||
int a = ptr[area.y * step + area.x];
|
||||
int b = ptr[area.y * step + area.width];
|
||||
int a = ptr[area.y * step + area.x];
|
||||
int b = ptr[area.y * step + area.width];
|
||||
int c = ptr[area.height * step + area.width];
|
||||
int d = ptr[area.height * step + area.x];
|
||||
|
||||
@ -224,7 +225,7 @@ struct Detector::Fields
|
||||
|
||||
int shrinkage;
|
||||
|
||||
std::vector<SOctave> octaves;
|
||||
std::vector<SOctave> octaves;
|
||||
std::vector<Weak> weaks;
|
||||
std::vector<Node> nodes;
|
||||
std::vector<float> leaves;
|
||||
@ -237,6 +238,8 @@ struct Detector::Fields
|
||||
typedef std::vector<SOctave>::iterator octIt_t;
|
||||
typedef std::vector<Detection> dvector;
|
||||
|
||||
std::string featureTypeStr;
|
||||
|
||||
void detectAt(const int dx, const int dy, const Level& level, const ChannelStorage& storage, dvector& detections) const
|
||||
{
|
||||
float detectionScore = 0.f;
|
||||
@ -341,6 +344,7 @@ struct Detector::Fields
|
||||
static const char *const SC_BOOST = "BOOST";
|
||||
|
||||
static const char *const SC_FEATURE_TYPE = "featureType";
|
||||
static const char *const SC_HOG6_MAG_LUV = "HOG6MagLuv";
|
||||
static const char *const SC_ICF = "ICF";
|
||||
|
||||
static const char *const SC_ORIG_W = "width";
|
||||
@ -365,8 +369,8 @@ struct Detector::Fields
|
||||
bool useBoxes = (fformat == "BOX");
|
||||
|
||||
// only HOG-like integral channel features supported
|
||||
std::string featureTypeStr = (std::string)root[SC_FEATURE_TYPE];
|
||||
CV_Assert(featureTypeStr == SC_ICF);
|
||||
featureTypeStr = (std::string)root[SC_FEATURE_TYPE];
|
||||
CV_Assert(featureTypeStr == SC_ICF || featureTypeStr == SC_HOG6_MAG_LUV);
|
||||
|
||||
origObjWidth = (int)root[SC_ORIG_W];
|
||||
origObjHeight = (int)root[SC_ORIG_H];
|
||||
@ -491,7 +495,7 @@ void Detector::detectNoRoi(const cv::Mat& image, std::vector<Detection>& objects
|
||||
{
|
||||
Fields& fld = *fields;
|
||||
// create integrals
|
||||
ChannelStorage storage(image, fld.shrinkage);
|
||||
ChannelStorage storage(image, fld.shrinkage, fld.featureTypeStr);
|
||||
|
||||
typedef std::vector<Level>::const_iterator lIt;
|
||||
for (lIt it = fld.levels.begin(); it != fld.levels.end(); ++it)
|
||||
@ -539,7 +543,7 @@ void Detector::detect(cv::InputArray _image, cv::InputArray _rois, std::vector<D
|
||||
cv::Mat(mask, cv::Rect(r[i].x / shr, r[i].y / shr, r[i].width / shr , r[i].height / shr)).setTo(cv::Scalar::all(1));
|
||||
|
||||
// create integrals
|
||||
ChannelStorage storage(image, shr);
|
||||
ChannelStorage storage(image, shr, fld.featureTypeStr);
|
||||
|
||||
typedef std::vector<Level>::const_iterator lIt;
|
||||
for (lIt it = fld.levels.begin(); it != fld.levels.end(); ++it)
|
||||
|
@ -46,13 +46,13 @@ using namespace cv::softcascade;
|
||||
|
||||
TEST(ChannelFeatureBuilderTest, info)
|
||||
{
|
||||
cv::Ptr<ChannelFeatureBuilder> builder = ChannelFeatureBuilder::create();
|
||||
cv::Ptr<ChannelFeatureBuilder> builder = ChannelFeatureBuilder::create("HOG6MagLuv");
|
||||
ASSERT_TRUE(builder->info() != 0);
|
||||
}
|
||||
|
||||
TEST(ChannelFeatureBuilderTest, compute)
|
||||
{
|
||||
cv::Ptr<ChannelFeatureBuilder> builder = ChannelFeatureBuilder::create();
|
||||
cv::Ptr<ChannelFeatureBuilder> builder = ChannelFeatureBuilder::create("HOG6MagLuv");
|
||||
|
||||
cv::Mat colored = cv::imread(cvtest::TS::ptr()->get_data_path() + "cascadeandhog/images/image_00000000_0.png");
|
||||
cv::Mat ints;
|
||||
|
@ -212,7 +212,7 @@ TEST(DISABLED_SoftCascade, training)
|
||||
float octave = powf(2.f, (float)(*it));
|
||||
cv::Size model = cv::Size( cvRound(64 * octave) / shrinkage, cvRound(128 * octave) / shrinkage );
|
||||
|
||||
cv::Ptr<FeaturePool> pool = FeaturePool::create(model, nfeatures);
|
||||
cv::Ptr<FeaturePool> pool = FeaturePool::create(model, nfeatures, 10);
|
||||
nfeatures = pool->size();
|
||||
int npositives = 20;
|
||||
int nnegatives = 40;
|
||||
@ -220,7 +220,8 @@ TEST(DISABLED_SoftCascade, training)
|
||||
cv::Rect boundingBox = cv::Rect( cvRound(20 * octave), cvRound(20 * octave),
|
||||
cvRound(64 * octave), cvRound(128 * octave));
|
||||
|
||||
cv::Ptr<Octave> boost = Octave::create(boundingBox, npositives, nnegatives, *it, shrinkage, nfeatures);
|
||||
cv::Ptr<ChannelFeatureBuilder> builder = ChannelFeatureBuilder::create("HOG6MagLuv");
|
||||
cv::Ptr<Octave> boost = Octave::create(boundingBox, npositives, nnegatives, *it, shrinkage, builder);
|
||||
|
||||
std::string path = cvtest::TS::ptr()->get_data_path() + "softcascade/sample_training_set";
|
||||
ScaledDataset dataset(path, *it);
|
||||
|
Loading…
x
Reference in New Issue
Block a user