Справочная информация и тестирование
Я пишу двумерные свертки с нуля, и мне трудно реализовать их с помощью преобразований Фурье. Я реализовал функцию, чтобы помочь мне проверить мои свертки.
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
методы)? Либо с помощью заполнения, либо каким-либо другим методом БПФ?
Я бы не стал масштабировать свое изображение; я думаю, что если я смогу сделать это без масштабирования выше, мне не придется делать это здесь.
Любая помощь будет принята с благодарностью. Спасибо!