二维卷积定理的验证(上)
文章目录
0. 写在前面
在进行图像处理时,我们经常会用到卷积计算,但是当卷积核较大时,卷积计算将相当耗时。
事实上,可以通过卷积定理,来使用傅里叶变换手段实现卷积计算。也即是卷积定理。
即本文要探讨和验证的内容。
1. 二维卷积定理
卷积定理是傅里叶变换满足的一个重要性质。函数卷积的傅里叶变换是函数傅里叶变换的乘积。本文验证二维卷积定理,用于处理图像。
图像的二维卷积定理表达式如下
F
(
f
(
x
,
y
)
∗
g
(
x
,
y
)
)
=
F
(
f
(
x
,
y
)
)
⋅
F
(
g
(
x
,
y
)
)
F(f(x,y)*g(x,y)) = F(f(x,y))·F(g(x,y))
F(f(x,y)∗g(x,y))=F(f(x,y))⋅F(g(x,y))
其中,
F
F
F 表示傅里叶变换操作,
∗
*
∗ 表示卷积操作。
式(1)中的两侧结果皆为复数,不利于展现,因此将上述等式变换如下
f
(
x
,
y
)
∗
g
(
x
,
y
)
=
F
−
1
[
F
(
f
(
x
,
y
)
)
⋅
F
(
g
(
x
,
y
)
)
]
f(x,y)*g(x,y) = F^{-1}[F(f(x,y))·F(g(x,y))]
f(x,y)∗g(x,y)=F−1[F(f(x,y))⋅F(g(x,y))]
此时,等式左侧和右侧结果皆可以用图像来展现。
本文的目标是验证二维卷积定理,即验证等式(2)成立。
2. 名词说明
2.1 卷积
根据 padding 的类型,可以将卷积分为
-
‘full‘。滑动步长为 1,图片尺寸大小为 w × h w\times h w×h ,卷积核尺寸大小为 m × n m\times n m×n,卷积后图像大小为 ( w + m − 1 ) × ( h + n − 1 ) (w+m-1)\times (h+n-1) (w+m−1)×(h+n−1) 。
-
’same’。滑动步长为 1,图片尺寸大小为 w × h w\times h w×h,卷积核尺寸大小为 m × n m\times n m×n,卷积后图像大小为 w × h w\times h w×h 。
-
‘valid’。滑动步长为 s s s,图片尺寸大小为 w × h w\times h w×h,卷积核尺寸大小为 m × n m\times n m×n,卷积后图像大小为 ( w − m s + 1 ) × ( h − n s + 1 ) (\frac{w-m}{s}+1)\times (\frac{h-n}{s}+1) (sw−m+1)×(sh−n+1) 。
卷积的具体实现步骤为:
- 对图片进行 padding 操作。通常是根据选择的卷积类型进行补零操作,即在第一行之前和最后一行之后、第一列之前和最后一列之后进行补零,以满足卷积的尺寸要求。
- 将卷积核绕其中心旋转180度。
- 在图像上滑动旋转后的卷积核,卷积核与图像进行逐项乘积求和,最终得到全图的卷积结果。
2.2 傅里叶变换与反变换
需要注意的是,因为图像的大小为 w × h w\times h w×h ,而卷积核的大小为 m × n m\times n m×n。 因此在进行傅里叶变换操作时,需要将两者大小统一,且跟前述卷积结果的图片尺寸大小相统一时,最终结果才有可能是相等的。
举例说明:
如果图片大小为 w × h w\times h w×h , 卷积核大小为 m × n m\times n m×n。
对于等式左侧,进行卷积时,采用 “full” 方式,则卷积后 f ( x , y ) ∗ g ( x , y ) f(x,y)*g(x,y) f(x,y)∗g(x,y) 的结果尺寸大小即为 ( w + m − 1 ) × ( h + n − 1 ) (w+m-1)\times (h+n-1) (w+m−1)×(h+n−1);因此,对于等式右侧,在进行傅里叶变换前,就需要对图像和卷积核进行补零填充操作,以使得其最终结果尺寸也为 ( w + m − 1 ) × ( h + n − 1 ) (w+m-1)\times (h+n-1) (w+m−1)×(h+n−1)。
3. 验证实现
3.1 使用 ”full“ 卷积
代码如下
import numpy as np
from scipy import signal
# 原始图像 f(x)
gray = np.uint16(np.random.randint(100, size=(7,7)))
# 卷积核 g(x)
kenel = np.ones((3,3))/9
# ----- Conv = f(x)*g(x) ----- #
# f(x)*g(x)
Conv = signal.convolve2d(gray, kenel, mode='full') # 使用full卷积类型,得到(M+N-1)X(M+N-1)大小
#--------- ifft{ F(f(x))·F(g(x)) } ---------#
# 傅里叶变换前进行 padding 填充,图像和卷积核都补零到 (M+N-1)x(M+N-1)大小。
img_pad = np.pad(gray, ((1, 1),(1, 1)), 'constant')
kenel_pad = np.pad(kenel, ((3, 3),(3, 3)), 'constant')
# F(f(x))
img_fft = np.fft.fftshift(np.fft.fft2(img_pad))
# F(g(x))
kenel_fft = np.fft.fftshift(np.fft.fft2(kenel_pad))
# ifft( F(f(x))·F(g(x)) )
FFT = np.fft.ifftshift(np.fft.ifft2(np.fft.fftshift(img_fft*kenel_fft)))
#--------- 打印结果 ---------#
print(" f(x) ↓")
print(gray)
print(" g(x) ↓")
print(kenel)
print("\n\n f(x)*g(x) ↓")
print(np.uint8(Conv))
print("\n ifft[F·G] ↓")
print(np.uint8(np.abs(FFT)))
结果如下
从(c)和(d)的数值结果可以看出,两者结果完全一致,也即 f ( x ) ∗ g ( x ) = i f f t ( F ⋅ G ) f(x)*g(x)=ifft(F·G) f(x)∗g(x)=ifft(F⋅G) 。二维卷积定理成立。
3.2 使用“same”卷积
代码如下
import numpy as np
from scipy import signal
# 原始图像 f(x)
gray = np.uint16(np.random.randint(100, size=(7,7)))
# 卷积核 g(x)
kenel = np.ones((3,3))/9
# ----- Conv = f(x)*g(x) ----- #
# f(x)*g(x)
Conv = signal.convolve2d(gray, kenel, mode='same') # 使用full卷积类型,得到(M+N-1)X(M+N-1)大小
#--------- ifft{ F(f(x))·F(g(x)) } ---------#
# 傅里叶变换前进行 padding 填充,图像和卷积核都补零到 (M+N-1)x(M+N-1)大小。
img_pad = np.pad(gray, ((0, 0),(0, 0)), 'constant')
kenel_pad = np.pad(kenel, ((2, 2),(2, 2)), 'constant')
# F(f(x))
img_fft = np.fft.fftshift(np.fft.fft2(img_pad))
# F(g(x))
kenel_fft = np.fft.fftshift(np.fft.fft2(kenel_pad))
# ifft( F(f(x))·F(g(x)) )
FFT = np.fft.ifftshift(np.fft.ifft2(np.fft.fftshift(img_fft*kenel_fft)))
#--------- 打印结果 ---------#
print(" f(x) ↓")
print(gray)
print(" g(x) ↓")
print(kenel)
print("\n\n f(x)*g(x) ↓")
print(np.uint8(Conv))
print("\n ifft[F·G] ↓")
print(np.uint8(np.abs(FFT)))
结果如下
根据(c)和(d)的数值结果,在橘色方框内两者保持完全一致,而框外由于受到傅里叶变换时补零的影响,所以数值会出现不同的情况。
4. 结论
从上述实验中,可以看出:
- padding 使用 “full” 方式时,等式左右两侧矩阵数值完全一致。但该种方式缺点是卷积图像结果矩阵尺寸发生改变。
- padding 使用 “same” 方式时,等式左右两侧矩阵在一定范围内完全一致。但该种方式缺点是卷积图像结果中有部分不与傅里叶方式计算下等价。
但我们可以得到一个结论是,padding 的方式影响着最终结果。
于是就发现了一个新的问题:即是否存在着某种边界处理方式,使得卷积图像结果矩阵尺寸没有变化,且所有值都可以与傅里叶方式计算下等价。
事实上,是存在的,因为 cv2.filter2D()
便是解决这一问题进而实现的。
至于,如何设置 padding 方式来解决这一问题,也即是下一篇博文的内容二维卷积定理的验证(下,cv2.filter2D())。