【问题标题】:Speeding up Fourier-related transform computations in python (OpenCV)在 python (OpenCV) 中加速傅里叶相关的变换计算
【发布时间】:2014-02-28 11:20:37
【问题描述】:

我有一个图像,我需要计算一个与傅立叶相关的变换,称为短时傅立叶变换(额外的数学信息检查:http://en.wikipedia.org/wiki/Short-time_Fourier_transform)。

为了做到这一点,我需要:

(1)在图像的起始像素处放置一个窗口(x,y)=(M/2,M/2)

(2) 使用此窗口截断图像

(3)计算截断图像的FFT,保存结果。

(4) 向右递增滑动窗口

(5) 转到第3步,直到窗口到达图像的末尾

但是我需要实时执行上述计算... 但是速度比较慢!!!

有没有办法加快上述过程??

我还包括我的代码:

        height, width = final_frame.shape
        M=2
        for j in range(M/2, height-M/2):
            for i in range(M/2, width-M/2):
                face_win=final_frame[j-M/2:j+M/2, i-M/2:i+M/2]

                #these steps are perfomed in order to speed up the FFT calculation process
                height_win, width_win = face_win.shape
                fftheight=cv2.getOptimalDFTSize(height_win)
                fftwidth=cv2.getOptimalDFTSize(width_win)
                right = fftwidth - width_win
                bottom = fftheight - height_win
                bordertype = cv2.BORDER_CONSTANT 
                nimg = cv2.copyMakeBorder(face_win,0,bottom,0,right,bordertype, value = 0)

                dft = cv2.dft(np.float32(face_win),flags = cv2.DFT_COMPLEX_OUTPUT)
                dft_shift = np.fft.fftshift(dft)
                magnitude_spectrum = 20*np.log(cv2.magnitude(dft_shift[:,:,0],dft_shift[:,:,1]))

【问题讨论】:

  • 我还没有答案,但我想自己分析一下,看看哪里可以改进并练习 numpy。但是,我在magnitude_spectrum = ... 行上得到RuntimeWarning: divide by zero encountered in log。这段代码可以吗,或者您可以在 imgur 上发布指向有效测试图像的链接吗?
  • 我也很确定是什么杀死了你正在复制cv2.copyMakeBorder(...)中的数据。这是您复制数据的唯一地方,而且确实会复制大量数据。我会看看我是否能想出一个更有效的解决方案。
  • 除非有人确切知道该做什么,否则这似乎需要一些讨论。你能加入this chat吗?
  • 希望回答对您有所帮助。我还建议您在DSP Exchange 上发帖并指出这个问题以了解是否有人有更好的想法。他们可能对数学方法有更深入的了解,甚至可能为您优化代码。

标签: python opencv python-2.7 image-processing fft


【解决方案1】:

当然,您的大部分时间将花在 FFT 和其他转换代码上,但我尝试了其他部分的简单优化。

变化

  • 每个循环的帧大小计算都是相同的,因此将它们移出(~nil 改进)
  • 从 uint8 到 float32 的类型强制可以在整个图像上执行一次,而不是转换每一帧。 (小但可衡量的改进)
  • 如果窗口大小已经与最佳大小相同(如果您将 M 保持为 2 的幂,我想它总是如此),那么不要进行有边框的复制。只需按原样使用face_win 视图。 (小但可衡量的改进)

总改进 26 秒 --> 22 秒。不多,但确实有。

独立代码(只需添加1024x768.jpg

import time
import cv2
import numpy as np

# image loading for anybody else who wants to use this
final_frame = cv2.imread('1024x768.jpg')
final_frame = cv2.cvtColor(final_frame, cv2.COLOR_BGR2GRAY)
final_frame_f32 = final_frame.astype(np.float32)  # moved out of the loop

# base data
M = 4
height, width = final_frame.shape

# various calculations moved out of the loop
m_half = M//2
height_win, width_win = [2 * m_half] * 2  # can you even use odd values for M?
fftheight = cv2.getOptimalDFTSize(height_win)
fftwidth = cv2.getOptimalDFTSize(width_win)
bordertype = cv2.BORDER_CONSTANT
right = fftwidth - width_win
bottom = fftheight - height_win

start = time.time()
for j in range(m_half, height-m_half):
    for i in range(m_half, width-m_half):
        face_win = final_frame_f32[j-m_half:j+m_half, i-m_half:i+m_half]
        # only copy for border if necessary
        if (fftheight, fftwidth) == (height_win, width_win):
            nimg = face_win
        else:
            nimg = cv2.copyMakeBorder(face_win, 0, bottom, 0, right, bordertype, value=0)
        dft = cv2.dft(nimg, flags=cv2.DFT_COMPLEX_OUTPUT)
        dft_shift = np.fft.fftshift(dft)
        magnitude_spectrum = 20 * np.log(cv2.magnitude(dft_shift[:, :, 0], dft_shift[:, :, 1]))
elapsed = time.time() - start

print elapsed

错误

  • 我在上面的代码中修复了这些问题,但我没有编辑您的原件,因为您可能希望它是这样的
  • 您计算 nimg,然后在 dft 中使用原始 face_win
  • 明确地说,我将M/2 等更改为M//2

【讨论】:

    猜你喜欢
    • 2010-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-29
    • 2017-08-26
    • 1970-01-01
    • 2011-07-12
    • 2014-11-02
    相关资源
    最近更新 更多