Polygon corners from a numpy array or arrays

Viewed 295

I have a numpy arary of numpy arrays of (x,y) points that make up a filled polygon.

[[ 441  455]
 [ 442  455]
 [ 443  455]
 ...
 [1737 1444]
 [1738 1444]
 [1739 1444]]

I need to find the corners of this polygon. How would one go about this?


Context: I'm using detectron2 for instance segmentation, and I received back a tensr of prediction masks, showing whether each pixel is representing the object or not. After some manipulation with numpy, I transformed this into a numpy array of numpy arrays representing all coordinates that are representing the polygon.

outputs = predictor(im)
outputnump = outputs["instances"].pred_masks.numpy()
ind1 = np.nonzero(outputnump[0])
ind = np.insert(ind1[0],np.arange(len(ind1[0])),ind1[1])
#ind = np.flip(ind,[1])
ind_len_div2 = int(len(ind)/2)
ind = ind.reshape(ind_len_div2,2)
2 Answers

You should keep the mask array and use the Marching Cube algorithm to describe the polygon, after that you may use an algorithm that simplifies the polygon.

from skimage.measure import find_contours, approximate_polygon

# mask should be your output mask
contours = find_contours(mask)
simple_contours = [approximate_polygon(p, tolerance=2) for p in contours]

Although the answer given by Gabriel works fine & tandy, I've decided to opt for another route, given that I feel much more comfortable with opencv than skimage.

  def random_colour_masks(image):
        colours = [[0, 255, 0], [0, 0, 255], [255, 0, 0], [0, 255, 255], [255, 255, 0], [255, 0, 255],
                           [80, 70, 180], [250, 80, 190], [245, 145, 50], [70, 150, 250], [50, 190, 190]]
        r = np.zeros_like(image).astype(np.uint8)
        g = np.zeros_like(image).astype(np.uint8)
        b = np.zeros_like(image).astype(np.uint8)
        image == 1], g[image == 1], b[image == 1] = colours[random.randrange(0, 10)]
        coloured_mask = np.stack([r, g, b], axis=2)
        return coloured_mask




masks = outputs['instances'].pred_masks.numpy()#[::-1, :]                       
rgb_mask = random_colour_masks(masks[0]) 
gray_mask = cv.cvtColor(rgb_mask, cv.COLOR_RGB2GRAY)                                         
# Find contours:                         

contours, hierarchy = cv.findContours(gray_mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_NONE) 
polycorners = cv.approxPolyDP(contours[0], 0.00065 * cv.arcLength(contours[0], False), False)
Related