@koshian2さんの記事でFFTした画像にガウスフィルタを畳み込みしたコードが示されていた。
このコードを拝借して周波数領域でjinc関数を畳み込んだ結果がどうなるかを示してみたい。
コードの変更
従来のガウシアンカーネルの代わりにjincカーネル、sincカーネルを定義し代わりに使用する。
# 画像処理のガウシアンぼかしのカーネル
gaussian_kernel = torch.FloatTensor([[1, 2, 1], [2, 4, 2], [1, 2, 1]]) / 16.0
# jinc,sinc関数のカーネル
import numpy as np
from scipy.special import jv, sinc
x = np.linspace(-32, 32, 65)
y = np.linspace(-32, 32, 65)
X, Y = np.meshgrid(x, y)
jinc_kernel = jv(1, 2*np.sqrt(X**2+Y**2))/(np.sqrt(X**2+Y**2))
jinc_kernel[32,32] = 1.0
jinc_kernel = torch.FloatTensor(jinc_kernel)
sinc_kernel = torch.FloatTensor(sinc(0.7*X)*sinc(0.7*Y))
また、周波数空間で最大強度が中央にくるようにFFT=>シフト=>畳み込み=>シフト=>IFFTとなるように追加でシフトを行っておく。
fft = torch.fft.rfftn(orig, dim=(-2, -1), norm="ortho") # (1, 3, 512, 257): 複素数
fft = torch.fft.fftshift(fft)
blur_real = F.conv2d(fft.real, conv_kernel, padding='same')
blur_imag = F.conv2d(fft.imag, conv_kernel, padding='same')
fft = torch.fft.ifftshift(fft)
blur_real = torch.fft.ifftshift(blur_real)
blur_imag = torch.fft.ifftshift(blur_imag)
結果
まとめ
結果は画像にマスクを掛けたようになった。jinc関数は円形、sinc関数は正方形のマスクを掛けた結果に見える。これはsinc関数のFFTがrect関数(矩形関数)であり、周波数領域の畳み込みは実空間でのrect関数の積(画像のマスク)に等しいからである。また、実空間でこれらのフィルタを畳み込むと、周波数空間ではローパスフィルタを掛ける事になる。
最近jinc関数を知ったのだが、これがsinc関数と比べどう違うかを確認できた。