Add icf feature evaluator

pull/40/head
Vlad Shakhuro 11 years ago
parent 5ff271efce
commit 479f71ef3e
  1. 25
      modules/xobjdetect/include/opencv2/xobjdetect.hpp
  2. 210
      modules/xobjdetect/src/acffeature.cpp
  3. 15
      modules/xobjdetect/src/icfdetector.cpp
  4. 4
      modules/xobjdetect/src/waldboost.cpp

@ -58,9 +58,9 @@ namespace xobjdetect
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:
/* Set channels for feature evaluation */
@ -69,8 +69,6 @@ public:
/* Set window position */
virtual void setPosition(Size position) = 0;
virtual void assertChannels() = 0;
/* Evaluate feature with given index for current channels
and window position */
virtual int evaluate(size_t feature_ind) const = 0;
@ -81,23 +79,28 @@ public:
*/
virtual void evaluateAll(OutputArray feature_values) const = 0;
virtual void assertChannels() = 0;
};
/* Construct evaluator, set features to evaluate */
CV_EXPORTS Ptr<ACFFeatureEvaluator>
createACFFeatureEvaluator(const std::vector<Point3i>& features);
/* Construct feature evaluator, set features to evaluate
type can "icf" or "acf" */
CV_EXPORTS Ptr<FeatureEvaluator>
createFeatureEvaluator(const std::vector<std::vector<int> >& features,
const std::string& type);
/* Generate acf features
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.
Max number of features is min(count, # possible distinct features)
Returns vector of distinct acf features
*/
std::vector<Point3i>
generateFeatures(Size window_size, int count = INT_MAX);
std::vector<std::vector<int> >
generateFeatures(Size window_size, const std::string& type,
int count = INT_MAX, int channel_count = 10);
struct CV_EXPORTS WaldBoostParams
@ -135,7 +138,7 @@ public:
is from class +1
*/
virtual float predict(
const Ptr<ACFFeatureEvaluator>& /*feature_evaluator*/) const
const Ptr<FeatureEvaluator>& /*feature_evaluator*/) const
{return 0.0f;}
/* Write WaldBoost to FileStorage */
@ -207,7 +210,7 @@ public:
private:
Ptr<WaldBoost> waldboost_;
std::vector<Point3i> features_;
std::vector<std::vector<int> > features_;
int model_n_rows_;
int model_n_cols_;
};

@ -54,75 +54,126 @@ namespace cv
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:
ACFFeatureEvaluatorImpl(const vector<Point3i>& features):
FeatureEvaluatorImpl(const vector<vector<int> >& features):
features_(features), channels_(), position_()
{
CV_Assert(features.size() > 0);
}
virtual void setChannels(InputArrayOfArrays channels);
virtual void assertChannels();
virtual void setPosition(Size position);
virtual int evaluate(size_t feature_ind) const;
virtual void evaluateAll(OutputArray feature_values) const;
virtual void assertChannels()
{
bool null_data = true;
for( size_t i = 0; i < channels_.size(); ++i )
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 */
std::vector<Point3i> features_;
vector<vector<int> > features_;
/* Channels for feature evaluation */
std::vector<Mat> channels_;
/* Channels window position */
Size position_;
};
static bool isNull(const Mat_<int> &m)
class ICFFeatureEvaluatorImpl : public FeatureEvaluatorImpl
{
bool null_data = true;
for( int row = 0; row < m.rows; ++row )
public:
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()
{
bool null_data = true;
for( size_t i = 0; i < channels_.size(); ++i )
null_data &= isNull(channels_[i]);
CV_Assert(!null_data);
}
virtual void setChannels(InputArrayOfArrays channels);
virtual void setPosition(Size position);
virtual int evaluate(size_t feature_ind) const;
};
void ACFFeatureEvaluatorImpl::setChannels(cv::InputArrayOfArrays channels)
void ICFFeatureEvaluatorImpl::setChannels(InputArrayOfArrays channels)
{
channels_.clear();
vector<Mat> ch;
channels.getMatVector(ch);
CV_Assert(ch.size() == 10);
/*int min_val = 100500, max_val = -1;
for( size_t i = 0; i < ch.size(); ++i )
{
const Mat &channel = ch[i];
for( int row = 0; row < channel.rows; ++row )
for( int col = 0; col < channel.cols; ++col )
{
int val = (int)channel.at<float>(row, col);
if( val < min_val )
min_val = val;
else if( val > max_val )
max_val = val;
}
Mat integral_channel;
integral(channel, integral_channel, CV_32F);
Mat_<int> chan(integral_channel.rows, integral_channel.cols);
for( int row = 0; row < integral_channel.rows; ++row )
for( int col = 0; col < integral_channel.cols; ++col )
chan(row, col) = (int)integral_channel.at<float>(row, col);
channels_.push_back(chan.clone());
}
}
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 )
{
@ -135,11 +186,7 @@ void ACFFeatureEvaluatorImpl::setChannels(cv::InputArrayOfArrays channels)
int sum = 0;
for( int cell_row = row; cell_row < row + 4; ++cell_row )
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);
}
acf_channel(row / 4, col / 4) = sum;
}
@ -159,49 +206,66 @@ int ACFFeatureEvaluatorImpl::evaluate(size_t feature_ind) const
CV_Assert(channels_.size() == 10);
CV_Assert(feature_ind < features_.size());
Point3i feature = features_.at(feature_ind);
int x = feature.x;
int y = feature.y;
int n = feature.z;
const vector<int>& feature = features_[feature_ind];
int x = feature[0];
int y = feature[1];
int n = feature[2];
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());
for( int i = 0; i < (int)features_.size(); ++i )
{
feature_vals(0, i) = evaluate(i);
}
feature_values.assign(feature_vals);
FeatureEvaluator *evaluator = NULL;
if( type == "acf" )
evaluator = new ACFFeatureEvaluatorImpl(features);
else if( type == "icf" )
evaluator = new ICFFeatureEvaluatorImpl(features);
else
CV_Assert(false);
return Ptr<FeatureEvaluator>(evaluator);
}
Ptr<ACFFeatureEvaluator>
createACFFeatureEvaluator(const vector<Point3i>& features)
{
return Ptr<ACFFeatureEvaluator>(new ACFFeatureEvaluatorImpl(features));
}
vector<Point3i> generateFeatures(Size window_size, int count)
vector<vector<int> > generateFeatures(Size window_size, const std::string& type,
int count, int channel_count)
{
CV_Assert(count > 0);
int cur_count = 0;
int max_count = window_size.width * window_size.height / 16;
count = min(count, max_count);
vector<Point3i> features;
for( int x = 0; x < window_size.width / 4; ++x )
vector<vector<int> > features;
if( type == "acf" )
{
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 */
for( int n = 0; n < 10; ++n )
{
features.push_back(Point3i(x, y, n));
if( (cur_count += 1) == count )
break;
}
int x = rng.uniform(0, window_size.width - 1);
int y = rng.uniform(0, window_size.height - 1);
int x_to = rng.uniform(x, window_size.width - 1);
int y_to = rng.uniform(y, window_size.height - 1);
int n = rng.uniform(0, channel_count - 1);
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;
}

@ -118,8 +118,9 @@ void ICFDetector::train(const String& pos_path,
for( int i = pos_count; i < pos_count + neg_count; ++i )
labels(0, i) = -1;
vector<Point3i> features = generateFeatures(model_size);
Ptr<ACFFeatureEvaluator> feature_evaluator = createACFFeatureEvaluator(features);
vector<vector<int> > features = generateFeatures(model_size, "icf",
params.feature_count);
Ptr<FeatureEvaluator> evaluator = createFeatureEvaluator(features, "icf");
Mat_<int> data = Mat_<int>::zeros((int)features.size(), (int)samples.size());
Mat_<int> feature_col(1, (int)samples.size());
@ -129,9 +130,9 @@ void ICFDetector::train(const String& pos_path,
{
cout << setw(6) << i << "/" << samples.size() << "\r";
computeChannels(samples[i], channels);
feature_evaluator->setChannels(channels);
//feature_evaluator->assertChannels();
feature_evaluator->evaluateAll(feature_col);
evaluator->setChannels(channels);
//evaluator->assertChannels();
evaluator->evaluateAll(feature_col);
CV_Assert(feature_col.cols == (int)features.size());
@ -180,7 +181,7 @@ void ICFDetector::read(const FileNode& node)
node["waldboost"] >> *waldboost_;
FileNode features = node["features"];
features_.clear();
Point3i p;
vector<int> p;
for( FileNodeIterator n = features.begin(); n != features.end(); ++n )
{
(*n) >> p;
@ -196,7 +197,7 @@ void ICFDetector::detect(const Mat& img, vector<Rect>& objects,
float scale_to = max(model_n_cols_ / (float)minSize.width,
model_n_rows_ / (float)minSize.height);
objects.clear();
Ptr<ACFFeatureEvaluator> evaluator = createACFFeatureEvaluator(features_);
Ptr<FeatureEvaluator> evaluator = createFeatureEvaluator(features_, "icf");
Mat rescaled_image;
int step = 8;
vector<Mat> channels;

@ -67,7 +67,7 @@ public:
const Mat& labels);
virtual float predict(
const Ptr<ACFFeatureEvaluator>& feature_evaluator) const;
const Ptr<FeatureEvaluator>& feature_evaluator) const;
virtual void write(FileStorage& fs) const;
@ -299,7 +299,7 @@ vector<int> WaldBoostImpl::train(const Mat& data_, const Mat& labels_)
}
float WaldBoostImpl::predict(
const Ptr<ACFFeatureEvaluator>& feature_evaluator) const
const Ptr<FeatureEvaluator>& feature_evaluator) const
{
float trace = 0;
CV_Assert(stumps_.size() == thresholds_.size());

Loading…
Cancel
Save