theta
theta

Reputation: 25631

Slicing numpy array with closed path

import numpy as np
from matplotlib.path import Path

w, h = 300, 200

mask = np.zeros((h, w))

verts = [(0, h), (w/2, 0), (w, h), (0, h)]
codes = [Path.MOVETO, Path.LINETO, Path.LINETO, Path.CLOSEPOLY]

path = Path(verts, codes)

mask[path.contains_points(mask)] = 1

result:

Traceback (most recent call last):
  File "test.py", line 13, in <module>
    mask[path.contains_points(mask)] = 1
  File "C:\Python27\lib\site-packages\matplotlib\path.py", line 488, in contains_points
    result = _path.points_in_path(points, radius, self, transform)
TypeError: Argument 0 to points_in_path must be an Nx2 numpy array

So matplotlib.path.Path.contains_points() does not expand array indexes which would be useful for mask creation.

How to mask numpy array with closed path (with matplotlib or without it if it's possible)

Upvotes: 3

Views: 655

Answers (1)

DrV
DrV

Reputation: 23530

The problem here is that path.contains_points expects to receive an array of coordinates (Nx2 array). Then it returns a vector with N points with True or False for each point.

So, you need to create an array of coordinates (e.g. [[0,0], [0,1], [0,2] ...]) for the area you want to search through. Then you can feed it to contains_points to know which of the points are within the path.

There are several ways of accomplishing this, for example:

coordinates = np.dstack(np.meshgrid(np.arange(w), np.arange(h))).reshape(-1,2)
within = coordinates[path.contains_points(coordinates)]
mask = np.zeros((h,w))
mask[within[:,1], within[:,0]] = 1

Now you should have an array with size h x w and 1's inside the mask.

Btw, the use of matplotlib.path is a nice trick!

Upvotes: 3

Related Questions