How to draw a Polygon Patch from a bitmask

Viewed 83

In matplotlib I show an image using matplotlib.pyplot.imshow. I also know how to draw a filled Polygon. One of the required arguments is xy a numpy array of shape (N, 2) where each of the N rows represents the x-y co-ordinates of a polygon point.

Now, a filled polygon rendered onto an image can also be represented by a bitmask (with the same height and width as the image), with 1s for fill, and 0s otherwise.

My question is, if I have a bitmask rather than polygon points, is there a way to draw a filled Polygon in matplotlib directly from that? And I mean in the general case where the bitmask may have more than one contiguous blob, or it may have holes:

enter image description here

It doesn't have to be a Polygon, but it should still be an Artist of some sort.

Note: There is this similar question Create matplotlib polygon patch using image mask but it has not been satisfactorily answered. Finding contours is an idea, but I want to know if there is something more direct in matplotlib.

1 Answers

You can overlay the bitmask as a another AxesImage over your image by converting the bitmask into an RGBA image (overlay in the example):

import matplotlib.pyplot as plt
from matplotlib.cbook import get_sample_data
import numpy as np

with get_sample_data("grace_hopper.jpg") as file:
    img = plt.imread(file)

fig, (ax1, ax2) = plt.subplots(ncols=2)

bitmask = np.zeros(img.shape[:2], dtype=np.uint8)
bitmask[500:580, 100:400] = 1
ax1.imshow(bitmask, cmap='gray')
ax1.set_title('Bitmask')

# 50 % opaque overlay
overlay = np.dstack((np.full(bitmask.shape + (3,), [255, 255, 0], dtype=np.uint8),
                     bitmask * 128))
ax2.imshow(img)
ax2.imshow(overlay)
ax2.set_title('Overlayed Bitmask')

enter image description here

Related