自建数据集系列:实例分割mask->语义分割mask->扩增mask


本文主要进行的是,由实例分割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)

🔰 汇总 🔰

1.从labelImg格式->txt格式(YOLO格式、ICDAR2015格式)

2.从二值mask->labelme格式->coco格式

3.从labelme格式->VOC格式+从二值mask->VOC格式

4.从RGB->二值mask->coco格式

🔷5.实例分割mask->语义分割mask->扩增mask

6.COCO格式->YOLO格式

双模图片数据与对应标注文件的命名对齐

xml标注文件的节点、属性、文本的修正

cocoJson数据集统计分析

  • 1
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
Labelme标注输出的mask默认是黑白的,即只有两种颜色,分别代表目标区域和背景区域。但是,如果我们看到的mask是彩色的,那是因为它用调色板的形式去存储的,针对255个像素,每个像素都对应了一个颜色。这样做的目的是为了方便可视化和观察标注结果。所以,虽然mask在存储时是彩色的,但实际上它仍然是基于黑白的二值图像。在使用Labelme进行标注后,会生成一个json文件,其中包含了标注的信息和对应的mask图像。在物体分割任务中,我们可以读取这个json文件,提取出对应的mask图像,并将其转化为二值图像。然后,可以将这些图像转化为tensor,以便在模型中进行训练。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Labelme标注的数据集转为VOC2007](https://download.csdn.net/download/hhhhhhhhhhwwwwwwwwww/12372055)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [为什么数据集中的mask是彩色的?](https://blog.csdn.net/candice5566/article/details/127984846)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [labelme标注的json文件变成每个类别一张黑白mask图](https://blog.csdn.net/m0_48095841/article/details/128397443)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

星空•物语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值