This tutorial will show you how to create masks from Shapely polygons. Specifically, a Shapely polygon has a WKT format and we will convert this WKT format into a mask. OK, concretely, suppose we have installed Shapely library, Anaconda, and had an image like the one on left side of images below. In this tutorial, we will convert this image into a mask image like the one on the right side.
The image on right side is called a mask image. It contains only binary pixels (black and white). Particularly, this mask contains black pixels as buildings and white pixels otherwise.
Let’s get started with the code! We are going to show all these codes as codes in Jupyter notebook cells.
Firstly, we import the libraries
%reload_ext autoreload %autoreload 2 %matplotlib inline from skimage.draw import line, polygon, circle, ellipse import matplotlib.pyplot as plt from pathlib import Path from PIL import Image import numpy as np import skimage.io # To read files in a directory from os import listdir from os.path import isfile, join # To load wkt; this is a specific method in shapely library from shapely.wkt import loads
Next, we construct paths to the images, the binary labels where the masks will be saved, and the labels where the json files are saved.
# We construct the path to the image images_path = Path('/home/hbunyamin/Datasets/asses-building-damage/train/images') # We construct the path to label path where we want to put the mask image label_path = Path('/home/hbunyamin/Datasets/asses-building-damage/train/binaryLabels') # We construct the path to the json file; the json file contains coordinates of polygons json_path = Path('/home/hbunyamin/Datasets/asses-building-damage/train/labels')
Then, we put all the image files in a list.
list_files = [f for f in listdir(images_path) if isfile(join(images_path, f))]
Finally, we process all the images and convert them into mask images.
counter = 0 for img_name in list_files: # split the file name prefix_file_name = img_name.split(".") # construct the path to the image temp_image_path = images_path / img_name # construct the path to the json temp_json_path = json_path / (prefix_file_name+".json") # read the json json_dict = None with open(temp_json_path, 'r') as read_file: json_dict = json.load(read_file) # construct the list of xy of buildings props_xy_list = json_dict['features']['xy'] # construct list of polygons polygon_geom_list =  for prop in props_xy_list: polygon_temp = loads(prop['wkt']) polygon_geom_list.append(polygon_temp) # read the image which we want to draw the polygons the_image = skimage.io.imread( temp_image_path ) # Create the basic mask a_mask = np.ones(shape=the_image.shape[0:2], dtype="bool") # original # For each polygon, draw the polygon inside the mask for polygon_geom in polygon_geom_list: poly_coordinates = np.array(list(polygon_geom.exterior.coords)) rr, cc = polygon(poly_coordinates[:,0], poly_coordinates[:,1], the_image.shape) a_mask[cc,rr] = False # Convert numpy array of the mask into an image with the help of PIL mask_image = Image.fromarray(a_mask) # Save the image of the mask into the "binaryLabels" folder mask_image.save( label_path / (prefix_file_name+"_mask.png"), format="PNG" ) # For debugging purposes if counter % 1000 == 0: print("Number of images have been processed:", counter) counter += 1
For conclusion, all the mask images are saved in