国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

高斯模糊與圖像處理(Gaussian Blur)

這篇具有很好參考價(jià)值的文章主要介紹了高斯模糊與圖像處理(Gaussian Blur)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

高斯模糊在圖像處理中的用途及其廣泛,除了常規(guī)的模糊效果外,還可用于圖像金字塔分解、反走樣、高低頻分解、噪聲壓制、發(fā)光效果等等等等。正因?yàn)楦咚鼓:A(chǔ),應(yīng)用太廣泛,所以需要盡可能深入認(rèn)識(shí)這個(gè)能力,避免在實(shí)際應(yīng)用中無意采坑。

一維高斯核函數(shù)

公式

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π ?σ1?e?2σ2(x?μ)2?

其中 μ \mu μ是對(duì)稱軸,圖像處理中通常不會(huì)考慮 μ ≠ 0 \mu \neq0 μ=0的情況,所以該參數(shù)可以忽略(本文自此向下均忽略 μ \mu μ)。

σ \sigma σ決定函數(shù)的高矮胖瘦, σ \sigma σ越小越高瘦,越大越矮胖。如果用于模糊的話,高瘦意味著中心像素對(duì)于計(jì)算結(jié)果的貢獻(xiàn)大,而遠(yuǎn)處的像素貢獻(xiàn)相對(duì)較小,也就是說模糊結(jié)果更多受中心像素支配,因此模糊程度就低;反之矮胖意味著模糊程度高。所以其他條件不變的情況下,增大 σ \sigma σ會(huì)加強(qiáng)模糊,反之會(huì)減弱模糊。

e指數(shù)前的系數(shù)保證了核函數(shù)在 ( ? ∞ , + ∞ ) (-\infty, +\infty) (?,+)的積分為1,不過在圖像處理中,我們顯然不可能用無窮大的半徑,所以會(huì)對(duì)高斯核的系數(shù)做歸一化,那么e指數(shù)前的系數(shù)在歸一化中就被約去了,所以干脆就不用計(jì)算。

曲線形態(tài)

下圖是一維高斯核函數(shù)的曲線形態(tài)。

注意下圖仍然計(jì)算了e指數(shù)前的系數(shù),并驗(yàn)證了核函數(shù)的積分,表明無論 σ \sigma σ怎么變化,其積分總是為1。

高斯模糊與圖像處理(Gaussian Blur),數(shù)字圖像處理,公式推導(dǎo),圖像處理,人工智能

# -*- 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()

有效模糊半徑

一般而言,增大模糊半徑會(huì)加強(qiáng)模糊效果。但從曲線形態(tài)可以看到,遠(yuǎn)離對(duì)稱中心時(shí),高斯核的系數(shù)將會(huì)變得非常非常小,在做圖像模糊時(shí),意味著這些遠(yuǎn)處的像素對(duì)于模糊的貢獻(xiàn)將會(huì)變得非常小,此時(shí)增大半徑幾乎不會(huì)帶來模糊程度的增加,但是計(jì)算量卻絲毫沒有減少。

所以這里應(yīng)當(dāng)注意一個(gè)有效模糊半徑的概念。因?yàn)?span id="n5n3t3z" class="katex--inline"> σ \sigma σ會(huì)影響曲線的高矮胖瘦,所以容易知道有效模糊半徑受 σ \sigma σ影響。為了定義有效模糊半徑,我們必須定義一個(gè)標(biāo)準(zhǔn),這個(gè)標(biāo)準(zhǔn)應(yīng)當(dāng)具有相對(duì)性概念。比如簡(jiǎn)單來說我們針對(duì)曲線某個(gè)點(diǎn)的數(shù)值與最大值的比來進(jìn)行定義:
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 σ的關(guān)系了。

搞清楚有效模糊半徑對(duì)于圖像處理的實(shí)踐很重要,避免浪費(fèi)了算力卻并沒有得到相應(yīng)的模糊效果。然而這個(gè)概念很少被討論。

下面是不同的limit情況下sigma與有效模糊半徑的關(guān)系,很容易看出來這是個(gè)線性關(guān)系。
因此,假如我們要開發(fā)一個(gè)“模糊”的功能,只開放一個(gè)模糊程度參數(shù),那么一般而言這個(gè)參數(shù)需要跟半徑掛鉤,但為了讓半徑能真正起到作用,就需要適配的sigma,這個(gè)sigma可以使用 s i g m a = r a d i u s / a sigma = radius / a sigma=radius/a 來計(jì)算得到。針對(duì)圖像模糊,根據(jù)經(jīng)驗(yàn),a使用[2, 2.5]之間的數(shù)字均可。
高斯模糊與圖像處理(Gaussian Blur),數(shù)字圖像處理,公式推導(dǎo),圖像處理,人工智能

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)

二維高斯核函數(shù)

公式

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?σy?1?e?(2σx2?(x?μx?)2?+2σy2?(y?μy?)2?)

對(duì)于圖像模糊來說,我們不關(guān)心平均值 μ \mu μ和前面的系數(shù),所以公式可以簡(jiǎn)化為:
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σx2?x2?+2σy2?y2?)

下面是生成kernel的代碼和結(jié)果

# -*- 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),數(shù)字圖像處理,公式推導(dǎo),圖像處理,人工智能

行列嵌套循環(huán)的高斯模糊

# -*- 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)

上面代碼僅用于示例計(jì)算流程,因?yàn)閜ython的for循環(huán)特別慢,所以只要kernel稍微大那么一些,上面的代碼就要運(yùn)行非常非常久。由于圖像需要在兩個(gè)方向循環(huán),kernel也需要在兩個(gè)方向循環(huán),所以整個(gè)下來計(jì)算量是o(n^4),特別慢。

除了常規(guī)的圖像高斯模糊外,上面代碼還示例了幾種邊界條件:

  • transparent:超出邊界的索引不參與計(jì)算,此種邊界條件必需累加weight,最后用累加得到的weight做歸一化。這種邊界條件因?yàn)楸仨氁獙?duì)weight做累加,所以計(jì)算量略大一些些,但效果是幾種邊界條件中最好最穩(wěn)定的。
  • zero:超出邊界的索引用0代替。因?yàn)?代表黑色,隨著kernel增大,越來越多的0參與到了邊界的模糊中,所以這種邊界條件會(huì)引起黑邊,效果最差。但是對(duì)于并行加速來講,其實(shí)現(xiàn)是比較容易的。在神經(jīng)網(wǎng)絡(luò)的卷積中使用非常多,但是傳統(tǒng)圖像處理中盡量避免用這種邊界條件。
  • copy:超出邊界的索引使用最近的邊緣像素值,效果中規(guī)中矩,實(shí)現(xiàn)也簡(jiǎn)單。
  • reflect:超出邊界的索引,以邊界為對(duì)稱中心取圖像內(nèi)部對(duì)應(yīng)位置的像素值,索引的計(jì)算會(huì)有些麻煩,特別是當(dāng)kernel尺寸非常大時(shí),以至于鏡像的索引超過了對(duì)面的邊界。但是當(dāng)kernel尺寸不那么極端時(shí),這種邊界條件的效果一般還不錯(cuò)。

下圖是4中邊界條件的效果,radius=20,sigma=10。
左上:transparent,右上:zero
左下:copy, 右下:reflect
高斯模糊與圖像處理(Gaussian Blur),數(shù)字圖像處理,公式推導(dǎo),圖像處理,人工智能

行列分離的高斯模糊

高斯模糊使用嵌套循環(huán)顯然是很差勁的寫法。在實(shí)踐中,一般我們會(huì)寫成行列分離的形式,此時(shí)計(jì)算量從o(n^4) 降低到 o(n^3)。
上面我們寫過二維高斯核函數(shù)為:
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σx2?x2?+2σy2?y2?)
注意此函數(shù)可以拆開寫成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)=e?2σx2?x2?G(y)=e?2σy2?y2?
那么有:
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)=e?2σx2?x2??e?2σy2?y2?=G(x)G(y)
然后一個(gè)高斯模糊的計(jì)算過程為:
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??[xi??I(xi?,yi?)G(xi?)]G(yi?)?

也就是說在x方向進(jìn)行模糊,然后對(duì)這個(gè)中間結(jié)果在y方向再做模糊即可,每次只在一個(gè)方向做循環(huán),并且這兩個(gè)循環(huán)不是嵌套,而是分離的。下面代碼沒有再實(shí)現(xiàn)多種邊界條件,只寫了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)

行列分離的耗時(shí)在我電腦上大概是45s,嵌套循環(huán)大概需要1020秒。盡管python的循環(huán)特別慢,這個(gè)時(shí)間對(duì)比可能做不得數(shù),但是量級(jí)上的差異還是比較能說明問題了。

下面左圖是之前嵌套循環(huán)得到的結(jié)果,中間是行列分離得到的結(jié)果,右圖是兩者的差的絕對(duì)值再乘以50,結(jié)果來看兩個(gè)模糊的結(jié)果完全一樣。
高斯模糊與圖像處理(Gaussian Blur),數(shù)字圖像處理,公式推導(dǎo),圖像處理,人工智能

加上step的高斯模糊

當(dāng)模糊的radius非常大時(shí)候,可以適當(dāng)加上一些step來節(jié)省計(jì)算。
此時(shí)應(yīng)當(dāng)注意,為了達(dá)到預(yù)想中的模糊效果,不僅image patch與kernel乘加時(shí)的索引需要加上step,kernel系數(shù)的計(jì)算也需要加上step,不然與不加step時(shí)候的系數(shù)會(huì)有很大差異。

# -*- 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)![請(qǐng)?zhí)砑訄D片描述](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)


下面左圖是之前嵌套循環(huán)得到的結(jié)果,中間是行列分離+step=4得到的結(jié)果,右圖是兩者的差的絕對(duì)值再乘以50。
此時(shí)計(jì)算出來的diff已經(jīng)不再是全零,如果仔細(xì)看中間的結(jié)果,顯示出了一些塊狀紋理,表明模糊的品質(zhì)已經(jīng)開始受到影響。
高斯模糊與圖像處理(Gaussian Blur),數(shù)字圖像處理,公式推導(dǎo),圖像處理,人工智能

任意二維高斯核的生成

這里任意高斯核指的是任意長(zhǎng)寬比,且存在旋轉(zhuǎn)角度的高斯核。
公式推導(dǎo)的思路是,把高斯核G(x,y)看做是一個(gè)圖像,然后用圖像旋轉(zhuǎn)的思路來改造二維高斯核的公式。

下面我們?cè)俅伟迅咚购斯綌[在這里。
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σx2?x2?+2σy2?y2?)
根據(jù)圖像旋轉(zhuǎn)的原理,當(dāng)圖像中某個(gè)點(diǎn)(x, y)以圓心作為旋轉(zhuǎn)中心,沿逆時(shí)針旋轉(zhuǎn)后,新的點(diǎn)(x’, y’)的坐標(biāo)公式為:
{ 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=x?cosθ?y?sinθy=x?sinθ+y?cosθ?

將其代入高斯核公式,并且方便起見仍以(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?(x?cosθ?y?sinθ)2?+2σy2?(x?sinθ+y?cosθ)2?)=e?(2σx2?x2?cos2θ+y2?sin2θ?2xy?sinθcosθ?+2σy2?x2sin2θ+y2?cos2θ+2xy?sinθcosθ?)=e?(x2(2σx2?cos2θ?+2σy2?sin2θ?)+xy(?2σx2?sin2θ?+2σy2?sin2θ?)+y2(2σx2?sin2θ?+2σy2?cos2θ?))?

上述公式就是任意二維高斯核的樣子。
下面是python的實(shí)現(xiàn)代碼和圖,將一個(gè)沿橫向比較長(zhǎng)的kernel逆時(shí)針旋轉(zhuǎn)了20度。
高斯模糊與圖像處理(Gaussian Blur),數(shù)字圖像處理,公式推導(dǎo),圖像處理,人工智能文章來源地址http://www.zghlxwxcb.cn/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)

到了這里,關(guān)于高斯模糊與圖像處理(Gaussian Blur)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • (數(shù)字圖像處理MATLAB+Python)第五章圖像增強(qiáng)-第四、五節(jié):基于模糊技術(shù)和基于偽彩色處理的圖像增強(qiáng)

    (數(shù)字圖像處理MATLAB+Python)第五章圖像增強(qiáng)-第四、五節(jié):基于模糊技術(shù)和基于偽彩色處理的圖像增強(qiáng)

    圖像的模糊特征平面 :假設(shè)原始圖像為 I ( x , y ) I(x,y) I ( x , y ) ,其中 x x x 和 y y y 分別表示圖像的水平和垂直方向的坐標(biāo)。模糊特征平面可以表示為 B ( x , y , θ ) B(x,y,theta) B ( x , y , θ ) ,其中 θ theta θ 是一個(gè)旋轉(zhuǎn)角度參數(shù),表示模糊核函數(shù)的旋轉(zhuǎn)角度。 B ( x , y , θ ) B(x,

    2023年04月20日
    瀏覽(102)
  • 【數(shù)字圖像處理】灰度圖像中添加高斯噪聲、椒鹽噪聲、斑點(diǎn)噪聲以及利用不同方法(中值、排序、維納濾波)去除各種噪聲的matlab程序

    【數(shù)字圖像處理】灰度圖像中添加高斯噪聲、椒鹽噪聲、斑點(diǎn)噪聲以及利用不同方法(中值、排序、維納濾波)去除各種噪聲的matlab程序

    圖像處理問題描述: 1、圖像中分別加入不同方差的高斯噪聲、不同噪聲密度椒鹽噪聲和不同方差的斑點(diǎn)噪聲(Gaussian noise, salt ?pepper noise and speckle noise) 2、分別通過函數(shù)medfilt2、ordfilt2和?Wiener 2 去除圖像中添加的一些噪聲(Gaussian noise, salt ?pepper noise and speckle noise)。 各部

    2024年02月07日
    瀏覽(32)
  • opencv 30 -圖像平滑處理01-均值濾波 cv2.blur()

    opencv 30 -圖像平滑處理01-均值濾波 cv2.blur()

    圖像平滑處理(Image Smoothing)是一種圖像處理技術(shù),旨在減少圖像中的噪聲、去除細(xì)節(jié)并平滑圖像的過渡部分。這種處理常用于預(yù)處理圖像,以便在后續(xù)圖像處理任務(wù)中獲得更好的結(jié)果。 常用的圖像平滑處理方法包括: 均值濾波(Mean Filtering) :用圖像中像素周圍區(qū)域的平

    2024年02月01日
    瀏覽(88)
  • 圖像處理之高斯濾波

    圖像處理之高斯濾波

    高斯函數(shù)廣泛應(yīng)用于統(tǒng)計(jì)學(xué)領(lǐng)域,用于表述正態(tài)分布,在信號(hào)處理領(lǐng)域,用于定義高斯濾波器,在圖像處理領(lǐng)域,二維高斯核函數(shù)常用于高斯模糊Gaussian Blur,在數(shù)學(xué)領(lǐng)域,主要是用于解決熱力方程和擴(kuò)散方程,以及定義Weiertrass Transform。 高斯函數(shù),Gaussian Function, 也簡(jiǎn)稱為

    2024年02月16日
    瀏覽(12)
  • 圖像處理:高斯濾波算法

    圖像處理:高斯濾波算法

    目錄 前言 概念介紹 基本原理 卷積核的大小 卷積核的形狀和權(quán)重比 卷積核的歸一化 結(jié)論 Opencv實(shí)現(xiàn)高斯濾波 Python手寫實(shí)現(xiàn)高斯濾波 參考文章 在此之前,我曾在此篇中推導(dǎo)過圖像處理:推導(dǎo)五種濾波算法(均值、中值、高斯、雙邊、引導(dǎo))。這在此基礎(chǔ)上,我想更深入地研

    2024年02月02日
    瀏覽(21)
  • 基于OpenCV的傳統(tǒng)視覺應(yīng)用 -- OpenCV圖像處理 圖像模糊處理 圖像銳化處理

    基于OpenCV的傳統(tǒng)視覺應(yīng)用 -- OpenCV圖像處理 圖像模糊處理 圖像銳化處理

    圖像處理是用計(jì)算機(jī)對(duì)圖像進(jìn)行分析,以獲取所需結(jié)果的過程,又稱為影像處理。圖像處理一般是指數(shù)字圖像的處理。數(shù)字圖像是用工業(yè)相機(jī)、攝像機(jī)、掃描儀等設(shè)備經(jīng)過拍攝得到的一個(gè)大的二維數(shù)組,該數(shù)組的元素稱為像素,其值稱為灰度值。 均值濾波是指任意一點(diǎn)的像素

    2024年02月07日
    瀏覽(99)
  • 【圖像處理OpenCV(C++版)】——5.2 圖像平滑之高斯平滑

    【圖像處理OpenCV(C++版)】——5.2 圖像平滑之高斯平滑

    前言 : ?????? 歡迎來到本博客 ?????? ?????? 本專欄主要結(jié)合OpenCV和C++來實(shí)現(xiàn)一些基本的圖像處理算法并詳細(xì)解釋各參數(shù)含義,適用于平時(shí)學(xué)習(xí)、工作快速查詢等,隨時(shí)更新。 ?????? 具體食用方式:可以點(diǎn)擊本專欄【OpenCV快速查找(更新中)】–搜索你要查詢的算子

    2024年02月15日
    瀏覽(17)
  • 圖像處理之LoG算子(高斯拉普拉斯)

    圖像處理之LoG算子(高斯拉普拉斯)

    LoG算子是由拉普拉斯算子改進(jìn)而來。拉普拉斯算子是二階導(dǎo)數(shù)算子,是一個(gè)標(biāo)量,具有線性、位移不變性,其傳函在頻域空間的原點(diǎn)為0。所有經(jīng)過拉普拉斯算子濾波的圖像具有零平均灰度。但是該算子的缺點(diǎn)是對(duì)噪聲具有敏感性,因此在實(shí)際應(yīng)用中,一般先要對(duì)圖像進(jìn)行平滑

    2024年02月16日
    瀏覽(27)
  • 圖像模糊處理(c++題解)

    給定n行m列的圖像各像素點(diǎn)的灰度值,要求用如下方法對(duì)其進(jìn)行模糊化處理: 四周最外側(cè)的像素點(diǎn)灰度值不變; 中間各像素點(diǎn)新灰度值為該像素點(diǎn)及其上下左右相鄰四個(gè)像素點(diǎn)原灰度值的平均(舍入到最接近的整數(shù))。 第一行包含兩個(gè)整數(shù)n和m,表示圖像包含像素點(diǎn)的行數(shù)和

    2024年01月22日
    瀏覽(24)
  • Matlab圖像處理- 高斯低通濾波器

    Matlab圖像處理- 高斯低通濾波器

    ? 高斯低通濾波器 高斯低通濾波器是一種 更平滑的一種濾波器 ,高斯低通濾波器完全沒有振鈴現(xiàn)象,且邊緣平滑。 示例代碼 利用輸入圖像,構(gòu)建一個(gè)截止頻率為30的高斯低通濾波器的透視圖如下圖所示。 效果圖片

    2024年02月09日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包