Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to generate a matrix with circle of ones in numpy/scipy

There are some signal generation helper functions in python's scipy, but these are only for 1 dimensional signal.

I want to generate a 2-D ideal bandpass filter, which is a matrix of all zeros, with a circle of ones to remove some periodic noise from my image.

I am now doing with:

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

result:

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.]])

Is there a more direct way to generate a matrix of circle of ones, all else zeros?

Edit: Python 2.7.12

like image 590
user2829759 Avatar asked Dec 10 '22 15:12

user2829759


1 Answers

Here's a vectorized approach -

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)

Runtime test -

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
like image 121
Divakar Avatar answered Jan 22 '23 16:01

Divakar