使用python实现一个快速高斯模糊算法

在gimp的retinex里面使用了一个快速计算的高斯模糊,论文应该是Recursive Implementation of the gaussian filter,是使用一些多项式计算来近似计算高斯分布,这样能够大大减少计算。

将retinex源码给抽离出来,并使用python进行实现,代码如下:


import math
import numpy as np
import cv2


class Coefs:
    def __init__(self):
        self.b0 = 0
        self.b1 = 0
        self.b2 = 0
        self.b3 = 0
        self.b = 0
        self.sigma = 0
        self.n = 0


def compute_coefs3(c, sigma):
    if sigma >= 2.5:
        q = 0.98711*sigma-0.9633
    elif sigma >= 0.5:
        q = 3.97156-4.14554*math.sqrt(1-0.26891*sigma)
    else:
        q = 0.1147705018520355224609375
    q2 = q*q
    q3 = q2*q
    c.b0 = 1.57825+2.44413*q+1.4281*q2+0.422205*q3
    c.b1 = 2.44413*q+2.85619*q2+1.26661*q3
    c.b2 = -(1.4281*q2+1.26661*q3)
    c.b3 = 0.422205*q3
    c.b = 1-((c.b1+c.b2+c.b3)/c.b0)
    c.sigma = sigma
    c.n = 3


def gausssmooth(input, size, rowstride, c):
    w1 = np.zeros((size+3))
    w2 = np.zeros((size+3))
    output = np.zeros_like(input)

    '''forward pass'''
    size = size - 1
    w1[0] = input[0]
    w1[1] = input[0]
    w1[2] = input[0]
    for i in range(3, size+4):
        w1[i] = input[(i - 3)*rowstride] * c.b + (c.b1*w1[i-1]+c.b2*w1[i-2]+c.b3*w1[i-3])/c.b0
    '''backward pass'''
    w2[size + 1] = w1[size + 3]
    w2[size + 2] = w1[size + 3]
    w2[size + 3] = w1[size + 3]
    for i in range(size, -1, -1):
        w2[i] = w1[i+3] * c.b + (c.b1*w2[i+1]+c.b2*w2[i+2]+c.b3*w2[i+3])/c.b0
        output[i*rowstride] = w2[i]
    return np.clip(output, 0, 255)


def gausss_blur(img):
    out_img = np.zeros_like(img)
    h, w, c = img.shape
    coefs = Coefs()
    compute_coefs3(coefs, 3)#使用sigma=3的高斯核
    for channel in range(c):
        gray = img[:, :, channel]+1#0-255 => 1-256
        # 横向滤波
        for row in range(h):
             pixels = gray[row, :]
             out_img[row, :, channel] = gausssmooth(pixels, w, 1, coefs)
        # 纵向滤波
        for col in range(w):
            pixels = out_img[:, col, channel]
            out_img[:, col, channel] = gausssmooth(pixels, h, 1, coefs)
    return out_img


if __name__ == '__main__':
    img = cv2.imread('tmp/50.jpg')
    blur_img = gausss_blur(img.astype(np.float32))
    blur_opencv_img = cv2.GaussianBlur(img, (0, 0), 3)
    cv2.imwrite('tmp/blur_img.jpg', blur_img)
    cv2.imwrite('tmp/blur_opencv_img.jpg', blur_opencv_img)

效果如下:

基本上和opencv的结果一致,也可以自定义sigma

参考:https://www.cnblogs.com/luo-peng/p/5223910.html

猜你喜欢

转载自blog.csdn.net/zhou_438/article/details/131330311