I'm trying to make a mask from contours.
Here's my full df
Here's a glimpse of first 7 rows
>>> df
contour.ID xrT yrT xlT ylT
1057 20 6259.2300 4620.7845 5670.1260 4651.4670
1058 20 6253.0935 4620.7845 5682.3990 4651.4670
1059 20 6253.0935 4633.0575 5694.6720 4657.6035
1060 20 6240.8205 4633.0575 5694.6720 4657.6035
1061 20 6228.5475 4645.3305 5700.8085 4669.8765
1062 20 6228.5475 4645.3305 5700.8085 4669.8765
1063 20 6216.2745 4645.3305 5713.0815 4669.8765
I can draw all contours I care about using a function.
def display_all_contours(img, df, grouping_var):
# display with matplotlib
# Create figure and axes
fig, ax = plt.subplots(1)
# Display the image
ax.imshow(img)
# split by contour
grouped_frame = df.groupby(grouping_var)
li = [grouped_frame.get_group(x) for x in grouped_frame.groups]
# for every contour
for i in range(len(li)):
poly = patches.Polygon(np.array([li[i].xrT, li[i].yrT]).T,
fill=False)
ax.add_patch(poly)
for i in range(len(li)):
poly = patches.Polygon(np.array([li[i].xlT, li[i].ylT]).T,
fill=False, color="white")
ax.add_patch(poly)
return("Displaying " + str(len(np.unique(df[grouping_var]))) + " contours.")
This is the result of drawing the contorus on something that has the shape of my image.
mask = np.zeros((9373, 12273), dtype=np.uint8)
display_all_contours(mask, df, "contour.ID")
Now, I want to create a mask of all the polygons (in this case the left side). So I create a mask and burn into it each polygon using cv2.fillConvexPoly
mask = np.zeros((9373, 12273), dtype=np.uint8)
display_all_contours(mask, df, "contour.ID")
for poly in np.unique(df["contour.ID"]):
# subset
sub_df = df[df["contour.ID"] == poly]
# burn into the mask
# explicitly burn into the mask
mask = cv2.fillConvexPoly(mask, np.array(sub_df[["xlT", "ylT"]], 'int32'), 1)
For some reason I don't understand, this does not produce the result I intended.
plt.imshow(mask)
Solved it, the function I was actually looking for is fillPoly
Replacing this line solves the problem
# mind the np.array(..., "int32") is wrapped in [] because that's how fillPoly likes it
mask = cv2.fillPoly(mask, [np.array(sub_df[["xlT", "ylT"]], 'int32')], 1)