Commit 32ed1bf8 authored by Vadim Pisarevsky's avatar Vadim Pisarevsky

added phaseCorrelate function by Will Lucas.

parent c26b0053
......@@ -139,3 +139,67 @@ The function supports multi-channel images. Each channel is processed independen
:ocv:func:`accumulate`,
:ocv:func:`accumulateSquare`,
:ocv:func:`accumulateProduct`
phaseCorrelate
-------------------------------
The function is used to detect translational shifts that occur between two images. The operation takes advantage of the Fourier shift theorem for detecting the translational shift in the frequency domain. It can be used for fast image registration as well as motion esitimation. For more information please see http://http://en.wikipedia.org/wiki/Phase\_correlation .
Calculates the cross-power spectrum of two supplied source arrays. The arrays are padded if needed with ``getOptimalDFTSize`` .
.. ocv:function:: Point2d phaseCorrelate(InputArray src1, InputArray src2, InputArray window = noArray())
:param src1: Source floating point array (CV_32FC1 or CV_64FC1)
:param src2: Source floating point array (CV_32FC1 or CV_64FC1)
:param window: Floating point array with windowing coefficients to reduce edge effects (optional).
:param result: Detected phase shift (sub-pixel) between the two arrays.
The function performs the following equations
*
First it applies a Hanning window (see http://en.wikipedia.org/wiki/Hann\_function) to each image to remove possible edge effects. This window is cached until the array size changes to speed up processing time.
*
Next it computes the forward DFTs of each source array:
..math:
\mathbf{G}_a = \mathcal{F}\{src_1\}, \; \mathbf{G}_b = \mathcal{F}\{src_2\}
where
:math:`\mathcal{F} is the forward DFT.`
*
It then computes the cross-power spectrum of each frequency domain array:
..math:
R = \frac{ \mathbf{G}_a \mathbf{G}_b^*}{|\mathbf{G}_a \mathbf{G}_b^*|}
*
Next the cross-correlation is converted back into the time domain via the inverse DFT:
..math:
r = \mathcal{F}^{-1}\{R\}
*
Finally, it computes the peak location and computes a 5x5 weighted centroid around the peak to achieve sub-pixel accuracy.
..math:
(\Delta x, \Delta y) = \textrm{weighted_centroid}\{\arg \max_{(x, y)}\{r\}\}
.. seealso::
:ocv:func:`dft`,
:ocv:func:`getOptimalDFTSize`,
:ocv:func:`idft`,
:ocv:func:`mulSpectrums`
:ocv:func:`createHanningWindow`
createHanningWindow
-------------------------------
This function computes a Hanning window coefficients in two dimensions. See http://en.wikipedia.org/wiki/Hann\_function and http://en.wikipedia.org/wiki/Window\_function for more information.
.. ocv:function:: void createHanningWindow(OutputArray dst, Size winSize, int type)
:param dst: Destination array to place Hann coefficients in
:param winSize: The window size specifications
:param type: Created array type
::
// create hanning window of size 100x100 and type CV_32F
Mat hann;
createHanningWindow(hann, Size(100, 100), CV_32F);
.. seealso::
:ocv:func:`phaseCorrelate`
......@@ -1132,6 +1132,14 @@ struct CvLSHOperations
virtual int hash_lookup(lsh_hash h, int l, int* ret_i, int ret_i_max) = 0;
};
namespace cv
{
CV_EXPORTS_W cv::Point2d phaseCorrelate(InputArray _src1, InputArray _src2, InputArray window = noArray());
CV_EXPORTS_W void createHanningWindow(OutputArray _dst, cv::Size winSize, int type);
}
#endif /* __cplusplus */
#endif
......
This diff is collapsed.
/*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 "test_precomp.hpp"
using namespace cv;
using namespace std;
namespace cvtest
{
/// phase correlation
class CV_PhaseCorrelatorTest : public cvtest::ArrayTest
{
public:
CV_PhaseCorrelatorTest();
protected:
void run( int );
};
CV_PhaseCorrelatorTest::CV_PhaseCorrelatorTest() {}
void CV_PhaseCorrelatorTest::run( int )
{
ts->set_failed_test_info(cvtest::TS::OK);
Mat r1 = Mat::ones(Size(128, 128), CV_64F);
Mat r2 = Mat::ones(Size(128, 128), CV_64F);
double expectedShiftX = -10.0;
double expectedShiftY = -20.0;
// draw 10x10 rectangles @ (100, 100) and (90, 80) should see ~(-10, -20) shift here...
cv::rectangle(r1, Point(100, 100), Point(110, 110), Scalar(0, 0, 0), CV_FILLED);
cv::rectangle(r2, Point(90, 80), Point(100, 90), Scalar(0, 0, 0), CV_FILLED);
Mat hann;
createHanningWindow(hann, r1.size(), CV_64F);
Point2d phaseShift = phaseCorrelate(r1, r2, hann);
// test accuracy should be less than 1 pixel...
if((expectedShiftX - phaseShift.x) >= 1 || (expectedShiftY - phaseShift.y) >= 1)
{
ts->set_failed_test_info( cvtest::TS::FAIL_BAD_ACCURACY );
}
}
TEST(Imgproc_PhaseCorrelatorTest, accuracy) { CV_PhaseCorrelatorTest test; test.safe_run(); }
}
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
using namespace cv;
int main(int argc, char* argv[])
{
VideoCapture video(0);
Mat frame, curr, prev, curr64f, prev64f, hann;
int key = 0;
do
{
video >> frame;
cvtColor(frame, curr, CV_RGB2GRAY);
if(prev.empty())
{
prev = curr.clone();
createHanningWindow(hann, curr.size(), CV_64F);
}
prev.convertTo(prev64f, CV_64F);
curr.convertTo(curr64f, CV_64F);
Point2d shift = phaseCorrelate(prev64f, curr64f, hann);
double radius = cv::sqrt(shift.x*shift.x + shift.y*shift.y);
if(radius > 5)
{
// draw a circle and line indicating the shift direction...
Point center(curr.cols >> 1, curr.rows >> 1);
cv::circle(frame, center, (int)radius, cv::Scalar(0, 255, 0), 3, CV_AA);
cv::line(frame, center, Point(center.x + (int)shift.x, center.y + (int)shift.y), cv::Scalar(0, 255, 0), 3, CV_AA);
}
imshow("phase shift", frame);
key = waitKey(2);
prev = curr.clone();
} while((char)key != 27); // Esc to exit...
return 0;
}
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