文章目录
本文主要进行的是,由实例分割mask到实例级别的语义分割mask的扩增
用实例个体信息进行语义mask扩增:
前言
在之前文章,解决了实例mask->二值mask的处理:
为进行语义分割,咱剔除不确定类别,融入类别信息的生成语义mask,这个颜色是唯一和类别对应。
但是吧,实际用的时候,不该保存成有颜色的形式,毕竟这是个三通道的图,而非灰度mask,不便于后续的数据扩增,将灰度图像目标区域设置成对应的类别“id”值方可。
扩增完毕后,然后通过Image的P模式指定灰度值对应的三色调色板,进行反演类别颜色
【P mode】但是对于Mask而言,每个颜色通常表示一个物体,而物体的种类是有限的,不需要太大的表达空间,因此可以用P模式。P模式需要预定义好多个颜色的模板,_palette= [0, 0, 0, 128, 0, 0, 0, 128,…],因此数据只需要一个通道存储index即可,(index可以从模板中取出对应的颜色),这样表达颜色个数上限是255但是足够了,而且只占用1/3数据存储空间。颜色模板可以从图像中读取出来。
方法
语义分割mask
也可以产生对应的灰度图像,每个类的像素值是不同的,但一张图片中可以有不少个目标,为便于实例级别的类别扩增,将对应的单实例的mask也给保存了。
addMaskClassColor.py
COCO_CATEGORIES = [
{"color": [220, 20, 60], "isthing": 1, "id": 1, "name": "BatFish"},
{"color": [119, 11, 32], "isthing": 1, "id": 2, "name": "ClownFish"},
{"color": [0, 0, 142], "isthing": 1, "id": 3, "name": "Crab"},
{"color": [0, 0, 230], "isthing": 1, "id": 4, "name": "Crocodile"},
{"color": [106, 0, 228], "isthing": 1, "id": 5, "name": "CrocodileFish"},
{"color": [0, 60, 100], "isthing": 1, "id": 6, "name": "Fish"},
{"color": [0, 80, 100], "isthing": 1, "id": 7, "name": "Flounder"},
{"color": [0, 0, 70], "isthing": 1, "id": 8, "name": "FrogFish"},
{"color": [0, 0, 192], "isthing": 1, "id": 9, "name": "GhostPipefish"},
{"color": [250, 170, 30], "isthing": 1, "id": 10, "name": "LeafySeaDragon"},
{"color": [100, 170, 30], "isthing": 1, "id": 11, "name": "Octopus"},
{"color": [250, 141, 255], "isthing": 1, "id": 12, "name": "Pagurian"},
{"color": [220, 220, 0], "isthing": 1, "id": 13, "name": "Pipefish"},
{"color": [175, 116, 175], "isthing": 1, "id": 14, "name": "ScorpionFish"},
{"color": [250, 0, 30], "isthing": 1, "id": 15, "name": "SeaHorse"},
{"color": [165, 42, 42], "isthing": 1, "id": 16, "name": "Shrimp"},
{"color": [255, 77, 255], "isthing": 1, "id": 17, "name": "Slug"},
{"color": [0, 226, 252], "isthing": 1, "id": 18, "name": "StarFish"},
{"color": [182, 182, 255], "isthing": 1, "id": 19, "name": "Stingaree"},
{"color": [0, 82, 0], "isthing": 1, "id": 20, "name": "Turtle"},
{"color": [120, 166, 157], "isthing": 1, "id": 21, "name": "Ant"},
{"color": [110, 76, 0], "isthing": 1, "id": 22, "name": "Bug"},
{"color": [174, 57, 255], "isthing": 1, "id": 23, "name": "Cat"},
{"color": [199, 100, 0], "isthing": 1, "id": 24, "name": "Caterpillar"},
{"color": [72, 0, 118], "isthing": 1, "id": 25, "name": "Centipede"},
{"color": [102, 102, 156], "isthing": 1, "id": 26, "name": "Chameleon"},
{"color": [255, 179, 240], "isthing": 1, "id": 27, "name": "Cheetah"},
{"color": [0, 125, 92], "isthing": 1, "id": 28, "name": "Deer"},
{"color": [116, 112, 0], "isthing": 1, "id": 29, "name": "Dog"},
{"color": [0, 114, 143], "isthing": 1, "id": 30, "name": "Duck"},
{"color": [209, 0, 151], "isthing": 1, "id": 31, "name": "Gecko"},
{"color": [188, 208, 182], "isthing": 1, "id": 32, "name": "Giraffe"},
{"color": [0, 220, 176], "isthing": 1, "id": 33, "name": "Grouse"},
{"color": [255, 99, 164], "isthing": 1, "id": 34, "name": "Human"},
{"color": [92, 0, 73], "isthing": 1, "id": 35, "name": "Kangaroo"},
{"color": [133, 129, 255], "isthing": 1, "id": 36, "name": "Leopard"},
{"color": [78, 180, 255], "isthing": 1, "id": 37, "name": "Lion"},
{"color": [0, 228, 0], "isthing": 1, "id": 38, "name": "Lizard"},
{"color": [174, 255, 243], "isthing": 1, "id": 39, "name": "Monkey"},
{"color": [45, 89, 255], "isthing": 1, "id": 40, "name": "Rabbit"},
{"color": [134, 134, 103], "isthing": 1, "id": 41, "name": "Reccoon"},
{"color": [145, 148, 174], "isthing": 1, "id": 42, "name": "Sciuridae"},
{"color": [255, 208, 186], "isthing": 1, "id": 43, "name": "Sheep"},
{"color": [197, 226, 255], "isthing": 1, "id": 44, "name": "Snake"},
{"color": [152, 161, 64], "isthing": 1, "id": 45, "name": "Spider"},
{"color": [171, 134, 1], "isthing": 1, "id": 46, "name": "StickInsect"},
{"color": [109, 63, 54], "isthing": 1, "id": 47, "name": "Tiger"},
{"color": [207, 138, 255], "isthing": 1, "id": 48, "name": "Wolf"},
{"color": [151, 0, 95], "isthing": 1, "id": 49, "name": "Worm"},
{"color": [9, 80, 61], "isthing": 1, "id": 50, "name": "Bat"},
{"color": [84, 105, 51], "isthing": 1, "id": 51, "name": "Bee"},
{"color": [74, 65, 105], "isthing": 1, "id": 52, "name": "Beetle"},
{"color": [166, 196, 102], "isthing": 1, "id": 53, "name": "Bird"},
{"color": [208, 195, 210], "isthing": 1, "id": 54, "name": "Bittern"},
{"color": [255, 109, 65], "isthing": 1, "id": 55, "name": "Butterfly"},
{"color": [0, 143, 149], "isthing": 1, "id": 56, "name": "Cicada"},
{"color": [179, 0, 194], "isthing": 1, "id": 57, "name": "Dragonfly"},
{"color": [209, 99, 106], "isthing": 1, "id": 58, "name": "Frogmouth"},
{"color": [5, 121, 0], "isthing": 1, "id": 59, "name": "Grasshopper"},
{"color": [227, 255, 205], "isthing": 1, "id": 60, "name": "Heron"},
{"color": [147, 186, 208], "isthing": 1, "id": 61, "name": "Katydid"},
{"color": [153, 69, 1], "isthing": 1, "id": 62, "name": "Mantis"},
{"color": [3, 95, 161], "isthing": 1, "id": 63, "name": "Mockingbird"},
{"color": [163, 255, 0], "isthing": 1, "id": 64, "name": "Moth"},
{"color": [119, 0, 170], "isthing": 1, "id": 65, "name": "Owl"},
{"color": [206, 186, 171], "isthing": 1, "id": 66, "name": "Owlfly"},
{"color": [0, 182, 199], "isthing": 1, "id": 67, "name": "Frog"},
{"color": [152, 251, 152], "isthing": 1, "id": 68, "name": "Toad"},
{"color": [208, 229, 228], "isthing": 1, "id": 69, "name": "Other"},
]
data_dict = {"ids":[],"classes":[],"colors":[],"cnt_list":[],"imgs_list":[]}
for _dict in COCO_CATEGORIES:
data_dict["ids"].append(_dict["id"])
data_dict["colors"].append(_dict["color"])
data_dict["classes"].append(_dict["name"])
data_dict["cnt_list"] = [0 for x in range(len(data_dict["classes"]))]
data_dict["imgs_list"] = [[]for x in range(len(data_dict["classes"]))]
import os
import re
import fnmatch
import cv2
import glob
import numpy as np
import json
def filter_for_jpeg(root, files):
file_types = ['*.jpeg', '*.jpg', '*.png']
file_types = r'|'.join([fnmatch.translate(x) for x in file_types])
files = [os.path.join(root, f) for f in files]
files = [f for f in files if re.match(file_types, f)]
return files
def filter_for_annotations(root, files, image_filename):
file_types = ['*.png']
file_types = r'|'.join([fnmatch.translate(x) for x in file_types])
basename_no_extension = os.path.splitext(os.path.basename(image_filename))[0]
file_name_prefix = basename_no_extension + '_.*' # 用于匹配对应的二值mask
files = [os.path.join(root, f) for f in files]
files = [f for f in files if re.match(file_types, f)]
files = [f for f in files if re.match(file_name_prefix, os.path.splitext(os.path.basename(f))[0])]
return files
part = "train" # train test
ROOT_DIR = 'E:/YFXu/rgb2mask/modify_'+part
IMAGE_DIR = os.path.join(ROOT_DIR, "image")
ANNOTATION_DIR = os.path.join(ROOT_DIR, "annotations")
COLOR_ANNOTATION_DIR = os.path.join(ROOT_DIR, "annotations_color")
L_ANNOTATION_DIR = os.path.join(ROOT_DIR, "annotations_L")
L_SINGLE_ANNOTATION_DIR = os.path.join(ROOT_DIR, "annotations_single_L")
os.makedirs(COLOR_ANNOTATION_DIR, exist_ok=True)
os.makedirs(L_ANNOTATION_DIR, exist_ok=True)
os.makedirs(L_SINGLE_ANNOTATION_DIR, exist_ok=True)
def main():
# filter for jpeg images
for root, _, files in os.walk(IMAGE_DIR):
image_files = filter_for_jpeg(root, files)
# go through each image
for image_file in image_files:
image = cv2.imread(image_file)
h,w = image.shape[:2]
res_mask_sav = os.path.join(COLOR_ANNOTATION_DIR,os.path.basename(image_file).replace(".jpg",".png"))
# if os.path.exists(res_mask_sav):
# continue
# filter for associated png annotations
for root, _, files in os.walk(ANNOTATION_DIR):
res_mask = np.zeros((h,w,3),dtype=np.uint8) # 没有一个annotion 就附上对应颜色加上去
res_mask_L = np.zeros((h,w),dtype=np.uint8)
annotation_files = filter_for_annotations(root, files, image_file)
for annaotation_file in annotation_files:
sub_class = os.path.basename(annaotation_file).split('_')[-2]
index = data_dict["classes"].index(sub_class)
class_id = data_dict["ids"][index]
color = data_dict["colors"][index]
color_pic = np.zeros((h,w,3),dtype=np.uint8)
# cv2读出是BGR 保存的应该也是BGR
color_pic[:,:,0]=color[2]
color_pic[:,:,1]=color[1]
color_pic[:,:,2]=color[0]
l_pic = np.ones((h,w),dtype=np.uint8)*class_id
mask = cv2.imread(annaotation_file,cv2.IMREAD_GRAYSCALE)
color_mask = cv2.add(color_pic,np.zeros((h,w,3),dtype=np.uint8),mask=mask)
res_mask = cv2.add(res_mask,color_mask)
l_mask = cv2.add(l_pic,np.zeros((h,w),dtype=np.uint8),mask=mask)
cv2.imwrite(os.path.join(L_SINGLE_ANNOTATION_DIR,os.path.basename(annaotation_file)),l_mask)
data_dict["cnt_list"][index] +=1
res_mask_L = cv2.add(res_mask_L,l_mask)
data_dict["imgs_list"][index].append(os.path.basename(image_file))
cv2.imwrite(res_mask_sav,res_mask)
cv2.imwrite(os.path.join(L_ANNOTATION_DIR,os.path.basename(image_file).replace(".jpg",".png")),res_mask_L)
save_json_path = os.path.join("./", "%s.json" % "stat_classify_COD10K.json")
json.dump(data_dict, open(save_json_path, 'w'), indent=4)
if __name__ == "__main__":
main()
颜色反演
with open("stat_classify_COD10K.json.json") as f:
data_dict = json.load(f)
palette=[]
for i in range(256):
palette.extend((i,i,i))
palette[:3*70]=np.array([[0,0,0]]+data_dict["colors"], dtype='uint8').flatten()
# palette[:3*70]=np.array([ [0,0,0], # 0灰度值对应黑色背景
# [220, 20, 60],
# [119, 11, 32],
# [0, 0, 142],
# [0, 0, 230],
# [106, 0, 228],
# [0, 60, 100],
# [0, 80, 100],
# [0, 0, 70],
# [0, 0, 192],
# [250, 170, 30],
# [100, 170, 30],
# [250, 141, 255],
# [220, 220, 0],
# [175, 116, 175],
# [250, 0, 30],
# [165, 42, 42],
# [255, 77, 255],
# [0, 226, 252],
# [182, 182, 255],
# [0, 82, 0],
# [120, 166, 157],
# [110, 76, 0],
# [174, 57, 255],
# [199, 100, 0],
# [72, 0, 118],
# [102, 102, 156],
# [255, 179, 240],
# [0, 125, 92],
# [116, 112, 0],
# [0, 114, 143],
# [209, 0, 151],
# [188, 208, 182],
# [0, 220, 176],
# [255, 99, 164],
# [92, 0, 73],
# [133, 129, 255],
# [78, 180, 255],
# [0, 228, 0],
# [174, 255, 243],
# [45, 89, 255],
# [134, 134, 103],
# [145, 148, 174],
# [255, 208, 186],
# [197, 226, 255],
# [152, 161, 64],
# [171, 134, 1],
# [109, 63, 54],
# [207, 138, 255],
# [151, 0, 95],
# [9, 80, 61],
# [84, 105, 51],
# [74, 65, 105],
# [166, 196, 102],
# [208, 195, 210],
# [255, 109, 65],
# [0, 143, 149],
# [179, 0, 194],
# [209, 99, 106],
# [5, 121, 0],
# [227, 255, 205],
# [147, 186, 208],
# [153, 69, 1],
# [3, 95, 161],
# [163, 255, 0],
# [119, 0, 170],
# [206, 186, 171],
# [0, 182, 199],
# [152, 251, 152],
# [208, 229, 228],
# ], dtype='uint8').flatten()
# # im.putpalette(palette)
# # im.save(name)
def save_colored_mask(mask, save_path):
lbl_pil = Image.fromarray(mask.astype(np.uint8), mode="P")
# colormap = imgviz.label_colormap()
# lbl_pil.putpalette(colormap.flatten()) # 可以人为设置调色板
lbl_pil.putpalette(palette)
lbl_pil.save(save_path)