mirror of
https://github.com/opencv/opencv_contrib.git
synced 2025-10-20 04:25:42 +08:00
Added naive blockmatching algorithm (just to get acquainted with the code base, this algo shouldn't be considered seriously).
Also, added boilerplate for pcaflow.
This commit is contained in:
@@ -191,6 +191,10 @@ CV_EXPORTS_W Ptr<DenseOpticalFlow> createOptFlow_Farneback();
|
|||||||
//! Additional interface to the SparseToDenseFlow algorithm - calcOpticalFlowSparseToDense()
|
//! Additional interface to the SparseToDenseFlow algorithm - calcOpticalFlowSparseToDense()
|
||||||
CV_EXPORTS_W Ptr<DenseOpticalFlow> createOptFlow_SparseToDense();
|
CV_EXPORTS_W Ptr<DenseOpticalFlow> createOptFlow_SparseToDense();
|
||||||
|
|
||||||
|
CV_EXPORTS_W Ptr<DenseOpticalFlow> createOptFlow_BlockMatching();
|
||||||
|
|
||||||
|
CV_EXPORTS_W Ptr<DenseOpticalFlow> createOptFlow_PCAFlow();
|
||||||
|
|
||||||
//! @}
|
//! @}
|
||||||
|
|
||||||
} //optflow
|
} //optflow
|
||||||
|
@@ -11,7 +11,7 @@ using namespace optflow;
|
|||||||
const String keys = "{help h usage ? | | print this message }"
|
const String keys = "{help h usage ? | | print this message }"
|
||||||
"{@image1 | | image1 }"
|
"{@image1 | | image1 }"
|
||||||
"{@image2 | | image2 }"
|
"{@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 }"
|
"{@groundtruth | | path to the .flo file (optional), Middlebury format }"
|
||||||
"{m measure |endpoint| error measure - [endpoint or angular] }"
|
"{m measure |endpoint| error measure - [endpoint or angular] }"
|
||||||
"{r region |all | region to compute stats about [all, discontinuities, untextured] }"
|
"{r region |all | region to compute stats about [all, discontinuities, untextured] }"
|
||||||
@@ -252,6 +252,10 @@ int main( int argc, char** argv )
|
|||||||
algorithm = createOptFlow_DeepFlow();
|
algorithm = createOptFlow_DeepFlow();
|
||||||
else if ( method == "sparsetodenseflow" )
|
else if ( method == "sparsetodenseflow" )
|
||||||
algorithm = createOptFlow_SparseToDense();
|
algorithm = createOptFlow_SparseToDense();
|
||||||
|
else if ( method == "blockmatching" )
|
||||||
|
algorithm = createOptFlow_BlockMatching();
|
||||||
|
else if ( method == "pcaflow" )
|
||||||
|
algorithm = createOptFlow_PCAFlow();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
printf("Wrong method!\n");
|
printf("Wrong method!\n");
|
||||||
|
143
modules/optflow/src/block_matching.cpp
Normal file
143
modules/optflow/src/block_matching.cpp
Normal file
@@ -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>(); }
|
||||||
|
}
|
||||||
|
}
|
148
modules/optflow/src/pcaflow.cpp
Normal file
148
modules/optflow/src/pcaflow.cpp
Normal file
@@ -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>(); }
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user