Search code examples
pythonnumpymatrixangle

Mask a circular sector in a numpy array


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

Is there a pythonic way for doing so?

Here's my (simplified) original 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 omitted that radius can vary.


Solution

  • I would do this by converting from cartesian to polar coordinates and constructing 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