Search code examples
python-3.ximage-processingpolygondrawscikit-image

How can I draw a polygon in the right shape from a mask?


  • I have a mask with different labelled areas as seen in the attached image.
  • After doing segmentation with active contour function, I want to draw a polygon around the resultant points of the active contour points, but the polygon reads the points row by row, so the polygon drawing is not correct as seen in the attached figure, the polygon should look like more like a circular area.
  • How can I solve it please?

  • image

  • image
  • mask
  • Label
  • polygon
  • polygon
import numpy as np
from skimage.io import imread, imsave
import skimage.filters as filters
from skimage.segmentation import active_contour
from scipy.sparse import csr_matrix
import matplotlib.pyplot as plt
from skimage.draw import polygon
#---------------------------------
img  = imread('image.jpg')
mask = imread('label.png')

def activeContour(img, mask, alpha=0.015, beta=10, gamma=0.001, iterations=500, max_step=0.5):
    lb_list = np.unique(mask)
    Result = np.zeros_like(img)
    for lb in lb_list:
        if(lb != 0):
            s = np.where(mask == lb)
            r = s[0].astype(np.uint8)
            c = s[1].astype(np.uint8)
            init = np.array([r, c]).T
            #-------PreProcessing----------------------------
            img2 = filters.gaussian(img, 3)
            #------- Active Contour  ------------------------
            snake = active_contour(img2, init, alpha=alpha, beta=beta, gamma=gamma, coordinates='rc',
             max_px_move=max_step, max_iterations=iterations)
            #------------------------------------------------
            vals = lb*np.ones_like(snake[:, 0],dtype=np.uint8)
            label = csr_matrix((vals, (snake[:, 1].astype(np.uint8), snake[:, 0].astype(np.uint8))), shape=(img.shape[0], img.shape[1])).toarray()
            Result = Result + label
    return Result


res = activeContour(img, mask, alpha=0, beta= 10, gamma= 0.0000001)
labels = np.unique(res)
ctr = 25
for label in labels:
    if label != 0:
        img = np.zeros_like(img)
        s = np.where(res == label)
        r = s[0].astype(np.uint8)
        c = s[1].astype(np.uint8)
        rr, cc = polygon(r, c)
        img[rr, cc] = 2*ctr
        plt.imshow(img, cmap='gray')
        plt.title('%d'%label)
        plt.axis('off')
        plt.show()
        ctr+=1


Solution

  • Thanks for Juan for his help, the theoritical part of this answer is here and the implementation is down.

    import numpy as np
    
    def sortVertices(array):
        s = np.where(array != 0)
        yr = s[0].astype(np.uint8)
        xc = s[1].astype(np.uint8)
        center_xc = np.sum(xc)/xc.shape 
        center_yr = np.sum(yr)/yr.shape 
        theta = np.arctan2(yr-center_yr, xc-center_xc) * 180 / np.pi
        indices = np.argsort(theta)
        x = xc[indices]
        y = yr[indices]
        return x, y