gpt4 book ai didi

python - 使用 FFT 的高斯图像滤波

转载 作者:太空宇宙 更新时间:2023-11-03 14:55:58 27 4
gpt4 key购买 nike

对于图像分割,我使用 OpenCV 的 GaussianBlur 差分高斯特征(范围从 0.8 到 8.43,指数步长为 1.4)。我的图像大小为 4096 x 2160,所以这需要相当长的时间(在一个核心上 8 秒,这在处理视频时相当长)。

你能给我一些关于如何加快速度的建议吗?目前我正在尝试在 FFT 中实现高斯滤波。到目前为止,我有以下代码:

ftimage = np.fft.fft2(image)
ftimage = np.fft.fftshift(ftimage)
kernel = cv2.getGaussianKernel(11, 3)
kernel = kernel * kernel.T
ftkernel = np.fft.fftshift(np.fft.fft2(kernel, (h, w)))
ftimagep = ftimage * gmask
imagep = np.fft.ifft2(ftimagep)
imageq = cv2.GaussianBlur(image, (11,11), 3))

这里的问题是 imagepimageq 是彼此的移位版本。其次,由于高斯函数的傅里叶函数也是高斯函数,我该如何直接计算 ftkernel


下面的答案:我已经实现了近似过滤:

 def approx_g(image, sigma_g, n=5):
w = np.sqrt(12*sigma_g**2/n + 1)
wu = np.ceil(w) if np.ceil(w) % 2 == 1 else np.ceil(w)+1
wl = np.floor(w) if np.floor(w) % 2 == 1 else np.floor(w)-1
if w == w//1:
wl -= 2
wu += 2
m = round((12*sigma_g**2 - n*wl**2 - 4*n*wl - 3*n) / (-4*wl - 4))
wl = int(wl)
wu = int(wu)
for num in range(0,int(m)):
image = cv2.blur(image, (wl, wl))
for num in range(0,int(n-m)):
image = cv2.blur(image, (wu, wu))
return image

对于 n=4,L2 像素差异看起来相当不错:

我还对不同的 sigma 进行了速度比较:

最佳答案

高斯滤波器可以通过级联的框(平均)滤波器来近似,如 Fast Almost-Gaussian Filtering 的第二部分所述。 .此方法需要使用 Integral Image ,并允许更快地应用(接近)高斯滤波,特别是对于高模糊情况。

下面的代码演示了如何使用上面链接的论文中的步骤来做到这一点。

让过滤器半径为问题中的 8.43。

sigma_g = 8.43

盒式过滤器的连续应用次数决定了近似程度。对于这个例子,我将它设置为 5:

n = 5

首先,使用等式 3 找到盒式过滤器的理想宽度:

w = np.sqrt(12*sigma_g**2/n + 1)

如论文中所述,使用两个不同大小的盒式过滤器效果更好。为了对称,滤波器的长度必须为奇数,长度相差 2。下面的代码采用 w 并找到最接近的奇数整数。 (它可能会写得更好):

wu = np.ceil(w) if np.ceil(w) % 2 == 1 else np.ceil(w)+1
wl = np.floor(w) if np.floor(w) % 2 == 1 else np.floor(w)-1
if w == w//1:
wl -= 2
wu += 2

如果需要 n 个连续的应用程序,则使用宽度为 wu 的第一个过滤器执行 m,并使用宽度为 wl 的第二个过滤器执行 (n-m)。公式 5 显示了如何计算 m:

m = round((12*sigma_g**2 - n*wl**2 - 4*n*wl - 3*n) / (-4*wl - 4))

接下来,计算水平和垂直积分图像的函数:

def integral_image_1d_hor(image):
''' Calculated the 1d horizontal integral
image of an image.'''
n1, n2 = np.shape(image)
int_im = np.zeros((n1, n2))
for row in range(0,n1):
int_im[row,0] = image[row,0]

for row in range(0,n1):
for col in range(1,n2):
int_im[row,col] = image[row,col] + int_im[row,col-1]

return int_im


def integral_image_1d_ver(image):
''' Calculated the 1d vertical integral
image of an image.'''
n1, n2 = np.shape(image)
int_im = np.zeros((n1, n2))
for col in range(0,n2):
int_im[0,col] = image[0,col]

for col in range(0,n2):
for row in range(1,n1):
int_im[row,col] = image[row,col] + int_im[row-1,col]

return int_im

要使用积分图像进行过滤,我有这些函数:

def box_1d_filter_hor(int_im_1d, width):
w = int((width-1)/2)
fil_im = np.zeros(np.shape(int_im_1d))
pad = w
int_im_1d = np.pad(int_im_1d, pad, 'constant')
n1 = np.shape(int_im_1d)[0]
n2 = np.shape(int_im_1d)[1]
for row in range(pad, n1-pad):
for col in range(pad, n2-pad):
fil_im[row-pad,col-pad] = (int_im_1d[row,col+w]
- int_im_1d[row,col-w-1])/width
return fil_im


def box_1d_filter_ver(int_im_1d, width):
w = int((width-1)/2)
fil_im = np.zeros(np.shape(int_im_1d))
pad = w
int_im_1d = np.pad(int_im_1d, pad, 'constant')
n1 = np.shape(int_im_1d)[0]
n2 = np.shape(int_im_1d)[1]
for col in range(pad, n2-pad):
for row in range(pad, n1-pad):
fil_im[row-pad,col-pad] = (int_im_1d[row+w,col]
- int_im_1d[row-w-1,col])/width
return fil_im

然后我又定义了两个函数,用于在水平和垂直方向上处理图像:

def process_hor(image, w):
int_im = integral_image_1d_hor(image)
fil_im = box_1d_filter_hor(int_im, w)
return fil_im

def process_ver(image, w):
int_im = integral_image_1d_ver(image)
fil_im2 = box_1d_filter_ver(int_im, w)
return fil_im2

最后,使用所有这些先前的函数,使用以下函数来近似高斯滤波:

def approximate_gaussian(image, wl, wu, m, n):
for num in range(0,int(m)):
image = process_hor(image, wl)
image = process_ver(image, wl)
for num in range(0,int(n-m)):
image = process_hor(image, wu)
image = process_ver(image, wu)
return image

我并没有真正处理图像的边缘,但是可以通过修改上面的函数来调整。这应该更快,特别是对于高斯模糊半径非常高的情况。

关于python - 使用 FFT 的高斯图像滤波,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42560434/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com