Commit 479f71ef authored by Vlad Shakhuro's avatar Vlad Shakhuro

Add icf feature evaluator

parent 5ff271ef
...@@ -58,9 +58,9 @@ namespace xobjdetect ...@@ -58,9 +58,9 @@ namespace xobjdetect
channels — output array for computed channels channels — output array for computed channels
*/ */
void computeChannels(InputArray image, std::vector<Mat>& channels); CV_EXPORTS void computeChannels(InputArray image, std::vector<Mat>& channels);
class CV_EXPORTS ACFFeatureEvaluator : public Algorithm class CV_EXPORTS FeatureEvaluator : public Algorithm
{ {
public: public:
/* Set channels for feature evaluation */ /* Set channels for feature evaluation */
...@@ -69,8 +69,6 @@ public: ...@@ -69,8 +69,6 @@ public:
/* Set window position */ /* Set window position */
virtual void setPosition(Size position) = 0; virtual void setPosition(Size position) = 0;
virtual void assertChannels() = 0;
/* Evaluate feature with given index for current channels /* Evaluate feature with given index for current channels
and window position */ and window position */
virtual int evaluate(size_t feature_ind) const = 0; virtual int evaluate(size_t feature_ind) const = 0;
...@@ -81,23 +79,28 @@ public: ...@@ -81,23 +79,28 @@ public:
*/ */
virtual void evaluateAll(OutputArray feature_values) const = 0; virtual void evaluateAll(OutputArray feature_values) const = 0;
virtual void assertChannels() = 0;
}; };
/* Construct evaluator, set features to evaluate */ /* Construct feature evaluator, set features to evaluate
CV_EXPORTS Ptr<ACFFeatureEvaluator> type can "icf" or "acf" */
createACFFeatureEvaluator(const std::vector<Point3i>& features); CV_EXPORTS Ptr<FeatureEvaluator>
createFeatureEvaluator(const std::vector<std::vector<int> >& features,
const std::string& type);
/* Generate acf features /* Generate acf features
window_size — size of window in which features should be evaluated window_size — size of window in which features should be evaluated
type — type of features, can be "icf" or "acf"
count — number of features to generate. count — number of features to generate.
Max number of features is min(count, # possible distinct features) Max number of features is min(count, # possible distinct features)
Returns vector of distinct acf features Returns vector of distinct acf features
*/ */
std::vector<Point3i> std::vector<std::vector<int> >
generateFeatures(Size window_size, int count = INT_MAX); generateFeatures(Size window_size, const std::string& type,
int count = INT_MAX, int channel_count = 10);
struct CV_EXPORTS WaldBoostParams struct CV_EXPORTS WaldBoostParams
...@@ -135,7 +138,7 @@ public: ...@@ -135,7 +138,7 @@ public:
is from class +1 is from class +1
*/ */
virtual float predict( virtual float predict(
const Ptr<ACFFeatureEvaluator>& /*feature_evaluator*/) const const Ptr<FeatureEvaluator>& /*feature_evaluator*/) const
{return 0.0f;} {return 0.0f;}
/* Write WaldBoost to FileStorage */ /* Write WaldBoost to FileStorage */
...@@ -207,7 +210,7 @@ public: ...@@ -207,7 +210,7 @@ public:
private: private:
Ptr<WaldBoost> waldboost_; Ptr<WaldBoost> waldboost_;
std::vector<Point3i> features_; std::vector<std::vector<int> > features_;
int model_n_rows_; int model_n_rows_;
int model_n_cols_; int model_n_cols_;
}; };
......
...@@ -54,75 +54,126 @@ namespace cv ...@@ -54,75 +54,126 @@ namespace cv
namespace xobjdetect namespace xobjdetect
{ {
class ACFFeatureEvaluatorImpl : public ACFFeatureEvaluator static bool isNull(const Mat_<int> &m)
{
bool null_data = true;
for( int row = 0; row < m.rows; ++row )
{
for( int col = 0; col < m.cols; ++col )
if( m.at<int>(row, col) )
null_data = false;
}
return null_data;
}
class FeatureEvaluatorImpl : public FeatureEvaluator
{ {
public: public:
ACFFeatureEvaluatorImpl(const vector<Point3i>& features): FeatureEvaluatorImpl(const vector<vector<int> >& features):
features_(features), channels_(), position_() features_(features), channels_(), position_()
{ {
CV_Assert(features.size() > 0); CV_Assert(features.size() > 0);
} }
virtual void setChannels(InputArrayOfArrays channels); virtual void assertChannels()
virtual void assertChannels(); {
virtual void setPosition(Size position); bool null_data = true;
virtual int evaluate(size_t feature_ind) const; for( size_t i = 0; i < channels_.size(); ++i )
virtual void evaluateAll(OutputArray feature_values) const; null_data &= isNull(channels_[i]);
CV_Assert(!null_data);
}
virtual void evaluateAll(OutputArray feature_values) const
{
Mat_<int> feature_vals(1, (int)features_.size());
for( int i = 0; i < (int)features_.size(); ++i )
{
feature_vals(0, i) = evaluate(i);
}
feature_values.assign(feature_vals);
}
private: protected:
/* Features to evaluate */ /* Features to evaluate */
std::vector<Point3i> features_; vector<vector<int> > features_;
/* Channels for feature evaluation */ /* Channels for feature evaluation */
std::vector<Mat> channels_; std::vector<Mat> channels_;
/* Channels window position */ /* Channels window position */
Size position_; Size position_;
}; };
class ICFFeatureEvaluatorImpl : public FeatureEvaluatorImpl
static bool isNull(const Mat_<int> &m)
{ {
bool null_data = true; public:
for( int row = 0; row < m.rows; ++row ) ICFFeatureEvaluatorImpl(const vector<vector<int> >& features):
FeatureEvaluatorImpl(features)
{ {
for( int col = 0; col < m.cols; ++col )
if( m.at<int>(row, col) )
null_data = false;
} }
return null_data;
}
void ACFFeatureEvaluatorImpl::assertChannels() virtual void setChannels(InputArrayOfArrays channels);
{ virtual void setPosition(Size position);
bool null_data = true; virtual int evaluate(size_t feature_ind) const;
for( size_t i = 0; i < channels_.size(); ++i ) };
null_data &= isNull(channels_[i]);
CV_Assert(!null_data);
}
void ACFFeatureEvaluatorImpl::setChannels(cv::InputArrayOfArrays channels) void ICFFeatureEvaluatorImpl::setChannels(InputArrayOfArrays channels)
{ {
channels_.clear(); channels_.clear();
vector<Mat> ch; vector<Mat> ch;
channels.getMatVector(ch); channels.getMatVector(ch);
CV_Assert(ch.size() == 10); CV_Assert(ch.size() == 10);
/*int min_val = 100500, max_val = -1;
for( size_t i = 0; i < ch.size(); ++i ) for( size_t i = 0; i < ch.size(); ++i )
{ {
const Mat &channel = ch[i]; const Mat &channel = ch[i];
for( int row = 0; row < channel.rows; ++row ) Mat integral_channel;
for( int col = 0; col < channel.cols; ++col ) integral(channel, integral_channel, CV_32F);
{ Mat_<int> chan(integral_channel.rows, integral_channel.cols);
int val = (int)channel.at<float>(row, col); for( int row = 0; row < integral_channel.rows; ++row )
if( val < min_val ) for( int col = 0; col < integral_channel.cols; ++col )
min_val = val; chan(row, col) = (int)integral_channel.at<float>(row, col);
else if( val > max_val ) channels_.push_back(chan.clone());
max_val = val;
}
} }
}
void ICFFeatureEvaluatorImpl::setPosition(Size position)
{
position_ = position;
}
int ICFFeatureEvaluatorImpl::evaluate(size_t feature_ind) const
{
CV_Assert(channels_.size() == 10);
CV_Assert(feature_ind < features_.size());
const vector<int>& feature = features_[feature_ind];
int x = feature[0] + position_.height;
int y = feature[1] + position_.width;
int x_to = feature[2] + position_.height;
int y_to = feature[3] + position_.width;
int n = feature[4];
const Mat_<int>& ch = channels_[n];
return ch(y_to + 1, x_to + 1) - ch(y, x_to + 1) - ch(y_to + 1, x) + ch(y, x);
}
class ACFFeatureEvaluatorImpl : public FeatureEvaluatorImpl
{
public:
ACFFeatureEvaluatorImpl(const vector<vector<int> >& features):
FeatureEvaluatorImpl(features)
{
}
virtual void setChannels(InputArrayOfArrays channels);
virtual void setPosition(Size position);
virtual int evaluate(size_t feature_ind) const;
};
cout << "SET " << min_val << " " << max_val << endl; void ACFFeatureEvaluatorImpl::setChannels(InputArrayOfArrays channels)
*/ {
channels_.clear();
vector<Mat> ch;
channels.getMatVector(ch);
CV_Assert(ch.size() == 10);
for( size_t i = 0; i < ch.size(); ++i ) for( size_t i = 0; i < ch.size(); ++i )
{ {
...@@ -135,11 +186,7 @@ void ACFFeatureEvaluatorImpl::setChannels(cv::InputArrayOfArrays channels) ...@@ -135,11 +186,7 @@ void ACFFeatureEvaluatorImpl::setChannels(cv::InputArrayOfArrays channels)
int sum = 0; int sum = 0;
for( int cell_row = row; cell_row < row + 4; ++cell_row ) for( int cell_row = row; cell_row < row + 4; ++cell_row )
for( int cell_col = col; cell_col < col + 4; ++cell_col ) for( int cell_col = col; cell_col < col + 4; ++cell_col )
{
//cout << channel.rows << " " << channel.cols << endl;
//cout << cell_row << " " << cell_col << endl;
sum += (int)channel.at<float>(cell_row, cell_col); sum += (int)channel.at<float>(cell_row, cell_col);
}
acf_channel(row / 4, col / 4) = sum; acf_channel(row / 4, col / 4) = sum;
} }
...@@ -159,49 +206,66 @@ int ACFFeatureEvaluatorImpl::evaluate(size_t feature_ind) const ...@@ -159,49 +206,66 @@ int ACFFeatureEvaluatorImpl::evaluate(size_t feature_ind) const
CV_Assert(channels_.size() == 10); CV_Assert(channels_.size() == 10);
CV_Assert(feature_ind < features_.size()); CV_Assert(feature_ind < features_.size());
Point3i feature = features_.at(feature_ind); const vector<int>& feature = features_[feature_ind];
int x = feature.x; int x = feature[0];
int y = feature.y; int y = feature[1];
int n = feature.z; int n = feature[2];
return channels_[n].at<int>(y + position_.width, x + position_.height); return channels_[n].at<int>(y + position_.width, x + position_.height);
} }
void ACFFeatureEvaluatorImpl::evaluateAll(OutputArray feature_values) const Ptr<FeatureEvaluator> createFeatureEvaluator(
const vector<vector<int> >& features, const std::string& type)
{ {
Mat_<int> feature_vals(1, (int)features_.size()); FeatureEvaluator *evaluator = NULL;
for( int i = 0; i < (int)features_.size(); ++i ) if( type == "acf" )
{ evaluator = new ACFFeatureEvaluatorImpl(features);
feature_vals(0, i) = evaluate(i); else if( type == "icf" )
} evaluator = new ICFFeatureEvaluatorImpl(features);
feature_values.assign(feature_vals); else
CV_Assert(false);
return Ptr<FeatureEvaluator>(evaluator);
} }
Ptr<ACFFeatureEvaluator> vector<vector<int> > generateFeatures(Size window_size, const std::string& type,
createACFFeatureEvaluator(const vector<Point3i>& features) int count, int channel_count)
{
return Ptr<ACFFeatureEvaluator>(new ACFFeatureEvaluatorImpl(features));
}
vector<Point3i> generateFeatures(Size window_size, int count)
{ {
CV_Assert(count > 0); CV_Assert(count > 0);
int cur_count = 0; vector<vector<int> > features;
int max_count = window_size.width * window_size.height / 16; if( type == "acf" )
count = min(count, max_count);
vector<Point3i> features;
for( int x = 0; x < window_size.width / 4; ++x )
{ {
for( int y = 0; y < window_size.height / 4; ++y ) int cur_count = 0;
int max_count = window_size.width * window_size.height / 16;
count = min(count, max_count);
for( int x = 0; x < window_size.width / 4; ++x )
for( int y = 0; y < window_size.height / 4; ++y )
for( int n = 0; n < channel_count; ++n )
{
int f[] = {x, y, n};
vector<int> feature(f, f + sizeof(f) / sizeof(*f));
features.push_back(feature);
if( (cur_count += 1) == count )
break;
}
}
else if( type == "icf" )
{
RNG rng;
for( int i = 0; i < count; ++i )
{ {
/* Assume there are 10 channel types */ int x = rng.uniform(0, window_size.width - 1);
for( int n = 0; n < 10; ++n ) int y = rng.uniform(0, window_size.height - 1);
{ int x_to = rng.uniform(x, window_size.width - 1);
features.push_back(Point3i(x, y, n)); int y_to = rng.uniform(y, window_size.height - 1);
if( (cur_count += 1) == count ) int n = rng.uniform(0, channel_count - 1);
break; int f[] = {x, y, x_to, y_to, n};
} vector<int> feature(f, f + sizeof(f) / sizeof(*f));
features.push_back(feature);
} }
} }
else
CV_Assert(false);
return features; return features;
} }
......
...@@ -118,8 +118,9 @@ void ICFDetector::train(const String& pos_path, ...@@ -118,8 +118,9 @@ void ICFDetector::train(const String& pos_path,
for( int i = pos_count; i < pos_count + neg_count; ++i ) for( int i = pos_count; i < pos_count + neg_count; ++i )
labels(0, i) = -1; labels(0, i) = -1;
vector<Point3i> features = generateFeatures(model_size); vector<vector<int> > features = generateFeatures(model_size, "icf",
Ptr<ACFFeatureEvaluator> feature_evaluator = createACFFeatureEvaluator(features); params.feature_count);
Ptr<FeatureEvaluator> evaluator = createFeatureEvaluator(features, "icf");
Mat_<int> data = Mat_<int>::zeros((int)features.size(), (int)samples.size()); Mat_<int> data = Mat_<int>::zeros((int)features.size(), (int)samples.size());
Mat_<int> feature_col(1, (int)samples.size()); Mat_<int> feature_col(1, (int)samples.size());
...@@ -129,9 +130,9 @@ void ICFDetector::train(const String& pos_path, ...@@ -129,9 +130,9 @@ void ICFDetector::train(const String& pos_path,
{ {
cout << setw(6) << i << "/" << samples.size() << "\r"; cout << setw(6) << i << "/" << samples.size() << "\r";
computeChannels(samples[i], channels); computeChannels(samples[i], channels);
feature_evaluator->setChannels(channels); evaluator->setChannels(channels);
//feature_evaluator->assertChannels(); //evaluator->assertChannels();
feature_evaluator->evaluateAll(feature_col); evaluator->evaluateAll(feature_col);
CV_Assert(feature_col.cols == (int)features.size()); CV_Assert(feature_col.cols == (int)features.size());
...@@ -180,7 +181,7 @@ void ICFDetector::read(const FileNode& node) ...@@ -180,7 +181,7 @@ void ICFDetector::read(const FileNode& node)
node["waldboost"] >> *waldboost_; node["waldboost"] >> *waldboost_;
FileNode features = node["features"]; FileNode features = node["features"];
features_.clear(); features_.clear();
Point3i p; vector<int> p;
for( FileNodeIterator n = features.begin(); n != features.end(); ++n ) for( FileNodeIterator n = features.begin(); n != features.end(); ++n )
{ {
(*n) >> p; (*n) >> p;
...@@ -196,7 +197,7 @@ void ICFDetector::detect(const Mat& img, vector<Rect>& objects, ...@@ -196,7 +197,7 @@ void ICFDetector::detect(const Mat& img, vector<Rect>& objects,
float scale_to = max(model_n_cols_ / (float)minSize.width, float scale_to = max(model_n_cols_ / (float)minSize.width,
model_n_rows_ / (float)minSize.height); model_n_rows_ / (float)minSize.height);
objects.clear(); objects.clear();
Ptr<ACFFeatureEvaluator> evaluator = createACFFeatureEvaluator(features_); Ptr<FeatureEvaluator> evaluator = createFeatureEvaluator(features_, "icf");
Mat rescaled_image; Mat rescaled_image;
int step = 8; int step = 8;
vector<Mat> channels; vector<Mat> channels;
......
...@@ -67,7 +67,7 @@ public: ...@@ -67,7 +67,7 @@ public:
const Mat& labels); const Mat& labels);
virtual float predict( virtual float predict(
const Ptr<ACFFeatureEvaluator>& feature_evaluator) const; const Ptr<FeatureEvaluator>& feature_evaluator) const;
virtual void write(FileStorage& fs) const; virtual void write(FileStorage& fs) const;
...@@ -299,7 +299,7 @@ vector<int> WaldBoostImpl::train(const Mat& data_, const Mat& labels_) ...@@ -299,7 +299,7 @@ vector<int> WaldBoostImpl::train(const Mat& data_, const Mat& labels_)
} }
float WaldBoostImpl::predict( float WaldBoostImpl::predict(
const Ptr<ACFFeatureEvaluator>& feature_evaluator) const const Ptr<FeatureEvaluator>& feature_evaluator) const
{ {
float trace = 0; float trace = 0;
CV_Assert(stumps_.size() == thresholds_.size()); CV_Assert(stumps_.size() == thresholds_.size());
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment