【问题标题】:Fast cross correlation method in PythonPython中的快速互相关方法
【发布时间】:2012-09-01 16:23:19
【问题描述】:

我最近一直在尝试寻找一种快速有效的方法来使用 Python 语言在两个数组之间执行互相关检查。经过一番阅读,我发现了这两个选项:

  1. NumPy.correlate() 方法,在处理大型数组时太慢了。
  2. cv.MatchTemplate() 方法,似乎要快得多。

出于显而易见的原因,我选择了第二个选项。我尝试执行以下代码:

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)

尽管这段代码假设非常简单,但它会引发下一个错误:

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

经过几个小时令人沮丧的尝试,我仍然卡住了!有人有什么建议吗?

顺便说一句,这是我的 Python 版本输出:

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.

谢谢大家!

【问题讨论】:

  • 这里有很多建议:stackoverflow.com/questions/6991471/…
  • 我已经阅读了这篇文章,谢谢。正如我所说,我不想使用 NumPy\SciPy 库,因为它们提供了相当慢的方法。
  • 虽然 numpy/scipy 并不总是使用最快的实现,但它们本身并不慢。例如,他们的 FFT 不如某些人快(这就是我写 FFTW wrappers 的原因)。关键是,不要指望使用 OpenCV 与使用带有 numpy/scipy 的“正确”算法相比会出现神奇的速度提升。 Numpy/scipy 非常普遍,这是一个很大的优势。

标签: python opencv numpy scipy correlation


【解决方案1】:

你不可能比使用基于 fft 的相关方法更快。

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

现在进行时间比较:

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

如果您可以处理循环相关,则可以删除副本。时差会随着data_length 的增加而增加。

【讨论】:

  • 嘿亨利,谢谢你的回答!我一定会尝试的。然而,我也想尝试 CV 库方法。知道错误的原因是什么吗?
  • 不知道 - 我没用过 OpenCV。
【解决方案2】:

我相信您的代码会失败,因为 OpenCV 期望图像为 uint8 而不是 float32 格式。 您可能会发现 cv2 python 界面使用起来更直观(ndarray 和 CV Image 格式之间的自动转换)。

至于关联的速度,你可以尝试使用快速的 fft 实现(FFTW 有一个 python 包装器:pyfftw)。

【讨论】:

  • 只是为了记录和自我宣传,对 FFTW 的现有包装不满意,我写了another set。它们旨在更加 Python 化,对 FFTW 知识的要求更低,并由一个非常全面的测试套件支持(并且正在积极维护和扩展,截至 2012 年 10 月 9 日)。
  • 谢谢!看起来确实很有希望。
猜你喜欢
  • 2010-09-17
  • 1970-01-01
  • 2013-11-26
  • 1970-01-01
  • 1970-01-01
  • 2018-05-17
  • 2014-04-19
  • 1970-01-01
  • 2020-11-28
相关资源
最近更新 更多