Commit 17831add authored by Vladislav Samsonov's avatar Vladislav Samsonov

Added new method for training forest

parent 7f93d951
......@@ -63,20 +63,41 @@ namespace optflow
struct CV_EXPORTS_W GPCPatchDescriptor
{
static const unsigned nFeatures = 18; // number of features in a patch descriptor
Vec<double, nFeatures> feature;
Vec< double, nFeatures > feature;
GPCPatchDescriptor( const Mat *imgCh, int i, int j );
};
typedef std::pair<GPCPatchDescriptor, GPCPatchDescriptor> GPCPatchSample;
typedef std::vector<GPCPatchSample> GPCSamplesVector;
typedef std::pair< GPCPatchDescriptor, GPCPatchDescriptor > GPCPatchSample;
typedef std::vector< GPCPatchSample > GPCSamplesVector;
/** @brief Class encapsulating training samples.
*/
class CV_EXPORTS_W GPCTrainingSamples
{
private:
GPCSamplesVector samples;
public:
/** @brief This function can be used to extract samples from a pair of images and a ground truth flow.
* Sizes of all the provided vectors must be equal.
*/
static Ptr< GPCTrainingSamples > create( const std::vector< String > &imagesFrom, const std::vector< String > &imagesTo,
const std::vector< String > &gt );
size_t size() const { return samples.size(); }
operator GPCSamplesVector() const { return samples; }
operator GPCSamplesVector &() { return samples; }
};
class CV_EXPORTS_W GPCTree : public Algorithm
{
public:
struct Node
{
Vec<double, GPCPatchDescriptor::nFeatures> coef; // hyperplane coefficients
Vec< double, GPCPatchDescriptor::nFeatures > coef; // hyperplane coefficients
double rhs;
unsigned left;
unsigned right;
......@@ -87,7 +108,7 @@ public:
private:
typedef GPCSamplesVector::iterator SIter;
std::vector<Node> nodes;
std::vector< Node > nodes;
bool trainNode( size_t nodeId, SIter begin, SIter end, unsigned depth );
......@@ -98,23 +119,38 @@ public:
void read( const FileNode &fn );
static Ptr<GPCTree> create() { return makePtr<GPCTree>(); }
static Ptr< GPCTree > create() { return makePtr< GPCTree >(); }
bool operator==( const GPCTree &t ) const { return nodes == t.nodes; }
};
template <int T> class CV_EXPORTS_W GPCForest : public Algorithm
template < int T > class CV_EXPORTS_W GPCForest : public Algorithm
{
private:
GPCTree tree[T];
public:
/** @brief Train the forest using one sample set for every tree.
* Please, consider using the next method instead of this one for better quality.
*/
void train( GPCSamplesVector &samples )
{
for ( int i = 0; i < T; ++i )
tree[i].train( samples );
}
/** @brief Train the forest using individual samples for each tree.
* It is generally better to use this instead of the first method.
*/
void train( const std::vector< String > &imagesFrom, const std::vector< String > &imagesTo, const std::vector< String > &gt )
{
for ( int i = 0; i < T; ++i )
{
Ptr< GPCTrainingSamples > samples = GPCTrainingSamples::create( imagesFrom, imagesTo, gt ); // Create training set for the tree
tree[i].train( *samples );
}
}
void write( FileStorage &fs ) const
{
fs << "ntrees" << T << "trees"
......@@ -136,28 +172,7 @@ public:
tree[i].read( *it );
}
static Ptr<GPCForest> create() { return makePtr<GPCForest>(); }
};
/** @brief Class encapsulating training samples.
*/
class CV_EXPORTS_W GPCTrainingSamples
{
private:
GPCSamplesVector samples;
public:
/** @brief This function can be used to extract samples from a pair of images and a ground truth flow.
* Sizes of all the provided vectors must be equal.
*/
static Ptr<GPCTrainingSamples> create( const std::vector<String> &imagesFrom, const std::vector<String> &imagesTo,
const std::vector<String> &gt );
size_t size() const { return samples.size(); }
operator GPCSamplesVector() const { return samples; }
operator GPCSamplesVector &() { return samples; }
static Ptr< GPCForest > create() { return makePtr< GPCForest >(); }
};
}
......
......@@ -14,7 +14,7 @@ int main( int argc, const char **argv )
}
nSequences /= 3;
std::vector<cv::String> img1, img2, gt;
std::vector< cv::String > img1, img2, gt;
for ( int i = 0; i < nSequences; ++i )
{
......@@ -23,12 +23,8 @@ int main( int argc, const char **argv )
gt.push_back( argv[1 + i * 3 + 2] );
}
cv::Ptr<cv::optflow::GPCTrainingSamples> ts = cv::optflow::GPCTrainingSamples::create( img1, img2, gt );
std::cout << "Got " << ts->size() << " samples." << std::endl;
cv::Ptr< cv::optflow::GPCForest<nTrees> > forest = cv::optflow::GPCForest<nTrees>::create();
forest->train( *ts );
cv::Ptr< cv::optflow::GPCForest< nTrees > > forest = cv::optflow::GPCForest< nTrees >::create();
forest->train( img1, img2, gt );
forest->save( "forest.dump" );
return 0;
......
......@@ -72,10 +72,10 @@ struct Magnitude
struct PartitionPredicate1
{
Vec<double, GPCPatchDescriptor::nFeatures> coef;
Vec< double, GPCPatchDescriptor::nFeatures > coef;
double rhs;
PartitionPredicate1( const Vec<double, GPCPatchDescriptor::nFeatures> &_coef, double _rhs ) : coef( _coef ), rhs( _rhs ) {}
PartitionPredicate1( const Vec< double, GPCPatchDescriptor::nFeatures > &_coef, double _rhs ) : coef( _coef ), rhs( _rhs ) {}
bool operator()( const GPCPatchSample &sample ) const
{
......@@ -87,10 +87,10 @@ struct PartitionPredicate1
struct PartitionPredicate2
{
Vec<double, GPCPatchDescriptor::nFeatures> coef;
Vec< double, GPCPatchDescriptor::nFeatures > coef;
double rhs;
PartitionPredicate2( const Vec<double, GPCPatchDescriptor::nFeatures> &_coef, double _rhs ) : coef( _coef ), rhs( _rhs ) {}
PartitionPredicate2( const Vec< double, GPCPatchDescriptor::nFeatures > &_coef, double _rhs ) : coef( _coef ), rhs( _rhs ) {}
bool operator()( const GPCPatchSample &sample ) const
{
......@@ -110,13 +110,14 @@ bool checkBounds( int i, int j, Size sz )
void getTrainingSamples( const Mat &from, const Mat &to, const Mat &gt, GPCSamplesVector &samples )
{
const Size sz = gt.size();
std::vector<Magnitude> mag;
std::vector< Magnitude > mag;
for ( int i = patchRadius; i + patchRadius < sz.height; ++i )
for ( int j = patchRadius; j + patchRadius < sz.width; ++j )
mag.push_back( Magnitude( normL2Sqr( gt.at<Vec2f>( i, j ) ), i, j ) );
mag.push_back( Magnitude( normL2Sqr( gt.at< Vec2f >( i, j ) ), i, j ) );
size_t n = mag.size() * thresholdMagnitudeFrac;
size_t n = mag.size() * thresholdMagnitudeFrac; // As suggested in the paper, we discard part of the training samples
// with a small displacement and train to better distinguish hard pairs.
std::nth_element( mag.begin(), mag.begin() + n, mag.end() );
mag.resize( n );
std::random_shuffle( mag.begin(), mag.end() );
......@@ -131,8 +132,8 @@ void getTrainingSamples( const Mat &from, const Mat &to, const Mat &gt, GPCSampl
{
int i0 = mag[k].i;
int j0 = mag[k].j;
int i1 = i0 + cvRound( gt.at<Vec2f>( i0, j0 )[1] );
int j1 = j0 + cvRound( gt.at<Vec2f>( i0, j0 )[0] );
int i1 = i0 + cvRound( gt.at< Vec2f >( i0, j0 )[1] );
int j1 = j0 + cvRound( gt.at< Vec2f >( i0, j0 )[0] );
if ( checkBounds( i1, j1, sz ) )
samples.push_back( std::make_pair( GPCPatchDescriptor( fromCh, i0, j0 ), GPCPatchDescriptor( toCh, i1, j1 ) ) );
}
......@@ -149,7 +150,7 @@ double getRandomCauchyScalar()
/* Sample random vector from Cauchy distribution (pointwise, i.e. vector whose components are independent random
* variables from Cauchy distribution) */
void getRandomCauchyVector( Vec<double, GPCPatchDescriptor::nFeatures> &v )
void getRandomCauchyVector( Vec< double, GPCPatchDescriptor::nFeatures > &v )
{
for ( unsigned i = 0; i < GPCPatchDescriptor::nFeatures; ++i )
v[i] = getRandomCauchyScalar();
......@@ -162,25 +163,25 @@ GPCPatchDescriptor::GPCPatchDescriptor( const Mat *imgCh, int i, int j )
Mat freqDomain;
dct( imgCh[0]( roi ), freqDomain );
feature[0] = freqDomain.at<float>( 0, 0 );
feature[1] = freqDomain.at<float>( 0, 1 );
feature[2] = freqDomain.at<float>( 0, 2 );
feature[3] = freqDomain.at<float>( 0, 3 );
feature[0] = freqDomain.at< float >( 0, 0 );
feature[1] = freqDomain.at< float >( 0, 1 );
feature[2] = freqDomain.at< float >( 0, 2 );
feature[3] = freqDomain.at< float >( 0, 3 );
feature[4] = freqDomain.at<float>( 1, 0 );
feature[5] = freqDomain.at<float>( 1, 1 );
feature[6] = freqDomain.at<float>( 1, 2 );
feature[7] = freqDomain.at<float>( 1, 3 );
feature[4] = freqDomain.at< float >( 1, 0 );
feature[5] = freqDomain.at< float >( 1, 1 );
feature[6] = freqDomain.at< float >( 1, 2 );
feature[7] = freqDomain.at< float >( 1, 3 );
feature[8] = freqDomain.at<float>( 2, 0 );
feature[9] = freqDomain.at<float>( 2, 1 );
feature[10] = freqDomain.at<float>( 2, 2 );
feature[11] = freqDomain.at<float>( 2, 3 );
feature[8] = freqDomain.at< float >( 2, 0 );
feature[9] = freqDomain.at< float >( 2, 1 );
feature[10] = freqDomain.at< float >( 2, 2 );
feature[11] = freqDomain.at< float >( 2, 3 );
feature[12] = freqDomain.at<float>( 3, 0 );
feature[13] = freqDomain.at<float>( 3, 1 );
feature[14] = freqDomain.at<float>( 3, 2 );
feature[15] = freqDomain.at<float>( 3, 3 );
feature[12] = freqDomain.at< float >( 3, 0 );
feature[13] = freqDomain.at< float >( 3, 1 );
feature[14] = freqDomain.at< float >( 3, 2 );
feature[15] = freqDomain.at< float >( 3, 3 );
feature[16] = cv::sum( imgCh[1]( roi ) )[0] / ( 2 * patchRadius );
feature[17] = cv::sum( imgCh[2]( roi ) )[0] / ( 2 * patchRadius );
......@@ -198,11 +199,11 @@ bool GPCTree::trainNode( size_t nodeId, SIter begin, SIter end, unsigned depth )
// Select the best hyperplane
unsigned globalBestScore = 0;
std::vector<double> values;
std::vector< double > values;
for ( int j = 0; j < globalIters; ++j )
{ // Global search step
Vec<double, GPCPatchDescriptor::nFeatures> coef;
Vec< double, GPCPatchDescriptor::nFeatures > coef;
unsigned localBestScore = 0;
getRandomCauchyVector( coef );
......@@ -280,13 +281,13 @@ void GPCTree::write( FileStorage &fs ) const
void GPCTree::read( const FileNode &fn ) { fn["nodes"] >> nodes; }
Ptr<GPCTrainingSamples> GPCTrainingSamples::create( const std::vector<String> &imagesFrom, const std::vector<String> &imagesTo,
const std::vector<String> &gt )
Ptr< GPCTrainingSamples > GPCTrainingSamples::create( const std::vector< String > &imagesFrom, const std::vector< String > &imagesTo,
const std::vector< String > &gt )
{
CV_Assert( imagesFrom.size() == imagesTo.size() );
CV_Assert( imagesFrom.size() == gt.size() );
Ptr<GPCTrainingSamples> ts = makePtr<GPCTrainingSamples>();
Ptr< GPCTrainingSamples > ts = makePtr< GPCTrainingSamples >();
for ( size_t i = 0; i < imagesFrom.size(); ++i )
{
Mat from = imread( imagesFrom[i] );
......
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