Проблема с четными изображениями: 2D Convolution with FFT - PullRequest
0 голосов
/ 02 апреля 2020

Справочная информация и тестирование

Я пишу двумерные свертки с нуля, и мне трудно реализовать их с помощью преобразований Фурье. Я реализовал функцию, чтобы помочь мне проверить мои свертки.

import numpy as np

def zero_pad(image, pad_height, pad_width):
    """ Zero-pad an image.

    Ex: a 1x1 image [[1]] with pad_height = 1, pad_width = 2 becomes:

        [[0, 0, 0, 0, 0],
         [0, 0, 1, 0, 0],
         [0, 0, 0, 0, 0]]         of shape (3, 5)

    Args:
        image: numpy array of shape (H, W).
        pad_width: width of the zero padding
        pad_height: height of the zero padding

    Returns:
        out: numpy array of shape (H+2*pad_height, W+2*pad_width).
    """
    H, W = image.shape
    out = np.zeros((H + 2 * pad_height, W + 2 * pad_width))
    out[pad_height:pad_height + H, pad_width:pad_width + W] = image
    return out


def conv(image, kernel):
    """Uses element-wise multiplication to efficiently compute weighted 
    sum of neighborhood at each pixel.

    Args:
        image: numpy array of shape (Hi, Wi).
        kernel: numpy array of shape (Hk, Wk).

    Returns:
        out: numpy array of shape (Hi, Wi).
    """
    Hi, Wi = image.shape
    Hk, Wk = kernel.shape
    out = np.zeros((Hi, Wi))

    #Creating new padded image and flipping kernel
    pad_img = zero_pad(image, (Hk - 1) // 2, (Wk - 1) // 2)
    flip_k = np.flip(kernel)

    #Multiplying matricies
    for i in range(Hi):
        for j in range(Wi):
            window = pad_img[i: i + Hk, j: j + Wk]
            out[i, j] = np.sum(window * flip_k)

    return out

Ввод изображения и ядра в conv приводит к очень близким результатам к scipy.signal.fftconvolve (с индексом 1: n - 1 в каждом направлении), что является целью.

Я тестирую эти функции с изображением формы (300, 332) и (3, 3) ядра: массив ([[1,0, -1], [2,0, -2] ], [1,0, -1]]).

Это изображение Я тестирую и результаты Я получаю через вышеуказанные функции.

Моя реализация

def fft_conv(image, kernel):
    """Uses FFT algorithm to find convolutions.

    Args:
        image: numpy array of shape (Hi, Wi).
        kernel: numpy array of shape (Hk, Wk).

    Returns:
        out: numpy array of shape (Hi, Wi).
    """
    img_t = np.fft.fft2(image)
    ker_t = np.fft.fft2(kernel)
    return np.real(np.fft.ifft2(img_t * ker_t)) #Where the problem lies

Моя проблема

Оказывается, мне нужно иметь одинаковые размеры, чтобы умножить img_t и ker_t. Я попытался zero_pad настроить свое ядро, чтобы оно подходило (300, 332), но моя функция может заполнять только нечетные размеры: (301, 333). Я тоже пробовал np.pad, но безуспешно. У кого-нибудь есть какие-либо решения для получения результатов, аналогичных приведенным выше функциям (мои домашние или scipy.signal.fftconvolve методы)? Либо с помощью заполнения, либо каким-либо другим методом БПФ?

Я бы не стал масштабировать свое изображение; я думаю, что если я смогу сделать это без масштабирования выше, мне не придется делать это здесь.

Любая помощь будет принята с благодарностью. Спасибо!

...