Search code examples
pythonnumpymatplotlibobject-detectionimage-segmentation

Numpy where generating x,y coordinates that cause segmentation mask to be diagonally split


Below is an image:

Original image

This is a segmentation mask of a class within this image:

Segmentation mask within image

Notice that the segmentation mask above is "porous". My goal is to produce a completely filled segmentation mask within its bounding box, using Numpy. Unfortunately, my current attempts at doing this result in segmentation mask that is striped, has a gradient, is transparent, and is split across the diagonal of the bounding box (image below). I have no idea why this is happening.

Current (incorrect) result :

https://github.com/ebolotin6/ebolotin6.github.io/blob/master/images/image3.png

Code (see compare 1 and 2):

# define row in pandas df
row = annotations_df.iloc[2]

# image width, height
img_w = annotations_df.iloc[0].width
img_h = annotations_df.iloc[0].height

# bounding box matrix 
bbox = np.zeros((img_h, img_w))

### compare 1 ---> this is the original mask
x_coords, y_coords = ast.literal_eval(row.x_coords), ast.literal_eval(row.y_coords)

### compare 2 ---> this should produce a filled mask (and does not work as expected)
bbox[min(y_coords):max(y_coords)+1,min(x_coords):max(x_coords)+1] = 1
y_coords, x_coords = np.where(bbox == 1)

# set fig, axes, style
fig = plt.figure()
ax = fig.add_axes([0,0,1,1])

# read image, plot image
img = plt.imread(first_row.path.values[0])
plt.imshow(img)

# convert coordinates to form of (x,y)
pts = np.array(list(zip(x_coords, y_coords)))

# get min/max of coordinates
xmin = min(x_coords)
xmax = max(x_coords)
ymin = min(y_coords)
ymax = max(y_coords)
width = xmax - xmin
height = ymax - ymin

# plot bounding box
rect = patches.Rectangle((xmin,ymin), width, height, edgecolor = 'c', facecolor = 'none')
ax.add_patch(rect)

# plot mask
poly = patches.Polygon(pts)
ax.add_patch(poly)

The correct output is a completely filled bounding box.


Solution

  • You do not have an issue. It works fine:

    poly = patches.Polygon(pts)

    A lovely, yet quite complex polygon... You expect it to plot the border, yet you pass all the coordinates of all the points in the region. You may want to try:

    poly = patches.Polygon([[xmin,ymin],[xmin,ymax],[xmax,ymax],[xmax,ymin]])

    ps: I assume you are using matplotlib Polygon