How to convert Playment segmentation mask to a grayscale mask

Many semantic segmentation models expect masks in grayscale format. In other words, each pixel of the PNG mask has a value between 0 and 255 with each integer corresponding to a class. Usually, 0 is reserved for blank pixels with no class.

To convert the Playment format PNG mask to a grayscale mask, you can use the python script given below. It is written in python3 and required the numpy, PIL & imageio libraries.

import numpy as np
import imageio
from PIL import Image


def hex_to_rgb(hex_color):
    h = hex_color.lstrip('#')
    return tuple(int(h[i:i + 2], 16) for i in (0, 2, 4))


if __name__ == '__main__':
    path_to_file = "example.png"

    # read PNG file and drop alpha (4th) channel
    im = imageio.imread(path_to_file)[:, :, 0:3]
    print(im.shape)

    # initiate new file with same dimensions as the Playment PNG.
    # But each pixel will only have one integer value instead of an RGBA array
    new_arr = np.zeros(im.shape[0:2])

    playment_legend = {
          "#1aeeed": "class_1",
          "#eedd3e": "class_2",
          "#deeee7": "class_3",
          "#feec3e": "class_4"
        }

    output_legend = {
        "class_1": 1,
        "class_2": 2,
        "class_3": 3,
        "class_4": 4
    }

    for k, v in playment_legend.items():
        # get rgb value for hex code k
        rgb = hex_to_rgb(k)
        # find all pixels in the image which have the color k
        mask = (im == rgb).all(axis=2)
        # write respective integer value to all such pixels
        new_arr[mask] = output_legend[v]

    # Save new grayscale PNG
    new_im = Image.fromarray(new_arr).convert("L")
    out_path = path_to_file.split('.')[0] + "_grayscale" + ".png"
    new_im.save(out_path, format="png")

Last updated