Added naive blockmatching algorithm (just to get acquainted with the code base, this algo shouldn't be considered seriously).

Also, added boilerplate for pcaflow.
pull/710/head
Vladislav Samsonov 9 years ago
parent 46dd2631d6
commit fc00397160
  1. 4
      modules/optflow/include/opencv2/optflow.hpp
  2. 6
      modules/optflow/samples/optical_flow_evaluation.cpp
  3. 143
      modules/optflow/src/block_matching.cpp
  4. 148
      modules/optflow/src/pcaflow.cpp

@ -191,6 +191,10 @@ CV_EXPORTS_W Ptr<DenseOpticalFlow> createOptFlow_Farneback();
//! Additional interface to the SparseToDenseFlow algorithm - calcOpticalFlowSparseToDense()
CV_EXPORTS_W Ptr<DenseOpticalFlow> createOptFlow_SparseToDense();
CV_EXPORTS_W Ptr<DenseOpticalFlow> createOptFlow_BlockMatching();
CV_EXPORTS_W Ptr<DenseOpticalFlow> createOptFlow_PCAFlow();
//! @}
} //optflow

@ -11,7 +11,7 @@ using namespace optflow;
const String keys = "{help h usage ? | | print this message }"
"{@image1 | | image1 }"
"{@image2 | | image2 }"
"{@algorithm | | [farneback, simpleflow, tvl1, deepflow or sparsetodenseflow] }"
"{@algorithm | | [farneback, simpleflow, tvl1, deepflow, pcaflow, blockmatching or sparsetodenseflow] }"
"{@groundtruth | | path to the .flo file (optional), Middlebury format }"
"{m measure |endpoint| error measure - [endpoint or angular] }"
"{r region |all | region to compute stats about [all, discontinuities, untextured] }"
@ -252,6 +252,10 @@ int main( int argc, char** argv )
algorithm = createOptFlow_DeepFlow();
else if ( method == "sparsetodenseflow" )
algorithm = createOptFlow_SparseToDense();
else if ( method == "blockmatching" )
algorithm = createOptFlow_BlockMatching();
else if ( method == "pcaflow" )
algorithm = createOptFlow_PCAFlow();
else
{
printf("Wrong method!\n");

@ -0,0 +1,143 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
namespace cv
{
namespace optflow
{
class OpticalFlowBlockMatching : public DenseOpticalFlow
{
protected:
int windowSize;
int blockSize;
inline float submatrixAbsDiff( int x0, int y0, const Mat &I0, int x1, int y1, const Mat &I1 ) const;
public:
OpticalFlowBlockMatching() : windowSize( 3 ), blockSize( 8 ){};
void calc( InputArray I0, InputArray I1, InputOutputArray flow );
void collectGarbage();
};
inline float OpticalFlowBlockMatching::submatrixAbsDiff( int x0, int y0, const Mat &I0, int x1, int y1,
const Mat &I1 ) const
{
float error = 0;
const Size size = I0.size();
for ( int i = -windowSize; i <= windowSize; ++i )
{
if ( i + y0 < 0 || i + y0 >= size.height || i + y1 < 0 || i + y1 >= size.height )
{
error += 1;
continue;
}
const Vec3f *I0X = I0.ptr<Vec3f>( i + y0 );
const Vec3f *I1X = I1.ptr<Vec3f>( i + y1 );
for ( int j = -windowSize; j <= windowSize; ++j )
{
if ( j + x0 < 0 || j + x0 >= size.width || j + x1 < 0 || j + x1 >= size.width )
{
error += 1;
continue;
}
const Vec3f diff = I0X[j + x0] - I1X[j + x1];
error += abs( diff[0] );
error += abs( diff[1] );
error += abs( diff[2] );
}
}
return error;
}
void OpticalFlowBlockMatching::calc( InputArray I0, InputArray I1, InputOutputArray flow_out )
{
CV_Assert( I0.channels() == 3 );
CV_Assert( I1.channels() == 3 );
Size size = I0.size();
CV_Assert( size == I1.size() );
flow_out.create( size, CV_32FC2 );
Mat flow = flow_out.getMat();
Mat from = I0.getMat();
Mat to = I1.getMat();
from.convertTo( from, CV_32FC3, 1.0 / 255.0 );
to.convertTo( to, CV_32FC3, 1.0 / 255.0 );
const float distNormalize = blockSize * sqrt( 2 );
for ( int y0 = 0; y0 < size.height; ++y0 )
{
Vec2f *flowX = flow.ptr<Vec2f>( y0 );
const int yEnd = std::min( size.height - 1, y0 + blockSize );
for ( int x0 = 0; x0 < size.width; ++x0 )
{
float minDiff = 1e10;
Vec2f du( 0, 0 );
const int xEnd = std::min( size.width - 1, x0 + blockSize );
for ( int y1 = std::max( 0, y0 - blockSize ); y1 <= yEnd; ++y1 )
for ( int x1 = std::max( 0, x0 - blockSize ); x1 <= xEnd; ++x1 )
{
const float distance = sqrt( ( x0 - x1 ) * ( x0 - x1 ) + ( y0 - y1 ) * ( y0 - y1 ) ) / distNormalize;
const float kernel = 1.0 + 0.5 * distance;
const float diff = kernel * submatrixAbsDiff( x0, y0, from, x1, y1, to );
if ( diff < minDiff )
{
minDiff = diff;
du = Vec2f( ( x1 - x0 ), ( y1 - y0 ) );
}
}
flowX[x0] = du;
}
}
}
void OpticalFlowBlockMatching::collectGarbage() {}
Ptr<DenseOpticalFlow> createOptFlow_BlockMatching() { return makePtr<OpticalFlowBlockMatching>(); }
}
}

@ -0,0 +1,148 @@
/*M///////////////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
//
// By downloading, copying, installing or using the software you agree to this license.
// If you do not agree to this license, do not download, install,
// copy or use the software.
//
//
// License Agreement
// For Open Source Computer Vision Library
//
// Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
// Copyright (C) 2009, Willow Garage Inc., all rights reserved.
// Third party copyrights are property of their respective owners.
//
// Redistribution and use in source and binary forms, with or without modification,
// are permitted provided that the following conditions are met:
//
// * Redistribution's of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistribution's in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * The name of the copyright holders may not be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// This software is provided by the copyright holders and contributors "as is" and
// any express or implied warranties, including, but not limited to, the implied
// warranties of merchantability and fitness for a particular purpose are disclaimed.
// In no event shall the Intel Corporation or contributors be liable for any direct,
// indirect, incidental, special, exemplary, or consequential damages
// (including, but not limited to, procurement of substitute goods or services;
// loss of use, data, or profits; or business interruption) however caused
// and on any theory of liability, whether in contract, strict liability,
// or tort (including negligence or otherwise) arising in any way out of
// the use of this software, even if advised of the possibility of such damage.
//
//M*/
#include "precomp.hpp"
namespace cv
{
namespace optflow
{
class OpticalFlowPCAFlow : public DenseOpticalFlow
{
protected:
float sparseRate;
public:
OpticalFlowPCAFlow() : sparseRate( 0.02 ){};
void calc( InputArray I0, InputArray I1, InputOutputArray flow );
void collectGarbage();
private:
void findSparseFeatures( Mat &from, Mat &to, std::vector<Point2f> &features,
std::vector<Point2f> &predictedFeatures );
};
void OpticalFlowPCAFlow::findSparseFeatures( Mat &from, Mat &to, std::vector<Point2f> &features,
std::vector<Point2f> &predictedFeatures )
{
std::vector<uchar> predictedStatus;
std::vector<float> predictedError;
calcOpticalFlowPyrLK( from, to, features, predictedFeatures, predictedStatus, predictedError );
size_t j = 0;
for ( size_t i = 0; i < features.size(); ++i )
{
if ( predictedStatus[i] )
{
features[j] = features[i];
predictedFeatures[j] = predictedFeatures[i];
++j;
}
}
features.resize( j );
predictedFeatures.resize( j );
}
void OpticalFlowPCAFlow::calc( InputArray I0, InputArray I1, InputOutputArray flow_out )
{
Size size = I0.size();
CV_Assert( size == I1.size() );
CV_Assert( sparseRate > 0 && sparseRate < 0.1 );
Mat from, to;
if ( I0.channels() == 3 )
{
cvtColor( I0, from, COLOR_BGR2GRAY );
from.convertTo( from, CV_8U );
}
else
{
I0.getMat().convertTo( from, CV_8U );
}
if ( I1.channels() == 3 )
{
cvtColor( I1, to, COLOR_BGR2GRAY );
to.convertTo( to, CV_8U );
}
else
{
I1.getMat().convertTo( to, CV_8U );
}
CV_Assert( from.channels() == 1 );
CV_Assert( to.channels() == 1 );
std::vector<Point2f> features, predictedFeatures;
const unsigned maxFeatures = size.area() * sparseRate;
goodFeaturesToTrack( from, features, maxFeatures, 0.005, 3 );
// Add points along the grid if not enough features
{
const unsigned missingPoints = maxFeatures - features.size();
const unsigned blockSize = sqrt( (float)size.area() / missingPoints );
for ( int x = blockSize / 2; x < size.width; x += blockSize )
for ( int y = blockSize / 2; y < size.height; y += blockSize )
features.push_back( Point2f( x, y ) );
}
findSparseFeatures( from, to, features, predictedFeatures );
// TODO: Remove occlusions
flow_out.create( size, CV_32FC2 );
Mat flow = flow_out.getMat();
for ( size_t i = 0; i < features.size(); ++i )
{
flow.at<Point2f>( features[i].y, features[i].x ) = predictedFeatures[i] - features[i];
}
from.convertTo( from, CV_32F );
to.convertTo( to, CV_32F );
}
void OpticalFlowPCAFlow::collectGarbage() {}
Ptr<DenseOpticalFlow> createOptFlow_PCAFlow() { return makePtr<OpticalFlowPCAFlow>(); }
}
}
Loading…
Cancel
Save