Home > Mobile >  Use python opencv to generate irregular masks image without knowing the number of masks
Use python opencv to generate irregular masks image without knowing the number of masks

Time:06-13

I have some images and the corresponding ROI positions, I want to use these data to generate a mask image, I have tried to generate some mask images, but it works fine when there is only one ROI, but when there are more than two ROIs causes mask to connect.

Is there any way to generate a Mask image without knowing how many ROIs there are?

code:

import numpy as np
import cv2
from skimage import morphology

def get_mask(imgshape, roi):
    mask = np.zeros(imgshape, dtype=np.int32)
    mask = cv2.fillConvexPoly(mask, roi, 255)
    mask = morphology.binary_closing(mask)
    return mask

mask_img = get_mask((200,200), roi_pos)

ROI = [[104,  94],[105,  94],[106,  93],[105,  92],[104,  91],
[103,  92],[103,  93],[ 95,  94],[ 96,  94],[ 97,  92],[ 97,  91],
[ 97,  91],[ 95,  91],[ 94,  91],[ 93,  93],[ 94,  94]]

Resluts: enter image description here

CodePudding user response:

Since you have many points in a single array, you will have to cluster them. As mentioned by Rahul, K-means is well suited for this job.

One question remains, how do you know how many ROIs are present? In other words, how many clusters do you divide your points into?

I used the silhouette method detailed well in enter image description here

The cluster with the highest silhouette score must be chosen to give best clustering results. The optimal number of cluster based on the graph above is 2.

# K-Means model with 2 clusters
final_kmeans = KMeans(n_clusters = 2)
final_kmeans.fit(r)
final_kmeans.predict(r)

# points and labels to separate lists
r_list = r.tolist()
labels = final_kmeans.predict(r).tolist()
# number of unique clusters
num_clusters = np.unique(final_kmeans.predict(r)).tolist()

# sample mask for demonstration
mask = np.zeros((300, 250,1), dtype=np.uint8)

# select points by their cluster labels and draw them
for clus in num_clusters:
  points = []
  for i, j in zip(r_list, labels):
    if j == clus:
      points.append(i)
  mask = cv2.fillConvexPoly(mask, np.array(points), 255)

enter image description here

Hope this gives you an idea. You can further optimize it. Remember the maximum number of ROIs that can be possible for your data set. You can try other clustering algorithms and also look out for methods that can get you optimal number of clusters

  • Related