I have been recently trying to find a fast and efficient way to perform cross correlation check between two arrays using Python language. After some reading, I found these two options:
NumPy.correlate()
method, which is too slow when it comes to large arrays.cv.MatchTemplate()
method, which seems to be much faster.For obvious reasons, I chose the second option. I tried to execute the following code:
import scipy
import cv
image = cv.fromarray(scipy.float32(scipy.asarray([1,2,2,1])),allowND=True)
template = cv.fromarray(scipy.float32(scipy.asarray([2,2])),allowND=True)
result = cv.fromarray(scipy.float32(scipy.asarray([0,0,0])),allowND=True)
cv.MatchTemplate(image,template,result,cv.CV_TM_CCORR)
Even though this code suppose to be very simple, it throws the next error:
OpenCV Error: Bad flag (parameter or structure field) (Unrecognized or unsupported array type) in cvGetMat, file /builddir/build/BUILD/OpenCV-2.1.0/src/cxcore/cxarray.cpp, line 2476
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
cv.error: Unrecognized or unsupported array type
After a few hours of frustrating tries, I am still stuck! Does anybody have any suggestion?
BTW, this is my Python version output:
Python 2.7 (r27:82500, Sep 16 2010, 18:03:06)
[GCC 4.5.1 20100907 (Red Hat 4.5.1-3)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
Thank you all!
Cross-correlation is an established and reliable tool to compute the degree to which the two seismic time-series are dependent on each other.
numpy.correlate() function defines the cross-correlation of two 1-dimensional sequences. This function computes the correlation as generally defined in signal processing texts: c_{av}[k] = sum_n a[n+k] * conj(v[n])
Cross-correlation is a measurement that tracks the movements of two or more sets of time series data relative to one another. It is used to compare multiple time series and objectively determine how well they match up with each other and, in particular, at what point the best match occurs.
The Pearson Correlation coefficient can be computed in Python using corrcoef() method from Numpy. The input for this function is typically a matrix, say of size mxn , where: Each column represents the values of a random variable. Each row represents a single sample of n random variables.
You're unlikely to get much faster than using an fft based correlation method.
import numpy
from scipy import signal
data_length = 8192
a = numpy.random.randn(data_length)
b = numpy.zeros(data_length * 2)
b[data_length/2:data_length/2+data_length] = a # This works for data_length being even
# Do an array flipped convolution, which is a correlation.
c = signal.fftconvolve(b, a[::-1], mode='valid')
# Use numpy.correlate for comparison
d = numpy.correlate(a, a, mode='same')
# c will be exactly the same as d, except for the last sample (which
# completes the symmetry)
numpy.allclose(c[:-1], d) # Should be True
Now for a time comparison:
In [12]: timeit b[data_length/2:data_length/2+data_length] = a; c = signal.fftconvolve(b, a[::-1], mode='valid')
100 loops, best of 3: 4.67 ms per loop
In [13]: timeit d = numpy.correlate(a, a, mode='same')
10 loops, best of 3: 69.9 ms per loop
If you can cope with a circular correlation, you can remove the copy. The time difference will increase as data_length
increases.
I believe your code fails because OpenCV is expecting images as uint8 and not float32 format. You may find the cv2 python interface more intuitive to use (automatic conversion between ndarray and CV Image formats).
As for the speed of correlation, you can try using a fast fft implementation (FFTW has a python wrapper : pyfftw).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With