高斯模糊与图像处理(Gaussian Blur)

这篇具有很好参考价值的文章主要介绍了高斯模糊与图像处理(Gaussian Blur)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

高斯模糊在图像处理中的用途及其广泛,除了常规的模糊效果外,还可用于图像金字塔分解、反走样、高低频分解、噪声压制、发光效果等等等等。正因为高斯模糊太基础,应用太广泛,所以需要尽可能深入认识这个能力,避免在实际应用中无意采坑。

一维高斯核函数

公式

G ( x ) = 1 2 π σ e − ( x − μ ) 2 2 σ 2 G(x) = \frac{1}{\sqrt{2\pi}\sigma}e^{-\frac{(x-\mu)^2}{2\sigma^2}} G(x)=2π σ1e2σ2(xμ)2

其中 μ \mu μ是对称轴,图像处理中通常不会考虑 μ ≠ 0 \mu \neq0 μ=0的情况,所以该参数可以忽略(本文自此向下均忽略 μ \mu μ)。

σ \sigma σ决定函数的高矮胖瘦, σ \sigma σ越小越高瘦,越大越矮胖。如果用于模糊的话,高瘦意味着中心像素对于计算结果的贡献大,而远处的像素贡献相对较小,也就是说模糊结果更多受中心像素支配,因此模糊程度就低;反之矮胖意味着模糊程度高。所以其他条件不变的情况下,增大 σ \sigma σ会加强模糊,反之会减弱模糊。

e指数前的系数保证了核函数在 ( − ∞ , + ∞ ) (-\infty, +\infty) (,+)的积分为1,不过在图像处理中,我们显然不可能用无穷大的半径,所以会对高斯核的系数做归一化,那么e指数前的系数在归一化中就被约去了,所以干脆就不用计算。

曲线形态

下图是一维高斯核函数的曲线形态。

注意下图仍然计算了e指数前的系数,并验证了核函数的积分,表明无论 σ \sigma σ怎么变化,其积分总是为1。

高斯模糊与图像处理(Gaussian Blur),数字图像处理,公式推导,图像处理,人工智能

# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt


def gaussian_1d(x, sigma):
    coef = 1. / (np.sqrt(2 * np.pi) * sigma)
    return coef * np.exp(-x * x / (2 * sigma * sigma))


def plot_gaussian_1d():
    dx = 0.01
    xx = np.arange(-10, 10, dx)
    plt.figure(0, figsize=(8, 6))
    for sigma in [0.5, 1, 2]:
        yy = gaussian_1d(xx, sigma)
        ss = np.sum(yy * dx)
        plt.plot(xx, yy, label="sigma = %0.1f, integral = %0.2f" % (sigma, ss))
    plt.legend(loc='best')
    plt.savefig('gaussian_1d.png', dpi=300)
    plt.close(0)


if __name__ == '__main__':
    plot_gaussian_1d()

有效模糊半径

一般而言,增大模糊半径会加强模糊效果。但从曲线形态可以看到,远离对称中心时,高斯核的系数将会变得非常非常小,在做图像模糊时,意味着这些远处的像素对于模糊的贡献将会变得非常小,此时增大半径几乎不会带来模糊程度的增加,但是计算量却丝毫没有减少。

所以这里应当注意一个有效模糊半径的概念。因为 σ \sigma σ会影响曲线的高矮胖瘦,所以容易知道有效模糊半径受 σ \sigma σ影响。为了定义有效模糊半径,我们必须定义一个标准,这个标准应当具有相对性概念。比如简单来说我们针对曲线某个点的数值与最大值的比来进行定义:
arg max ⁡ x ( G ( x , σ ) G ( 0 , σ ) ) > l i m i t \argmax_x(\frac{G(x, \sigma)}{G(0,\sigma)}) > limit xargmax(G(0,σ)G(x,σ))>limit
如果我们把满足上式的最大x称为有效有效模糊半径,那么就可以去找一下其与 σ \sigma σ的关系了。

搞清楚有效模糊半径对于图像处理的实践很重要,避免浪费了算力却并没有得到相应的模糊效果。然而这个概念很少被讨论。

下面是不同的limit情况下sigma与有效模糊半径的关系,很容易看出来这是个线性关系。
因此,假如我们要开发一个“模糊”的功能,只开放一个模糊程度参数,那么一般而言这个参数需要跟半径挂钩,但为了让半径能真正起到作用,就需要适配的sigma,这个sigma可以使用 s i g m a = r a d i u s / a sigma = radius / a sigma=radius/a 来计算得到。针对图像模糊,根据经验,a使用[2, 2.5]之间的数字均可。
高斯模糊与图像处理(Gaussian Blur),数字图像处理,公式推导,图像处理,人工智能

def effective_radius():
    dx = 0.01
    xx = np.arange(0, 100, dx)
    limits = [0.1, 0.01, 0.001]
    colors = ['red', 'green', 'blue']

    sigmas = np.arange(0.1, 10, 0.1)

    plt.figure(0, figsize=(8, 6))
    for i, limit in enumerate(limits):
        effective_r = []
        for sigma in sigmas:
            yy = gaussian_1d(xx, sigma)
            yy = yy / np.max(yy)
            radius = np.max(np.argwhere(yy >= limit))
            effective_r.append(radius * dx)
        plt.plot(sigmas, effective_r, color=colors[i],
                 label='limit=%0.3f' % limit)

    plt.legend(loc='best')
    plt.grid()
    plt.xlabel('sigma')
    plt.ylabel('effective radius')
    plt.savefig('effective radius', dpi=300)
    plt.close(0)

二维高斯核函数

公式

G ( x , y ) = 1 2 π σ x σ y e − ( ( x − μ x ) 2 2 σ x 2 + ( y − μ y ) 2 2 σ y 2 ) G(x,y) = \frac{1}{2\pi\sigma_x\sigma_y}e^{-(\frac{(x-\mu_x)^2 }{2\sigma_x^2} + \frac{(y-\mu_y)^2 }{2\sigma_y^2})} G(x,y)=2πσxσy1e(2σx2(xμx)2+2σy2(yμy)2)

对于图像模糊来说,我们不关心平均值 μ \mu μ和前面的系数,所以公式可以简化为:
G ( x , y ) = e − ( x 2 2 σ x 2 + y 2 2 σ y 2 ) G(x,y) = e^{-(\frac{x^2 }{2\sigma_x^2} + \frac{y^2 }{2\sigma_y^2})} G(x,y)=e(2σx2x2+2σy2y2)

下面是生成kernel的代码和结果

# -*- coding: utf-8 -*-
import cv2
import numpy as np


def gaussian_2d(radius, sigma_x, sigma_y):
    coord = np.arange(-radius, radius, 0.01)
    xx, yy = np.meshgrid(coord, coord)
    res = np.exp(
        -(xx * xx / (sigma_x * sigma_x) + yy * yy / (sigma_y * sigma_y)) / 2)
    res = res / np.sum(res)
    return res


def plot_gaussian_2d():
    radius = 10
    sigma_x = 1.0
    sigma_y = 1.0

    kernel = gaussian_2d(radius, sigma_x, sigma_y)
    kernel = kernel / np.max(kernel)
    kernel = np.clip(np.round(kernel * 255), 0, 255)
    kernel = np.uint8(kernel)

    cv2.imwrite('radius=%d, sigma=(%d, %d).png' % (radius, sigma_x, sigma_y),
                kernel)

高斯模糊与图像处理(Gaussian Blur),数字图像处理,公式推导,图像处理,人工智能

行列嵌套循环的高斯模糊

# -*- coding: utf-8 -*-
import cv2
import numpy as np


def gaussian_2d(radius, sigma_x, sigma_y, d_radius=1):
    coord = np.arange(-radius, radius + d_radius, d_radius)
    xx, yy = np.meshgrid(coord, coord)
    res = np.exp(-(xx * xx / (sigma_x * sigma_x) +
                   yy * yy / (sigma_y * sigma_y)) / 2)
    res = res / np.sum(res)
    return res


def convolve_2d(image, kernel, border='transparent'):
    image_height, image_width = image.shape[:2]
    kernel_height, kernel_width = kernel.shape[:2]
    radius_h = kernel_height // 2
    radius_w = kernel_width // 2

    # check: kernel_height and kernel_width must be odd
    if radius_h * 2 + 1 != kernel_height or radius_w * 2 + 1 != kernel_width:
        raise ValueError('kernel_height and kernel_width must be odd')

    res = np.zeros_like(image, dtype=np.float32)
    for row in range(image_height):
        # print(row)
        for col in range(image_width):
            pix = 0.0
            weight = 0
            for i in range(kernel_height):
                for j in range(kernel_width):
                    row_k = row + i - radius_h
                    col_k = col + j - radius_w
                    if border == 'transparent':
                        if 0 <= row_k < image_height and \
                                0 <= col_k < image_width:
                            pix += image[row_k, col_k] * kernel[i, j]
                            weight += kernel[i, j]
                    elif border == 'zero':
                        if 0 <= row_k < image_height and \
                                0 <= col_k < image_width:
                            pix += image[row_k, col_k] * kernel[i, j]
                        weight += kernel[i, j]
                    elif border == 'copy':
                        if row_k < 0:
                            row_k = 0
                        elif row_k >= image_height:
                            row_k = image_height - 1
                        if col_k < 0:
                            col_k = 0
                        elif col_k >= image_width:
                            col_k = image_width - 1
                        pix += image[row_k, col_k] * kernel[i, j]
                        weight += kernel[i, j]
                    elif border == 'reflect':
                        if row_k < 0:
                            row_k = np.abs(row_k)
                        elif row_k >= image_height:
                            row_k = 2 * (image_height - 1) - row_k
                        if col_k < 0:
                            col_k = np.abs(col_k)
                        elif col_k >= image_height:
                            col_k = 2 * (image_width - 1) - col_k
                        pix += image[row_k, col_k] * kernel[i, j]
                        weight += kernel[i, j]
                    else:
                        raise ValueError('border must be one of '
                                         '[transparent, zero, copy, reflect]')
            res[row, col] = np.float32(pix / weight)
    res = np.uint8(np.clip(np.round(res), 0, 255))
    return res


def main_gaussian_blur():
    radius = 20
    sigma_x = 10.0
    sigma_y = 10.0
    borders = ['transparent', 'zero', 'copy', 'reflect']

    image = cv2.imread('lena_std.bmp')
    kernel = gaussian_2d(radius, sigma_x, sigma_y, d_radius=1)

    for border in borders:
        blur_image = convolve_2d(image, kernel, border)
        cv2.imwrite('blur_radius=%d,sigma=(%0.1f,%0.1f),border=%s.png' % (
            radius, sigma_x, sigma_y, border), blur_image)

上面代码仅用于示例计算流程,因为python的for循环特别慢,所以只要kernel稍微大那么一些,上面的代码就要运行非常非常久。由于图像需要在两个方向循环,kernel也需要在两个方向循环,所以整个下来计算量是o(n^4),特别慢。

除了常规的图像高斯模糊外,上面代码还示例了几种边界条件:

  • transparent:超出边界的索引不参与计算,此种边界条件必需累加weight,最后用累加得到的weight做归一化。这种边界条件因为必须要对weight做累加,所以计算量略大一些些,但效果是几种边界条件中最好最稳定的。
  • zero:超出边界的索引用0代替。因为0代表黑色,随着kernel增大,越来越多的0参与到了边界的模糊中,所以这种边界条件会引起黑边,效果最差。但是对于并行加速来讲,其实现是比较容易的。在神经网络的卷积中使用非常多,但是传统图像处理中尽量避免用这种边界条件。
  • copy:超出边界的索引使用最近的边缘像素值,效果中规中矩,实现也简单。
  • reflect:超出边界的索引,以边界为对称中心取图像内部对应位置的像素值,索引的计算会有些麻烦,特别是当kernel尺寸非常大时,以至于镜像的索引超过了对面的边界。但是当kernel尺寸不那么极端时,这种边界条件的效果一般还不错。

下图是4中边界条件的效果,radius=20,sigma=10。
左上:transparent,右上:zero
左下:copy, 右下:reflect
高斯模糊与图像处理(Gaussian Blur),数字图像处理,公式推导,图像处理,人工智能

行列分离的高斯模糊

高斯模糊使用嵌套循环显然是很差劲的写法。在实践中,一般我们会写成行列分离的形式,此时计算量从o(n^4) 降低到 o(n^3)。
上面我们写过二维高斯核函数为:
G ( x , y ) = e − ( x 2 2 σ x 2 + y 2 2 σ y 2 ) G(x,y) = e^{-(\frac{x^2 }{2\sigma_x^2} + \frac{y^2 }{2\sigma_y^2})} G(x,y)=e(2σx2x2+2σy2y2)
注意此函数可以拆开写成x,y分离的形式。

G ( x ) = e − x 2 2 σ x 2 G ( y ) = e − y 2 2 σ y 2 G(x) = e^{-\frac{x^2 }{2\sigma_x^2}} \\[2ex] G(y) = e^{-\frac{y^2 }{2\sigma_y^2}} G(x)=e2σx2x2G(y)=e2σy2y2
那么有:
G ( x , y ) = e − x 2 2 σ x 2 ⋅ e − y 2 2 σ y 2 = G ( x ) G ( y ) G(x,y) = e^{-\frac{x^2 }{2\sigma_x^2}} \cdot e^{-\frac{y^2 }{2\sigma_y^2}}=G(x)G(y) G(x,y)=e2σx2x2e2σy2y2=G(x)G(y)
然后一个高斯模糊的计算过程为:
b l u r ( x , y ) = ∫ ∫ I ( x , y ) G ( x , y ) d x d y = ∫ ∫ I ( x , y ) G ( x ) G ( y ) d x d y = ∫ [ ∫ I ( x , y ) G ( x ) d x ] ⋅ G ( y ) d y ( 写成离散形式 ) = ∑ y i [ ∑ x i I ( x i , y i ) G ( x i ) ] G ( y i ) \begin{aligned} blur(x,y) &= \int \int I(x,y)G(x,y)dxdy \\[2ex] &= \int \int I(x,y)G(x)G(y)dxdy \\[2ex] &=\int [\int I(x,y)G(x)dx] \cdot G(y)dy \\[2ex] & (写成离散形式) \\[2ex] & =\sum_{y_i} [\sum_{x_i} I(x_i,y_i)G(x_i)]G(y_i) \end{aligned} blur(x,y)=∫∫I(x,y)G(x,y)dxdy=∫∫I(x,y)G(x)G(y)dxdy=[I(x,y)G(x)dx]G(y)dy(写成离散形式)=yi[xiI(xi,yi)G(xi)]G(yi)

也就是说在x方向进行模糊,然后对这个中间结果在y方向再做模糊即可,每次只在一个方向做循环,并且这两个循环不是嵌套,而是分离的。下面代码没有再实现多种边界条件,只写了transparent类型的。

# -*- coding: utf-8 -*-
import cv2
import numpy as np


def gaussian_1d(radius, sigma, d_radius=1):
    xx = np.arange(-radius, radius + d_radius, d_radius)
    res = np.exp(-xx * xx / (sigma * sigma) / 2)
    res = res / np.sum(res)
    return res


def convolve_2d_xy(image, kernel_x, kernel_y):
    image_height, image_width = image.shape[:2]
    kernel_x_len = len(kernel_x)
    kernel_y_len = len(kernel_y)
    radius_x = kernel_x_len // 2
    radius_y = kernel_y_len // 2

    # check: kernel_height and kernel_width must be odd
    if radius_x * 2 + 1 != kernel_x_len or radius_y * 2 + 1 != kernel_y_len:
        raise ValueError('kernel size must be odd')

    res = np.zeros_like(image, dtype=np.float32)
    # convolve in x direction
    for row in range(image_height):
        for col in range(image_width):
            pix = 0.0
            weight = 0
            for j in range(kernel_x_len):
                col_k = col + j - radius_x
                if 0 <= col_k < image_width:
                    pix += image[row, col_k] * kernel_x[j]
                    weight += kernel_x[j]
            res[row, col] = pix / weight

    # convolve in y direction
    image = res.copy()
    for col in range(image_width):
        for row in range(image_height):
            pix = 0.0
            weight = 0
            for i in range(kernel_y_len):
                row_k = row + i - radius_y
                if 0 <= row_k < image_height:
                    pix += image[row_k, col] * kernel_y[i]
                    weight += kernel_y[i]
            res[row, col] = pix / weight
    res = np.uint8(np.clip(np.round(res), 0, 255))
    return res


def main_gaussian_blur_xy():
    radius = 20
    sigma_x = 10.0
    sigma_y = 10.0

    image = cv2.imread('lena_std.bmp')
    kernel_x = gaussian_1d(radius, sigma_x, d_radius=1)
    kernel_y = gaussian_1d(radius, sigma_y, d_radius=1)

    blur_image = convolve_2d_xy(image, kernel_x, kernel_y)
    cv2.imwrite('xy_blur_radius=%d,sigma=(%0.1f,%0.1f).png' % (
        radius, sigma_x, sigma_y), blur_image)

行列分离的耗时在我电脑上大概是45s,嵌套循环大概需要1020秒。尽管python的循环特别慢,这个时间对比可能做不得数,但是量级上的差异还是比较能说明问题了。

下面左图是之前嵌套循环得到的结果,中间是行列分离得到的结果,右图是两者的差的绝对值再乘以50,结果来看两个模糊的结果完全一样。
高斯模糊与图像处理(Gaussian Blur),数字图像处理,公式推导,图像处理,人工智能

加上step的高斯模糊

当模糊的radius非常大时候,可以适当加上一些step来节省计算。
此时应当注意,为了达到预想中的模糊效果,不仅image patch与kernel乘加时的索引需要加上step,kernel系数的计算也需要加上step,不然与不加step时候的系数会有很大差异。

# -*- coding: utf-8 -*-
import cv2
import numpy as np
import time


def gaussian_1d(radius, sigma, d_radius=1.0):
    xx = np.arange(-radius, radius + d_radius, d_radius)
    res = np.exp(-xx * xx / (sigma * sigma) / 2)![请添加图片描述](https://img-blog.csdnimg.cn/0d509cd3e63a4f4680df49de7b807309.png)

    res = res / np.sum(res)
    return res


def convolve_2d_xy_step(image, kernel_x, kernel_y, step):
    image_height, image_width = image.shape[:2]
    kernel_x_len = len(kernel_x)
    kernel_y_len = len(kernel_y)
    radius_x = kernel_x_len // 2
    radius_y = kernel_y_len // 2

    # check: kernel_height and kernel_width must be odd
    if radius_x * 2 + 1 != kernel_x_len or radius_y * 2 + 1 != kernel_y_len:
        raise ValueError('kernel size must be odd')

    res = np.zeros_like(image, dtype=np.float32)
    # convolve in x direction
    for row in range(image_height):
        for col in range(image_width):
            pix = 0.0
            weight = 0
            for j in range(kernel_x_len):
                col_k = int(round(col + (j - radius_x) * step))
                if 0 <= col_k < image_width:
                    pix += image[row, col_k] * kernel_x[j]
                    weight += kernel_x[j]
            res[row, col] = pix / weight

    # convolve in y direction
    image = res.copy()
    for col in range(image_width):
        for row in range(image_height):
            pix = 0.0
            weight = 0
            for i in range(kernel_y_len):
                row_k = int(round(row + (i - radius_y) * step))
                if 0 <= row_k < image_height:
                    pix += image[row_k, col] * kernel_y[i]
                    weight += kernel_y[i]
            res[row, col] = pix / weight
    res = np.uint8(np.clip(np.round(res), 0, 255))
    return res


def main_gaussian_blur_xy():
    radius = 20
    sigma_x = 10.0
    sigma_y = 10.0
    step = 4.0

    image = cv2.imread('lena_std.bmp')
    kernel_x = gaussian_1d(radius, sigma_x, d_radius=step)
    kernel_y = gaussian_1d(radius, sigma_y, d_radius=step)

    blur_image = convolve_2d_xy_step(image, kernel_x, kernel_y, step)
    cv2.imwrite('xy_blur_radius=%d,sigma=(%0.1f,%0.1f)_step.png' % (
        radius, sigma_x, sigma_y), blur_image)


下面左图是之前嵌套循环得到的结果,中间是行列分离+step=4得到的结果,右图是两者的差的绝对值再乘以50。
此时计算出来的diff已经不再是全零,如果仔细看中间的结果,显示出了一些块状纹理,表明模糊的品质已经开始受到影响。
高斯模糊与图像处理(Gaussian Blur),数字图像处理,公式推导,图像处理,人工智能

任意二维高斯核的生成

这里任意高斯核指的是任意长宽比,且存在旋转角度的高斯核。
公式推导的思路是,把高斯核G(x,y)看做是一个图像,然后用图像旋转的思路来改造二维高斯核的公式。

下面我们再次把高斯核公式摆在这里。
G ( x , y ) = e − ( x 2 2 σ x 2 + y 2 2 σ y 2 ) G(x,y) = e^{-(\frac{x^2 }{2\sigma_x^2} + \frac{y^2 }{2\sigma_y^2})} G(x,y)=e(2σx2x2+2σy2y2)
根据图像旋转的原理,当图像中某个点(x, y)以圆心作为旋转中心,沿逆时针旋转后,新的点(x’, y’)的坐标公式为:
{ x ′ = x ∗ c o s θ − y ∗ s i n θ y ′ = x ∗ s i n θ + y ∗ c o s θ \begin{cases} x' = x*cos\theta - y*sin\theta \\ y' = x*sin\theta + y*cos\theta \end{cases} \\[4ex] {x=xcosθysinθy=xsinθ+ycosθ

将其代入高斯核公式,并且方便起见仍以(x, y)来表示,那么有:
G ( x , y ) = e − ( ( x ∗ c o s θ − y ∗ s i n θ ) 2 2 σ x 2 + ( x ∗ s i n θ + y ∗ c o s θ ) 2 2 σ y 2 ) = e − ( x 2 ∗ c o s 2 θ + y 2 ∗ s i n 2 θ − 2 x y ∗ s i n θ c o s θ 2 σ x 2 + x 2 s i n 2 θ + y 2 ∗ c o s 2 θ + 2 x y ∗ s i n θ c o s θ 2 σ y 2 ) = e − ( x 2 ( c o s 2 θ 2 σ x 2 + s i n 2 θ 2 σ y 2 ) + x y ( − s i n 2 θ 2 σ x 2 + s i n 2 θ 2 σ y 2 ) + y 2 ( s i n 2 θ 2 σ x 2 + c o s 2 θ 2 σ y 2 ) ) \begin{aligned} G(x,y) &= e^{-(\frac{(x*cos\theta - y*sin\theta)^2 }{2\sigma_x^2} + \frac{(x*sin\theta + y*cos\theta)^2 }{2\sigma_y^2})} \\[2ex] &=e^{-(\frac{x^2*cos^2\theta + y^2*sin^2\theta -2xy*sin\theta cos\theta}{2\sigma_x^2} + \frac{x^2sin^2\theta + y^2*cos^2\theta + 2xy*sin\theta cos\theta }{2\sigma_y^2})} \\[2ex] &=e^{-(x^2(\frac{cos^2\theta}{2\sigma_x^2} + \frac{sin^2\theta}{2\sigma_y^2}) + xy(-\frac{sin2\theta}{2\sigma_x^2} + \frac{sin2\theta}{2\sigma_y^2}) + y^2( \frac{sin^2\theta}{2\sigma_x^2} + \frac{cos^2\theta}{2\sigma_y^2} ))} \end{aligned} G(x,y)=e(2σx2(xcosθysinθ)2+2σy2(xsinθ+ycosθ)2)=e(2σx2x2cos2θ+y2sin2θ2xysinθcosθ+2σy2x2sin2θ+y2cos2θ+2xysinθcosθ)=e(x2(2σx2cos2θ+2σy2sin2θ)+xy(2σx2sin2θ+2σy2sin2θ)+y2(2σx2sin2θ+2σy2cos2θ))

上述公式就是任意二维高斯核的样子。
下面是python的实现代码和图,将一个沿横向比较长的kernel逆时针旋转了20度。
高斯模糊与图像处理(Gaussian Blur),数字图像处理,公式推导,图像处理,人工智能文章来源地址https://www.toymoban.com/news/detail-640131.html

# -*- coding: utf-8 -*-
import cv2
import numpy as np


def generalized_gaussian_kernel(ksize,
                                sigma_x,
                                sigma_y=None,
                                angle=0.0):
    """
    Generate generalized gaussian kernel.

    Parameters
    ----------
    ksize: kernel size, one integer or a list/tuple of two integers, must be
        odd
    sigma_x: standard deviation in x direction
    sigma_y: standard deviation in y direction
    angle: rotate angle, anti-clockwise

    Returns
    -------
    kernel: generalized gaussian blur kernel
    """
    # check parameters
    if not isinstance(ksize, (tuple, list)):
        ksize = [ksize, ksize]
    else:
        ksize = list(ksize)
    ksize[0] = ksize[0] // 2 * 2 + 1
    ksize[1] = ksize[1] // 2 * 2 + 1

    if sigma_y is None:
        sigma_y = sigma_x

    # meshgrid coordinates
    radius_x = ksize[0] // 2
    radius_y = ksize[1] // 2
    x = np.arange(-radius_x, radius_x + 1, 1)
    y = np.arange(-radius_y, radius_y + 1, 1)
    xx, yy = np.meshgrid(x, y)

    # coefficients of coordinates
    angle = angle / 180 * np.pi
    cos_square = np.cos(angle) ** 2
    sin_square = np.sin(angle) ** 2
    sin_2 = np.sin(2 * angle)

    alpha = 0.5 / (sigma_x * sigma_x)
    beta = 0.5 / (sigma_y * sigma_y)
    a = cos_square * alpha + sin_square * beta
    b = -sin_2 * alpha + sin_2 * beta
    c = sin_square * alpha + cos_square * beta

    # generate and normalize kernel
    kernel = np.exp(-(a * xx * xx + b * xx * yy + c * yy * yy))
    kernel = kernel / np.sum(kernel)
    return kernel


if __name__ == '__main__':
    ksize = (511, 511)
    sigma_x = 100.0
    sigma_y = 20.0
    angle = 20.0

    gaussian_kernel = generalized_gaussian_kernel(ksize=ksize,
                                                  sigma_x=sigma_x,
                                                  sigma_y=sigma_y,
                                                  angle=angle)
    gaussian_kernel = gaussian_kernel / np.max(gaussian_kernel)
    gaussian_kernel = np.uint8(np.round(gaussian_kernel * 255))
    cv2.imwrite('generalized_gaussian_kernel_1.png', gaussian_kernel)

到了这里,关于高斯模糊与图像处理(Gaussian Blur)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • (数字图像处理MATLAB+Python)第五章图像增强-第四、五节:基于模糊技术和基于伪彩色处理的图像增强

    图像的模糊特征平面 :假设原始图像为 I ( x , y ) I(x,y) I ( x , y ) ,其中 x x x 和 y y y 分别表示图像的水平和垂直方向的坐标。模糊特征平面可以表示为 B ( x , y , θ ) B(x,y,theta) B ( x , y , θ ) ,其中 θ theta θ 是一个旋转角度参数,表示模糊核函数的旋转角度。 B ( x , y , θ ) B(x,

    2023年04月20日
    浏览(105)
  • 【数字图像处理】灰度图像中添加高斯噪声、椒盐噪声、斑点噪声以及利用不同方法(中值、排序、维纳滤波)去除各种噪声的matlab程序

    图像处理问题描述: 1、图像中分别加入不同方差的高斯噪声、不同噪声密度椒盐噪声和不同方差的斑点噪声(Gaussian noise, salt  pepper noise and speckle noise) 2、分别通过函数medfilt2、ordfilt2和 Wiener 2 去除图像中添加的一些噪声(Gaussian noise, salt  pepper noise and speckle noise)。 各部

    2024年02月07日
    浏览(57)
  • opencv 30 -图像平滑处理01-均值滤波 cv2.blur()

    图像平滑处理(Image Smoothing)是一种图像处理技术,旨在减少图像中的噪声、去除细节并平滑图像的过渡部分。这种处理常用于预处理图像,以便在后续图像处理任务中获得更好的结果。 常用的图像平滑处理方法包括: 均值滤波(Mean Filtering) :用图像中像素周围区域的平

    2024年02月01日
    浏览(56)
  • 图像处理之高斯滤波

    高斯函数广泛应用于统计学领域,用于表述正态分布,在信号处理领域,用于定义高斯滤波器,在图像处理领域,二维高斯核函数常用于高斯模糊Gaussian Blur,在数学领域,主要是用于解决热力方程和扩散方程,以及定义Weiertrass Transform。 高斯函数,Gaussian Function, 也简称为

    2024年02月16日
    浏览(40)
  • 图像处理:高斯滤波算法

    目录 前言 概念介绍 基本原理 卷积核的大小 卷积核的形状和权重比 卷积核的归一化 结论 Opencv实现高斯滤波 Python手写实现高斯滤波 参考文章 在此之前,我曾在此篇中推导过图像处理:推导五种滤波算法(均值、中值、高斯、双边、引导)。这在此基础上,我想更深入地研

    2024年02月02日
    浏览(39)
  • 基于OpenCV的传统视觉应用 -- OpenCV图像处理 图像模糊处理 图像锐化处理

    图像处理是用计算机对图像进行分析,以获取所需结果的过程,又称为影像处理。图像处理一般是指数字图像的处理。数字图像是用工业相机、摄像机、扫描仪等设备经过拍摄得到的一个大的二维数组,该数组的元素称为像素,其值称为灰度值。 均值滤波是指任意一点的像素

    2024年02月07日
    浏览(74)
  • 【图像处理OpenCV(C++版)】——5.2 图像平滑之高斯平滑

    前言 : 😊😊😊 欢迎来到本博客 😊😊😊 🌟🌟🌟 本专栏主要结合OpenCV和C++来实现一些基本的图像处理算法并详细解释各参数含义,适用于平时学习、工作快速查询等,随时更新。 😊😊😊 具体食用方式:可以点击本专栏【OpenCV快速查找(更新中)】–搜索你要查询的算子

    2024年02月15日
    浏览(46)
  • 图像处理之LoG算子(高斯拉普拉斯)

    LoG算子是由拉普拉斯算子改进而来。拉普拉斯算子是二阶导数算子,是一个标量,具有线性、位移不变性,其传函在频域空间的原点为0。所有经过拉普拉斯算子滤波的图像具有零平均灰度。但是该算子的缺点是对噪声具有敏感性,因此在实际应用中,一般先要对图像进行平滑

    2024年02月16日
    浏览(47)
  • 图像模糊处理(c++题解)

    给定n行m列的图像各像素点的灰度值,要求用如下方法对其进行模糊化处理: 四周最外侧的像素点灰度值不变; 中间各像素点新灰度值为该像素点及其上下左右相邻四个像素点原灰度值的平均(舍入到最接近的整数)。 第一行包含两个整数n和m,表示图像包含像素点的行数和

    2024年01月22日
    浏览(38)
  • 图像处理:随机添加椒盐噪声和高斯噪声Python

    目录 图像处理:随机添加椒盐噪声和高斯噪声Python 1.常见的图像噪声 (1)高斯噪声 (2) 椒盐噪声 2.生成图像噪声 (1)高斯噪声 (2) 椒盐噪声(速度慢) (3) 椒盐噪声(快速版) 3. Demo测试         图像噪声是指存在于图像数据中的不必要的或多余的干扰信息。在噪

    2024年02月02日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包