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

Add icf feature evaluator

parent 5ff271ef
......@@ -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());
......
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