mirror of
https://github.com/opencv/opencv_contrib.git
synced 2025-10-16 22:35:51 +08:00
Add icf feature evaluator
This commit is contained in:
@@ -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,31 +54,6 @@ namespace cv
|
||||
namespace xobjdetect
|
||||
{
|
||||
|
||||
class ACFFeatureEvaluatorImpl : public ACFFeatureEvaluator
|
||||
{
|
||||
public:
|
||||
ACFFeatureEvaluatorImpl(const vector<Point3i>& 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;
|
||||
|
||||
private:
|
||||
/* Features to evaluate */
|
||||
std::vector<Point3i> features_;
|
||||
/* Channels for feature evaluation */
|
||||
std::vector<Mat> channels_;
|
||||
/* Channels window position */
|
||||
Size position_;
|
||||
};
|
||||
|
||||
|
||||
static bool isNull(const Mat_<int> &m)
|
||||
{
|
||||
bool null_data = true;
|
||||
@@ -91,38 +66,114 @@ static bool isNull(const Mat_<int> &m)
|
||||
return null_data;
|
||||
}
|
||||
|
||||
void ACFFeatureEvaluatorImpl::assertChannels()
|
||||
class FeatureEvaluatorImpl : public FeatureEvaluator
|
||||
{
|
||||
bool null_data = true;
|
||||
for( size_t i = 0; i < channels_.size(); ++i )
|
||||
null_data &= isNull(channels_[i]);
|
||||
CV_Assert(!null_data);
|
||||
}
|
||||
public:
|
||||
FeatureEvaluatorImpl(const vector<vector<int> >& features):
|
||||
features_(features), channels_(), position_()
|
||||
{
|
||||
CV_Assert(features.size() > 0);
|
||||
}
|
||||
|
||||
void ACFFeatureEvaluatorImpl::setChannels(cv::InputArrayOfArrays channels)
|
||||
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);
|
||||
}
|
||||
|
||||
protected:
|
||||
/* Features to evaluate */
|
||||
vector<vector<int> > features_;
|
||||
/* Channels for feature evaluation */
|
||||
std::vector<Mat> channels_;
|
||||
/* Channels window position */
|
||||
Size position_;
|
||||
};
|
||||
|
||||
class ICFFeatureEvaluatorImpl : public FeatureEvaluatorImpl
|
||||
{
|
||||
public:
|
||||
ICFFeatureEvaluatorImpl(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;
|
||||
};
|
||||
|
||||
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)
|
||||
{
|
||||
}
|
||||
|
||||
cout << "SET " << min_val << " " << max_val << endl;
|
||||
*/
|
||||
virtual void setChannels(InputArrayOfArrays channels);
|
||||
virtual void setPosition(Size position);
|
||||
virtual int evaluate(size_t feature_ind) const;
|
||||
};
|
||||
|
||||
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());
|
||||
|
Reference in New Issue
Block a user