Mask circular sector in a numpy array

I have code that slices a numpy array into a circle. I want to restore only the values โ€‹โ€‹included in a certain range of angles from the circle and mask the array. For example: mask the original array with (x, y) positions between 0 and 45 degrees of a circle.

Is there a pythonic way for this?

Here is my (simplified) source code:

import numpy as np matrix = np.zeros((500,500)) x = 240 y = 280 radius = 10 mask=np.ogrid[x-radius:x+radius+1,y-radius:y+radius+1] matrix[mask] 

Thanks in advance

Edit: I missed that the radius could change.

+8
python numpy matrix angle
source share
2 answers

I would do this by converting from Cartesian coordinates to polar and building Boolean masks for the circle and for the range of angles you want:

 import numpy as np def sector_mask(shape,centre,radius,angle_range): """ Return a boolean mask for a circular sector. The start/stop angles in `angle_range` should be given in clockwise order. """ x,y = np.ogrid[:shape[0],:shape[1]] cx,cy = centre tmin,tmax = np.deg2rad(angle_range) # ensure stop angle > start angle if tmax < tmin: tmax += 2*np.pi # convert cartesian --> polar coordinates r2 = (x-cx)*(x-cx) + (y-cy)*(y-cy) theta = np.arctan2(x-cx,y-cy) - tmin # wrap angles between 0 and 2*pi theta %= (2*np.pi) # circular mask circmask = r2 <= radius*radius # angular mask anglemask = theta <= (tmax-tmin) return circmask*anglemask 

For example:

 from matplotlib import pyplot as pp from scipy.misc import lena matrix = lena() mask = sector_mask(matrix.shape,(200,100),300,(0,50)) matrix[~mask] = 0 pp.imshow(matrix) pp.show() 

enter image description here

+17
source share

Same approach for centered circles in square matrices:

 def circleMask(mat, r=0): if mat.shape[0] != mat.shape[1]: raise TypeError('Matrix has to be square') if not isinstance(r, int): raise TypeError('Radius has to be of type int') s = mat.shape[0] d = num.abs(num.arange(-s/2 + s%2, s/2 + s%2)) dm = num.sqrt(d[:, num.newaxis]**2 + d[num.newaxis, :]**2) return num.logical_and(dm >= r-.5, dm < r+.5) 

looping over this implicit function is expensive!

0
source share

All Articles