二维高斯核函数(python)

今天突然想要去试一试opencv里面的高斯模糊怎么实现,虽然以前已经写过很多次关于高斯核的函数了,但是有个好奇点,那就是一般不填sigma这个参数的时候,opencv是怎么计算的。

关于具体的高斯函数的讲解,已经有人写的很详细了,我就不赘述了,所以给大家个链接有兴趣的可以去看看。

http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html

我这里想做的实验是到底opencv中的高斯模糊函数GaussianBlur使用的高斯核是什么。

但是直接获取这个二维的高斯核貌似是不可行的,opencv提供了一维高斯核获取的函数。

具体参考以下页面

https://docs.opencv.org/2.4.13.2/modules/imgproc/doc/filtering.html#void sepFilter2D(InputArray src, OutputArray dst, int ddepth, InputArray kernelX, InputArray kernelY, Point anchor, double delta, int borderType)

那么此处问题就出来了,如何通过一维高斯核生成二维高斯核。

先获取两个一维高斯核,而后对后一个高斯核进行转置,而后第一个高斯核核第二个高斯核通过矩阵相乘就可以得到一个二维高斯核了。

下面是测试代码

def gaussian_kernel_2d_opencv(kernel_size = 3,sigma = 0):
    kx = cv2.getGaussianKernel(kernel_size,sigma)
    ky = cv2.getGaussianKernel(kernel_size,sigma)
    return np.multiply(kx,np.transpose(ky)) 

然后我需要的是自己写一个二维高斯核函数,此处写法有很多版本,但是我是参考了刚才上面给出的参考链接中的计算方式,同时参考了opencv的源码。

两个地方不一样,一个是opencv当中在计算高斯模版的时候并没有在最后计算除以pi2(sigma**2),而是将每次计算后的数值加起来,最后用1/总和,然后输出的时候将刚才计算的数值乘上本身的像素值。

本来此处写一下公式会比较好理解,但是这里稍微偷懒一下就不给出具体的公式了,大家自行看我下面的代码就OK了。

#kernel_size set (n,n) default
def gaussian_2d_kernel(kernel_size = 3,sigma = 0):
    
    kernel = np.zeros([kernel_size,kernel_size])
    center = kernel_size//2
    
    if sigma == 0:
        sigma = ((kernel_size-1)*0.5 - 1)*0.3 + 0.8
    
    s = 2*(sigma**2)
    sum_val = 0
    for i in range(0,kernel_size):
        for j in range(0,kernel_size):
            x = i-center
            y = j-center
            kernel[i,j] = np.exp(-(x**2+y**2) / s)
            sum_val += kernel[i,j]
            #/(np.pi * s)
    sum_val = 1/sum_val
    return kernel*sum_val

这个计算结果和通过opencv获取一维高斯核通过计算转换为二维高斯核的结果完全一致。此处实验成功。

但是!!通过这个高斯核和图像进行卷积操作的结果和直接通过opencv调用GaussianBlur计算的结果是有所不同的。虽然单纯从数值上来讲,基本都只是差1的大小,但是这说明此函数并不是直接和这个卷积核进行卷积的,而是还做了一点修改。那么具体是什么,我暂时没画时间去查源码,如有了解者希望能够告知我,感激不尽。

最后一个小注意点,上面忘记书写了,卷积核大小在小于等于7的情况下结果是和我自己写的那个函数计算不完全一致的。原因在于opencv源码当中小于等于7的高斯核并不是通过计算给出而是直接给出了结果,所以在小数上有一定差距,估计是效率问题才这么做的。

20190115 修正(源自评论“临京雪月”)

opencv源码当中小于等于7的高斯核并不是通过计算给出而是直接给出了结果。这句话不对,当小于等于7且sigma<=0时候才会使用内置的模板,其余情况同样是计算出来的结果

### 二维高斯核函数概述 在机器学习领域,尤其是支持向量机(SVM)中,高斯核函数是一种常用的非线性映射工具。它能够将输入数据从低维空间映射到高维甚至无限维的空间,从而解决复杂的分类问题[^1]。 #### 二维高斯核函数的定义 二维高斯核函数可以看作是对两个样本点 \( \mathbf{x}_i = (x_{i1}, x_{i2})^\top \) 和 \( \mathbf{x}_j = (x_{j1}, x_{j2})^\top \) 的相似度测量。其核心公式如下: \[ K(\mathbf{x}_i, \mathbf{x}_j) = \exp\left(-\frac{\|\mathbf{x}_i - \mathbf{x}_j\|^2}{2\sigma^2}\right) \] 其中: - \( K(\mathbf{x}_i, \mathbf{x}_j) \) 表示样本点之间的相似度; - \( \|\mathbf{x}_i - \mathbf{x}_j\| \) 是欧几里得距离; - 参数 \( \sigma \) 控制着高斯分布的标准差,决定了核函数的作用范围和影响程度[^2]。 当应用于图像处理时,\( \mathbf{x} \) 可能表示像素位置或特征向量,而该公式的计算则用于衡量不同区域间的相似性。 --- #### Python 实现代码 以下是基于上述公式的二维高斯核函数的具体实现方式: ```python import numpy as np def gaussian_kernel_2d(x_i, x_j, sigma=1.0): """ 计算二维高斯核函数值 :param x_i: 输入的第一个样本点 (numpy array 或 list),形状为 (2,) :param x_j: 输入的第二个样本点 (numpy array 或 list),形状为 (2,) :param sigma: 高斯核函数中的标准差参数,默认为 1.0 :return: 返回对应的高斯核函数值 """ distance_squared = np.sum((np.array(x_i) - np.array(x_j)) ** 2) kernel_value = np.exp(-distance_squared / (2 * sigma ** 2)) return kernel_value # 测试样例 if __name__ == "__main__": point_a = [1, 2] point_b = [3, 4] result = gaussian_kernel_2d(point_a, point_b, sigma=1.0) print(f"Gaussian Kernel Value between {point_a} and {point_b}: {result}") ``` 此代码片段实现了任意两点间二维高斯核函数的计算过程,并允许调整超参 \( \sigma \)。 --- #### 应用场景分析 1. **机器学习中的 SVM** 在 SVM 中,高斯核函数被用来构建非线性的决策边界。通过调节 \( \sigma \),可以使模型更加灵活地适应训练集特性。 2. **图像处理中的平滑滤波器** 当把二维高斯核作为卷积操作的核心部分时,它可以有效去除噪声并保留重要细节信息。 ---
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值