【问题标题】:How to generate a matrix with circle of ones in numpy/scipy如何在 numpy/scipy 中生成一个带有一圈的矩阵
【发布时间】:2016-12-28 16:14:30
【问题描述】:

python's scipy 中有一些信号生成辅助函数,但这些仅适用于一维信号。

我想生成一个二维理想带通滤波器,它是一个全零矩阵,带有一圈一以从我的图像中去除一些周期性噪声。

我现在正在处理:

def unit_circle(r):
    def distance(x1, y1, x2, y2):
        return math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
    d = 2*r + 1
    mat = np.zeros((d, d))
    rx , ry = d/2, d/2
    for row in range(d):
        for col in range(d):
            dist = distance(rx, ry, row, col)
            if abs(dist - r) < 0.5:
                mat[row, col] = 1
    return mat

结果:

In [18]: unit_circle(6)
Out[18]:
array([[ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.,  1.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  1.,  1.,  0.,  0.,  0.,  0.,  0.,  1.,  1.,  0.,  0.],
       [ 0.,  1.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  1.,  0.],
       [ 0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  0.],
       [ 1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.],
       [ 1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.],
       [ 1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.],
       [ 1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.],
       [ 1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.],
       [ 0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  0.],
       [ 0.,  1.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  1.,  0.],
       [ 0.,  0.,  1.,  1.,  0.,  0.,  0.,  0.,  0.,  1.,  1.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.,  1.,  0.,  0.,  0.,  0.]])

有没有更直接的方法来生成matrix of circle of ones, all else zeros

编辑: Python 2.7.12

【问题讨论】:

  • 当前输出是你想要的输出吗?
  • @OhadEytan 是的,但感觉有点复杂,希望看到其他解决方案。事实上,我很想知道是否有像 scipy 提供的 1-D 信号那样生成二维信号的框架。
  • 您应该始终指定您的 python 版本,因为除法运算符在 Py2 和 Py3 中的工作方式不同,除非您在 Py2 中从 __future__ 导入新的运算符。

标签: python numpy scipy signal-processing python-2.x


【解决方案1】:

这是一种矢量化方法 -

def unit_circle_vectorized(r):
    A = np.arange(-r,r+1)**2
    dists = np.sqrt(A[:,None] + A)
    return (np.abs(dists-r)<0.5).astype(int)

运行时测试-

In [165]: %timeit unit_circle(100) # Original soln
10 loops, best of 3: 31.1 ms per loop

In [166]: %timeit my_unit_circle(100) #@Eli Korvigo's soln
100 loops, best of 3: 2.68 ms per loop

In [167]: %timeit unit_circle_vectorized(100)
1000 loops, best of 3: 582 µs per loop

【讨论】:

  • 很奇怪,你的解决方案在我的机器上只快了 150 微秒(~350 微秒 vs ~500 微秒)。你能提供你机器的规格吗?
  • @EliKorvigo 我有一台旧机器:Intel(R) Core(TM)2 Duo CPU T6600 @ 2.20GHz,4GB RAM。不过,我认为这些数字不应该那么接近。
  • @EliKorvigo 好的,所以我在 ideone 上运行它,当我在 1002001000 作为输入运行它时,矢量化版本似乎在你的方法的 2/3rd 上运行.我猜这可能是可信的。这是 ideone 运行:ideone.com/8qFAnH 这与您的时间安排一致。
  • 用单次迭代测试不是一件好事,所以我用timeit ideone.com/MpGi6c 重新运行。您的解决方案确实快了 30%
  • 我想知道,是什么让它在你的机器上运行速度慢了近 5 倍。
【解决方案2】:

这是一个纯 NumPy 替代方案,它应该运行得更快,看起来更干净,恕我直言。基本上,我们通过将内置的 sqrtabs 替换为它们的 NumPy 替代品并处理索引矩阵来对您的代码进行矢量化。

更新以将 distance 替换为 np.hypot(由 James K 提供)

In [5]: import numpy as np

In [6]: def my_unit_circle(r):
   ...:     d = 2*r + 1
   ...:     rx, ry = d/2, d/2
   ...:     x, y = np.indices((d, d))
   ...:     return (np.abs(np.hypot(rx - x, ry - y)-r) < 0.5).astype(int)
   ...: 

In [7]: my_unit_circle(6)
Out[7]: 
array([[ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.,  1.,  0.,  0.,  0.,  0.],
       [ 0.,  0.,  1.,  1.,  0.,  0.,  0.,  0.,  0.,  1.,  1.,  0.,  0.],
       [ 0.,  1.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  1.,  0.],
       [ 0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  0.],
       [ 1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.],
       [ 1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.],
       [ 1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.],
       [ 1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.],
       [ 1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.],
       [ 0.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  0.],
       [ 0.,  1.,  1.,  0.,  0.,  0.,  0.,  0.,  0.,  0.,  1.,  1.,  0.],
       [ 0.,  0.,  1.,  1.,  0.,  0.,  0.,  0.,  0.,  1.,  1.,  0.,  0.],
       [ 0.,  0.,  0.,  0.,  1.,  1.,  1.,  1.,  1.,  0.,  0.,  0.,  0.]])

基准测试

In [12]: %timeit unit_circle(100)
100 loops, best of 3: 17.7 ms per loop

In [13]: %timeit my_unit_circle(100)
1000 loops, best of 3: 480 µs per loop

【讨论】:

猜你喜欢
  • 2018-10-10
  • 1970-01-01
  • 1970-01-01
  • 2013-02-20
  • 2016-11-24
  • 2019-02-27
  • 2012-11-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多