对于图像分割,我使用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))
这里的问题是imagep
和imageq
是彼此的移位版本。
其次,由于高斯的傅立叶也是高斯,我如何以直接的方式计算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进行了速度比较:
答案 0 :(得分:4)
高斯滤波器可以通过级联的盒子(平均)滤波器来近似,如Fast Almost-Gaussian Filtering的第II部分所述。此方法需要使用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,并且使用宽度为w1的第二滤波器执行(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
我没有真正处理图像的边缘,但可以通过修改上述功能来调整。这应该更快,特别是对于高斯模糊半径非常高的情况。