python - 需要 scipy signal.fftconvolve 的 Tensorflow/Keras 等效项

标签 python numpy tensorflow scipy keras

我想在Tensorflow/Keras中使用scipy.signal.fftconvolve,有什么办法可以做到吗?

现在我正在使用以下代码:

window = np.tile(window, (1, 1, 1, 3))
tf.nn.conv2d(img1, window, strides=[1,1,1,1], padding='VALID')

这些行是否相当于:

signal.fftconvolve(img1, window, mode='valid')

最佳答案

实现

FFT 卷积可以在 tensorflow 中相对容易地实现。以下内容非常严格地遵循scipy.signal.fftconvolve

import tensorflow as tf

def _centered(arr, newshape):
    # Return the center newshape portion of the array.
    currshape = tf.shape(arr)[-2:]
    startind = (currshape - newshape) // 2
    endind = startind + newshape
    return arr[..., startind[0]:endind[0], startind[1]:endind[1]]

def fftconv(in1, in2, mode="full"):
    # Reorder channels to come second (needed for fft)
    in1 = tf.transpose(in1, perm=[0, 3, 1, 2])
    in2 = tf.transpose(in2, perm=[0, 3, 1, 2])

    # Extract shapes
    s1 = tf.convert_to_tensor(tf.shape(in1)[-2:])
    s2 = tf.convert_to_tensor(tf.shape(in2)[-2:])
    shape = s1 + s2 - 1

    # Compute convolution in fourier space
    sp1 = tf.spectral.rfft2d(in1, shape)
    sp2 = tf.spectral.rfft2d(in2, shape)
    ret = tf.spectral.irfft2d(sp1 * sp2, shape)

    # Crop according to mode
    if mode == "full":
        cropped = ret
    elif mode == "same":
        cropped = _centered(ret, s1)
    elif mode == "valid":
        cropped = _centered(ret, s1 - s2 + 1)
    else:
        raise ValueError("Acceptable mode flags are 'valid',"
                         " 'same', or 'full'.")

    # Reorder channels to last
    result = tf.transpose(cropped, perm=[0, 2, 3, 1])
    return result

示例

将宽度为 20 像素的高斯平滑应用于标准“面部”图像的简单示例如下:

if __name__ == '__main__':
    from scipy import misc
    import matplotlib.pyplot as plt
    from tensorflow.python.ops import array_ops, math_ops
    session = tf.InteractiveSession()

    # Create gaussian
    std = 20
    grid_x, grid_y = array_ops.meshgrid(math_ops.range(3 * std),
                                        math_ops.range(3 * std))
    grid_x = tf.cast(grid_x[None, ..., None], 'float32')
    grid_y = tf.cast(grid_y[None, ..., None], 'float32')

    gaussian = tf.exp(-((grid_x - 1.5 * std) ** 2 + (grid_y - 1.5 * std) ** 2) / std ** 2)
    gaussian = gaussian / tf.reduce_sum(gaussian)

    face = misc.face(gray=False)[None, ...].astype('float32')

    # Apply convolution
    result = fftconv(face, gaussian, 'same')
    result_r = session.run(result)

    # Show results
    plt.figure('face')
    plt.imshow(face[0, ...] / 256.0)

    plt.figure('convolved')
    plt.imshow(result_r[0, ...] / 256.0)

enter image description here enter image description here

关于python - 需要 scipy signal.fftconvolve 的 Tensorflow/Keras 等效项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47272699/

相关文章:

python - 等待用户操作继续执行代码

python - Python 中的线程/队列

python - tensorflow 中图像的有效加权和

python - 如何在 keras fit_generator() 中定义 max_queue_size、workers 和 use_multiprocessing?

python ,子进程: reading output from subprocess

python - 在多索引 pandas DataFrame 上选择一列

python - 正确使用 fftw fft

python - 优化测试多个 NumPy 数组中的所有行组合

python - Python 中存储在数组中的矩阵相乘

python - 使用 dropout 和 CudnnLSTM 进行训练和验证