python sobel滤波_python - 如何提高sobel边缘检测器的效率 - 堆栈内存溢出

即使您正在构建自己的库,您也绝对应该使用库进行卷积,它们将在后端用C或Fortran进行结果运算,这将大大加快速度。

但是,如果您愿意,可以自己做,使用线性可分离滤波器。 这是想法:

图片:

1 2 3 4 5

2 3 4 5 1

3 4 5 1 2

Sobel x内核:

-1 0 1

-2 0 2

-1 0 1

结果:

8, 3, -7

在卷积的第一个位置,您将计算9个值。 首先,为什么? 您永远不会添加中间列,不必费心将其相乘。 但这不是线性可分离滤波器的重点。 这个想法很简单。 将内核放在第一个位置时,会将第三列乘以[1, 2, 1] 。 但是随后的两个步骤,您将第三列乘以[-1, -2, -1] 。 真是浪费! 您已经计算过了,现在只需要取反即可。 这就是线性可分离滤波器的想法。 请注意,您可以将过滤器分解为两个向量的矩阵外积:

[1]

[2] * [-1, 0, 1]

[1]

将外部乘积在这里得到相同的矩阵。 因此,这里的想法是将操作分为两部分。 首先将整个图像乘以行向量,然后乘以列向量。 以行向量

-1 0 1

在整个图像上,我们最终得到

2 2 2

2 2 -3

2 -3 -3

然后将列向量传递给乘法和求和,我们再次得到

8, 3, -7

另一种可能有用或无效的妙招(取决于您在内存和效率之间的权衡):

请注意,在单行乘法中,您忽略中间值,而只从左边的值中减去右边的值。 这意味着您正在有效地执行以下操作减去这两个图像:

3 4 5 1 2 3

4 5 1 - 2 3 4

5 1 2 3 4 5

如果将图像的前两列剪掉,则会得到左矩阵,如果将后两列剪掉,则会得到右矩阵。 因此,您只需将卷积的第一部分计算为

result_h = img[:,2:] - img[:,:-2]

然后,您可以遍历sobel运算符的其余列。 或者,您甚至可以继续进行,然后做我们刚才做的相同的事情。 这次是垂直情况,您只需要添加第一行和第三行,第二行加倍即可; 或者,使用numpy加法:

result_v = result_h[:-2] + result_h[2:] + 2*result_h[1:-1]

大功告成! 我可能会在不久的将来在此处添加一些时间。 对于包络的某些计算(例如,在1000x1000图像上草草的Jupyter笔记本计时):

新方法(图像总和):每个循环8.18 ms±399 µs(平均±标准偏差,共运行7次,每个循环100个)

旧方法(双循环):每个循环7.32 s±207毫秒(平均±标准偏差,共运行7次,每个循环1次)

是的,您没看错:1000倍加速。

这是比较两者的一些代码:

import numpy as np

def sobel_x_orig(img):

xKernel = np.array([[-1,0,1],[-2,0,2],[-1,0,1]])

sobelled = np.zeros((img.shape[0]-2, img.shape[1]-2))

for y in range(1, img.shape[0]-1):

for x in range(1, img.shape[1]-1):

sobelled[y-1, x-1] = np.sum(np.multiply(img[y-1:y+2, x-1:x+2], xKernel))

return sobelled

def sobel_x_new(img):

result_h = img[:,2:] - img[:,:-2]

result_v = result_h[:-2] + result_h[2:] + 2*result_h[1:-1]

return result_v

img = np.random.rand(1000, 1000)

sobel_new = sobel_x_new(img)

sobel_orig = sobel_x_orig(img)

assert (np.abs(sobel_new-sobel_orig) < 1e-12).all()

当然, 1e-12容忍度很严格,但这是1e-12每个元素的,因此应该可以。 但是我还有一个float图像,对于uint8图像,您当然会有更大的差异。

请注意,您可以对任何线性可分离滤波器执行此操作! 包括高斯滤波器。 还要注意,通常,这需要很多操作。 在C或Fortran或任何其他语言中,通常仅将其实现为单行/列向量的两个卷积,因为最后,它实际上仍然需要遍历每个矩阵的每个元素; 不管您是将它们相加还是相乘,因此在C中用这种方法添加图像值并不比卷积要快。 但是遍历numpy数组非常慢,因此在Python中这种方法要快得多。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值