How to go from outline to image mask using Matplotlib

If I build a 2D array and contour, I can access the segmentation map through cs = plt.contour(...); cs.allsegs cs = plt.contour(...); cs.allsegs , but it is parameterized as a string. I would like segmap to be the logical mask of what interval for the line, so I can, say, quickly summarize everything within this outline.

Thank you very much!

+4
source share
2 answers

I don’t think there is a very simple way, mainly because you want to mix raster and vector data. Fortunately, Matplotlib paths have the ability to check if a point is in the path by doing this for all pixels, creating a mask, but I think this method can be very slow for large datasets.

 import matplotlib.patches as patches from matplotlib.nxutils import points_inside_poly import matplotlib.pyplot as plt import numpy as np # generate some data X, Y = np.meshgrid(np.arange(-3.0, 3.0, 0.025), np.arange(-3.0, 3.0, 0.025)) Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1) # difference of Gaussians Z = 10.0 * (Z2 - Z1) fig, axs = plt.subplots(1,2, figsize=(12,6), subplot_kw={'xticks': [], 'yticks': [], 'frameon': False}) # create a normal contour plot axs[0].set_title('Standard contour plot') im = axs[0].imshow(Z, cmap=plt.cm.Greys_r) cs = axs[0].contour(Z, np.arange(-3, 4, .5), linewidths=2, colors='red', linestyles='solid') # get the path from 1 of the contour lines verts = cs.collections[7].get_paths()[0] # highlight the selected contour with yellow axs[0].add_patch(patches.PathPatch(verts, facecolor='none', ec='yellow', lw=2, zorder=50)) # make a mask from it with the dimensions of Z mask = verts.contains_points(list(np.ndindex(Z.shape))) mask = mask.reshape(Z.shape).T axs[1].set_title('Mask of everything within one contour line') axs[1].imshow(mask, cmap=plt.cm.Greys_r, interpolation='none') # get the sum of everything within the contour # the mask is inverted because everything within the contour should not be masked print np.ma.MaskedArray(Z, mask=~mask).sum() 

Please note that the contour lines, which by default "leave" the graph on different edges, do not make the path following these edges. These lines will require additional processing.

enter image description here

+6
source

Another way, perhaps more intuitive, is the binary_fill_holes function from scipy.ndimage .

 import numpy as np import scipy image = np.zeros((512, 512)) image[contour1[:, 0], contour1[:, 1]] = 1 masked_image = scipy.ndimage.morphology.binary_fill_holes(image) ``` 
+1
source

Source: https://habr.com/ru/post/1484952/


All Articles