Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 高斯滤波器的线性分离与Numpy计算_Python_Numpy_Convolution_Gaussianblur - Fatal编程技术网

Python 高斯滤波器的线性分离与Numpy计算

Python 高斯滤波器的线性分离与Numpy计算,python,numpy,convolution,gaussianblur,Python,Numpy,Convolution,Gaussianblur,我有一个2dnumpy数组包含灰度像素值,从0到255。我想做的是从头创建一个高斯滤波器。我已经编写了一个函数来生成一个标准化的高斯内核: def gaussianKernel(size, sigma): kernel = np.fromfunction(lambda x, y: (1/(2*math.pi*sigma**2)) * math.e ** ((-1*((x-(size-1)/2)**2+(y-(size-1)/2)**2))/(2*sigma**2)), (size, s

我有一个
2d
numpy
数组
包含
灰度
像素值,从
0
255
。我想做的是从头创建一个
高斯滤波器
。我已经编写了一个函数来生成一个
标准化的
高斯
内核

def gaussianKernel(size, sigma):
    kernel =  np.fromfunction(lambda x, y: (1/(2*math.pi*sigma**2)) * math.e ** ((-1*((x-(size-1)/2)**2+(y-(size-1)/2)**2))/(2*sigma**2)), (size, size))
    return kernel / np.sum(kernel)
哪种方法很好:

>>> vision.gaussianKernel(5, 1.5)
array([[ 0.01441882,  0.02808402,  0.0350727 ,  0.02808402,  0.01441882],
       [ 0.02808402,  0.05470021,  0.06831229,  0.05470021,  0.02808402],
       [ 0.0350727 ,  0.06831229,  0.08531173,  0.06831229,  0.0350727 ],
       [ 0.02808402,  0.05470021,  0.06831229,  0.05470021,  0.02808402],
       [ 0.01441882,  0.02808402,  0.0350727 ,  0.02808402,  0.01441882]])
然后我创建了一个基本的
卷积
函数,将这个
内核
应用到每个
像素
,并产生一个
高斯
模糊:

def gaussianBlurOld(img, kSize, kSigma):
    kernel = gaussianKernel(kSize, kSigma)
    d = int((kSize-1)/2)
    gaussian = np.zeros((img.shape[0]-2*d, img.shape[1]-2*d))
    for y in range(d, img.shape[0]-d):
        for x in range(d, img.shape[1]-d):
            gaussian[y-d][x-d] = np.sum(np.multiply(img[y-d:y+d+1, x-d:x+d+1], kernel))
    return gaussian
这很好,模糊了一个图像,然而,由于这段代码最终将运行在一个树莓圆周率,我需要它是有效的,它要快得多。由于昨天我问了一个问题,关于如何加速
Sobel
边缘检测器,我尝试将他给出的相同逻辑应用于
gaussian
滤波器。但是,由于
函数
将为
内核
接受一个
变量
大小参数,因此与
Sobel
内核的设置大小相比,它稍微使事情复杂化,而
内核的设置大小为3x3

如果我正确理解了解释,我需要首先将内核分为
x
y
两个组件,只需使用原始
内核的顶部
行和左侧
列即可(显然它们是相同的,但我决定将它们分开,因为我已经计算了
2d
内核)。下面是分开的矩阵:

从这些
向量中,我需要遍历每个值,并将数组的
'window'
按元素相乘。在每一个值之后,将缩小的窗口沿数组向右移动。为了更清楚地显示我认为需要做的事情,以下是3个不同的
'windows'
I我说的是一个内核大小为3x3的小图像:

          _______3_______
     _____|_2_______    |
_____|_1__|____|    |   |
|    |    |    |    |   |
|123,|213,|124,|114,|175|
|235,|161,|127,|215,|186|
|128,|215,|111,|141,|221|
|224,|171,|193,|127,|117|
|146,|245,|129,|213,|221|
|152,|131,|150,|112,|171|
因此,对于每个
“窗口”
,您将乘以内核中该窗口的
索引
,并将其添加到总数中

然后,取应用了
gaussian
内核的
x
组件的img,并对
y
组件执行相同操作

这些是我认为我可以做的计算
高斯
模糊的步骤,比使用
嵌套
循环
要快得多

def gaussianBlur(img, kSize, kSigma):
    kernel = gaussianKernel(kSize, kSigma)
    gausX = np.zeros((img.shape[0], img.shape[1] - kSize + 1))
    for i, v in enumerate(kernel[0]):
        gausX += v * img[:, i : img.shape[1] - kSize + i + 1]
    gausY = np.zeros((gausX.shape[0] - kSize + 1, gausX.shape[1]))
    for i, v in enumerate(kernel[:,0]):
        gausY += v * gausX[i : img.shape[0]  - kSize + i + 1]
    return gausY
我的问题是,此函数产生正确的“模糊效果”,但输出值都在
0
3
之间,因为
由于某种原因浮动了
。幸运的是,由于其他原因,
matplotlib
仍然可以很好地显示输出,因此我可以检查它是否正确地模糊了图像

问题很简单:为什么像素值在
0
3
之间输出


我已经调试了几个小时,但找不到原因。我很确定某个地方有一些缩放细节,但我就是找不到。任何帮助都将不胜感激!

对于任何感兴趣的人来说,问题在于函数
gaussianKernel
返回了
2d
内核
标准化的
用作
2d
内核
。这意味着,当我通过取顶部
和左侧
将其拆分为
组件时,这些组件没有标准化

为了解决这个问题,我刚刚在
gaussianKernel
函数中添加了一个参数,以选择
2
维度或
1
维度(两个
均已正常化
):


因此,现在我可以使用
gaussianKernel(size,sigma,False)获得
1d
内核
,并将其正常化。这意味着我最终可以获得正确的模糊效果,而无需缩放像素值。

检查数据类型。如果可能,使用扩展数据类型-uint64/int64/float64。@Divakar我尝试将
gausX
更改为初始化为这些
dtypes
,b但是,当设置为
int
dtype
时,它无法与内核相乘,
float64
没有任何变化。我尝试了一个简化的示例,似乎可以工作:
image=np.zeros((30,30))
image[:,15:=10000.0
i2=gaussianblurld(image,9,3.0)
plt.imshow(i2)
-这会使输出图像具有更高的值。@VBB如果我不清楚,很抱歉,函数
GaussianBlurd
工作正常,但在
数组中循环时速度非常慢。函数
gaussianBlur
不会在
数组中循环,因此应该更快,但产生的值太小。。。
def gaussianKernel(size, sigma, twoDimensional=True):
    if twoDimensional:
        kernel = np.fromfunction(lambda x, y: (1/(2*math.pi*sigma**2)) * math.e ** ((-1*((x-(size-1)/2)**2+(y-(size-1)/2)**2))/(2*sigma**2)), (size, size))
    else:
        kernel = np.fromfunction(lambda x: math.e ** ((-1*(x-(size-1)/2)**2) / (2*sigma**2)), (size,))
    return kernel / np.sum(kernel)