【问题标题】:Box blur is not any faster than Gaussian blur?盒子模糊不比高斯模糊快吗?
【发布时间】:2020-12-04 10:18:16
【问题描述】:

我已经编写了一些代码来使用内核卷积将过滤器应用于图像。目前,400x400 图像需要相当长的时间,大约需要 30 秒。我知道框模糊比高斯模糊要快得多。但是,当我将内核更改为框模糊时,它似乎需要与高斯模糊一样多的时间。有什么想法吗?

import cv2
import numpy as np

img = cv2.imread('test.jpg')
img2 = cv2.imread('test.jpg')

height, width, channels = img.shape

GB3 = np.array([[1,2,1], [2,4,2], [1,2,1]])
GB5 = np.array([[1,4,6,4,1], [4,16,24,16,4], [6,24,36,24,6], [4,16,24,16,4], [1,4,6,4,1]])
BB = np.array([[1,1,1], [1,1,1], [1,1,1]])

kernel = BB

#initialise
kernel_sum = 1

filtered_sum_r = 0 
filtered_sum_g = 0 
filtered_sum_b = 0 


for i in range(kernel.shape[0]):
    for j in range(kernel.shape[1]):
        p = kernel[i][j]
        kernel_sum += p 

for x in range(1,width-1):
    for y in range(1,height-1):
        for i in range(kernel.shape[0]):
            for j in range(kernel.shape[1]):
                filtered_sum_b += img[y-1+j,x-1+i,0]*kernel[i][j]
                filtered_sum_g += img[y-1+j,x-1+i,1]*kernel[i][j]
                filtered_sum_r += img[y-1+j,x-1+i,2]*kernel[i][j]
        
        new_pixel_r = filtered_sum_r/kernel_sum
        new_pixel_g = filtered_sum_g/kernel_sum
        new_pixel_b = filtered_sum_b/kernel_sum

        if new_pixel_r>255:
            new_pixel_r = 255
        elif new_pixel_r<0: 
            new_pixel_r = 0

        if new_pixel_g>255:
            new_pixel_g = 255
        elif new_pixel_g<0: 
            new_pixel_g = 0

        if new_pixel_b>255:
            new_pixel_b = 255
        elif new_pixel_b<0: 
            new_pixel_b = 0

        img2[y,x,0] = new_pixel_b
        img2[y,x,1] = new_pixel_g
        img2[y,x,2] = new_pixel_r

        filtered_sum_r = 0 
        filtered_sum_g = 0 
        filtered_sum_b = 0 
        #print(kernel_sum)

scale = 2
img_big = cv2.resize(img, (0,0), fx=scale, fy=scale) 
img2_big = cv2.resize(img2, (0,0), fx=scale, fy=scale) 


cv2.imshow('original', img_big)
cv2.imshow('processed', img2_big)

cv2.waitKey(0)
cv2.destroyAllWindows()

【问题讨论】:

  • 如果盒子过滤器具有相同的大小和相同的操作数,它与卷积一样快。盒式过滤器的一个优点是,您可以使用积分图像来预先计算大量信息,因此可以非常有效地计算更大尺寸的盒式过滤器,并且几乎与过滤器大小无关。另外我建议你使用opencv函数而不是自己实现filter,因为opencv有很多优化,比如SSE指令,积分图像等等。

标签: python opencv blur gaussianblur


【解决方案1】:
  • 您正在使用 python 循环。这总是比优化的二进制代码慢几个数量级。尽可能使用库函数,即 numpy 和 OpenCV。或将您的关键代码编写为可编译的 Cython。
  • 您的代码访问模式不是最理想的。您应该沿着内部循环中的行移动(对于 y:对于 x:),因为这就是图像的存储方式。这里的原因是您的 CPU 缓存的使用方式。在row-major storage 中,高速缓存行包含一行中的多个像素。如果您沿着列运行,则在需要另一个缓存行之前,您只使用该缓存行一次。
  • 您的代码没有使用两种类型的过滤器都是“separable”的属性
  • 卷积可以表示为频域中的元素乘法(DFT、乘法、逆 DFT),这是执行卷积的常用方法。

使用 OpenCV 的 filter2D 函数进行卷积。

至于框模糊与高斯,唯一的区别是“有趣”的权重与无权重(都相等)。这相当于更多的乘法,或者不是。优化代码后,其执行时间主要取决于将数据从 RAM 传输到 CPU 所需的时间。这适用于优化代码,而不是纯 python 循环。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-11
    • 2018-05-01
    • 1970-01-01
    • 2015-11-05
    • 2016-09-26
    • 1970-01-01
    • 2015-01-18
    相关资源
    最近更新 更多