• Pytorch_Coco数据集转换_pre_transform_format


    数据集处理-数据集转换格式

       数据为王,而合适的数据格式也非常重要
        labelMe的标注数据集格式
        ImageNet coco kitti  apollo
    

    数据集处理

    1.将自己的数据集转化为COCO数据集的格式-COCO的 全称是Common Objects in COntext
    2.将自己的数据集--自定义dataset 和dataloader--然后训练
       制作训练和验证数据的.txt文件
       自定义Dataset,继承Dataset, 重写抽象方法:__init__, __len()__, __getitem()__
    

    coco数据集

     Dataset之COCO数据集--
     1.各个类型包含了训练和验证-文件夹格式-目标检测为例
       01.图片数据
       data/coco/images/train2017
       data/coco/images/val2017
       02.标注数据
         /data/coco/annotations
                         instances_train2017.json 
    	                 instances_val2017.json 
    					 
     2.coco数据集的格式
        MS COCO数据集是微软构建的一个大规模图像数据集,包含目标检测、像素分割及看图说话等任务数据
    		object instances(目标实例), 
    		object keypoints(目标上的关键点), 
    		image captions(看图说话)
    	该数据集的标注信息主要存放为JSON格式,
    	  info、licenses、images这三个结构体/类型 在不同的JSON文件中这三个类型是一样的,定义是共享的。
    	   annotation和category这两种结构体,他们在不同类型的JSON文件中是不一样,不共享。
    	  注释类型包含五大类,
    	   分别为目标检测、关键点检测、素材分割、全景分割及看图说话,
    	   其中五大注释类型共用基础数据结构
    	   {
            "info" : info,   # 数据集描述信息
            "images" : [image],   # 图像字典段列表信息
            "annotations" : [annotation],   # 注释类型字典段列表
    		"categories" : [category],   # 注释类型字典段列表
            "licenses" : [license],   # 许可协议字典段列表
            }
    
              info{
              "year" : int,   # 年份
              "version" : str,   # 版本
              "description" : str,   # 详细描述信息
              "contributor" : str,   # 作者
              "url" : str,   # 协议链接
              "date_created" : datetime,  # 生成日期
              }             
              
              image{
              "id" : int,   # 图像id,可从0开始
              "width" : int,   # 图像的宽
              "height" : int,  # 图像的高
              "file_name" : str,   # 文件名
              "license" : int,   # 遵循哪个协议
              "flickr_url" : str,   # flickr图片链接url
              "coco_url" : str,   # COCO图片链接url
              "date_captured" : datetime, # 获取数据的日期
              }
              
              license{
              "id" : int,   # 协议id编号
              "name" : str,   # 协议名
              "url" : str,   # 协议链接
              }
    	按照不同的任务
    	
    	 01.目标检测和素材分割任务中,annotation和categories字典段的形式如下
              annotation{
              "id" : int,  # 注释id编号
              "image_id" : int,  # 图像id编号
              "category_id" : int,  # 类别id编号
              "segmentation" : RLE or [polygon],  # 分割具体数据
              "area" : float,  # 目标检测的区域大小
              "bbox" : [x,y,width,height],  # 目标检测框的坐标详细位置信息
              "iscrowd" : 0 or 1,  # 目标是否被遮盖,默认为0
              }
              
              categories[{
              "id" : int,  # 类别id编号
              "name" : str,  # 类别名字
              "supercategory" : str, # 类别所属的大类,如哈巴狗和狐狸犬都属于犬科这个大类
              }]
    	02.关键点检测任务中,annotation和categories字典段的形式如下:
    
          annotation{
          "keypoints" : [x1,y1,v1,...],  # 关键点坐标,其中V字段表示关键点属性,0表示未标注,1表示已标注但不可见,2表示已标注且可见
          "num_keypoints" : int,  # 多少个关键点
          "[cloned]" : ...,  # 当同时存在多个任务时其他任务格式的annotation字典段信息直接放在这个位置,不分先后组合
          }
          
          categories[{
          "keypoints" : [str],  # 关键点名字,注意要与num_keypoints对应起来
          "skeleton" : [edge],  # 概略描述
          "[cloned]" : ...,  # 当同时存在多个任务时其他任务格式的categories字典段信息直接放在这个位置,不分先后组合
          }]
    	03.分割任务中,annotation和categories字典段的形式如下:
           annotation{
           "image_id" : int,  # 图像id编号
           "file_name" : str,  # 文件名
           "segments_info" : [segment_info], # 分割数据字典段列表
           }
           
           segment_info{
           "id" : int, # 分割id编号
           "category_id" : int,  # 类别id编号
           "area" : int,  # 分割区域面积大小
           "bbox" : [x,y,width,height],  # 检测框的坐标详细位置信息
           "iscrowd" : 0 or 1, # 该实例是否被遮挡
           }
           
           categories[{
           "id" : int,  # 类别id编号
           "name" : str,  # 类别名
           "supercategory" : str,  # 该类别所属的大类
           "isthing" : 0 or 1,  # 是否为物体
           "color" : [R,G,B],  # 分割标示的像素颜色
           }]
    	annotations字段是包含多个annotation实例的一个数组,
    	   annotation类型本身又包含了一系列的字段,
    	   如这个目标的category id和segmentation mask。
    	   segmentation格式取决于这个实例是一个单个的对象(即iscrowd=0,将使用polygons格式)还是一组对象(即iscrowd=1,将使用RLE格式)
     3.支持的标注
       COCO 支持两种类型的标注,其格式取决于标注的是单个物体 还是密集物体.
           单个物体的标注是沿着物体边界的点列表进行编码的.
           密集物体的标注是采用column-major RLE  进行标注的.  RLE:Run Length Encoding(行程长度压缩算法)-把RLE格式的文件转变为图像格式
    	   iscrowd=0 那么segmentation就是polygon格式
    	   iscrowd=1 那么segmentation就是RLE格式
    

    定制的数据格式说明

      原有的数据标签形式如下:
       文件名 标注框 关键点 类别
    

    转换步骤和代码

     01.转换的数据集方式
         数据放置方式
    	 
     02.转换的步骤
        脚本一开始先将info、licenses及categories进行定义,
    	遍历图像信息将其转换为对应的coco格式,最终生成相应的json文件
     
     03.转换的代码
     
     04.数据集可视化
     
     05.数据集使用
    

    代码示例-转换代码

    #!/usr/bin/env python3
    # -*- coding: UTF-8 -*-
    
    import os
    import os.path
    import json
    import pyhdfs
    import cv2
    import numpy as np
    
    def copy_2_local_multi_dir(stat_file_nm,local_dir):
        """ 根据标注文件内容-下载数据到本地 """
        client = pyhdfs.HdfsClient(hosts="1.1.1.1",user_name="1")
        if not  os.path.exists(local_dir):
            os.makedirs(local_dir)
            print("创建",local_dir)
        with open(file=stat_file_nm,mode='r',encoding="utf8") as f:
            for file_num, data in enumerate(f):
                strdict = json.loads(data)
                hdfs_src_img = strdict.get("pict_nm")
                img_file_nm = hdfs_src_img.strip().replace("\r","").replace("\n","").split("/")[-1]
                local_src_jpg =  os.path.join(local_dir,img_file_nm)
                if client.exists(hdfs_src_img) and not os.path.exists(local_src_jpg):
                    print((file_num,hdfs_src_img, local_src_jpg))
                    client.copy_to_local(hdfs_src_img, local_src_jpg)
                    print(local_src_jpg)
    
    
    #def gene_coco_format(orig_anno_json,dest_dir_path,dest_json):
    def gene_coco_format():
        orig_anno_json = r"F:\dataset\origin\test_2017_data.json"
        dest_dir_path = r"F:\dataset\coco\annotations"
        dest_json ="train2021"
        local_img_dir = r"F:\dataset\coco\images\train2021"
        coco_dataset = {'info':[], 'images':[], 'annotations':[], 'categories':[], 'licenses':[]}
        if not  os.path.exists(dest_dir_path):
            os.makedirs(dest_dir_path)
            print("创建",dest_dir_path)
        classname_to_id = {"person": 1}
        coco_dataset['info'] = 'coco_created'
        coco_dataset['licenses'] = ['mylicense']
        with open(file=orig_anno_file,mode='r',encoding="utf8") as f:
            for f_num, data in enumerate(f):
                strdict = json.loads(data)
                hdfs_src_img = strdict.get("pict_nm")
                img_file_nm = hdfs_src_img.strip().replace("\r","").replace("\n","").split("/")[-1]
                local_src_jpg =  os.path.join(local_img_dir,img_file_nm)
                # 构建COCO的image字段
                coco_dataset["images"].append(
                    {
                        "id" : f_num,   # 图像id,可从0开始
                        "width" : 90,   # 图像的宽
                        "height" : 180,  # 图像的高
                        "file_name" : local_src_jpg,   # 文件名
                        "license" : None,   # 遵循哪个协议
                        "flickr_url" : None,   # flickr图片链接url
                        "coco_url" : None,   # COCO图片链接url
                        "date_captured" : "2017/05/21", # 获取数据的日期
                    }
                )
                mark_info = strdict.get("oriAn").get("res")
                for mark_num,elem in enumerate(mark_info[0].get("elems")):
                    print(f_num,mark_num,elem)
                    print(elem.get("markType"))
                    if elem.get("markType")=="rect":
                        print(elem.get('attribute').get("type"))
                        coco_dataset["annotations"].append(
                            {
                                "id" : mark_num,  # 注释id编号
                                "image_id" : f_num,  # 图像id编号
                                "category_id" : 1,  # 类别id编号
                                "segmentation" : elem.get('points'),  # 分割具体数据
                                "area" : 1,  # 目标检测的区域大小
                                "bbox" : [elem.get('X'),elem.get('Y'),elem.get('W'),elem.get('H')],  # 目标检测框的坐标详细位置信息
                                "iscrowd" : 0 ,  # 目标是否被遮盖,默认为0
                            })
                coco_dataset["categories"].append( {
                    "id" : f_num,   # 图像id,可从0开始
                    "name" : "person",
                    "supercategory" : "mark"
                })
        print(coco_dataset)
        return coco_dataset
    
    
    def save_coco_json( instance, save_path):
        json.dump(instance, open(save_path, 'w', encoding='utf-8'), ensure_ascii=False, indent=1)
    
    # COCO的格式: [x1,y1,w,h] 对应COCO的bbox格式
    def get_box(points):
        min_x = min_y = np.inf
        max_x = max_y = 0
        for x, y in points:
            min_x = min(min_x, x)
            min_y = min(min_y, y)
            max_x = max(max_x, x)
            max_y = max(max_y, y)
        return [min_x, min_y, max_x - min_x, max_y - min_y]
    
    if __name__ == "__main__":
        # 原始的json标注文件
        orig_anno_file = r"F:\dataset\origin\test_2017_data.json"
        local_dir_path = r"F:\dataset\coco\images\train2021"
    
        #1.将图片copy到对应文件夹
        #copy_2_local_multi_dir(orig_anno_file,local_dir_path)
    
        # 生成coco的标注数据集
        instance_info = gene_coco_format()
        json_save_path = r"F:\dataset\coco\annotations\new_coco_data.json"
        save_coco_json(instance_info,json_save_path)
    

    类的方式

      参考github上的代码 prepare_detection_dataset/labelme2coco.py  进行改写
    import json
    import os
    import os.path
    import numpy as np
    
    
    #构建类别-名称对应的ID以及大类
    classname_to_id = {"person": [1,"person"],"cyc":[2,"cyc"],"vertical":[3,"myareaobj"]}
    
    class Lable2CoCo:
        def __init__(self):
            self.images = []
            self.annotations = []
            self.categories = []
            self.img_id = 0
            self.ann_id = 0
    
        def save_coco_json(self, instance, save_path):
            json.dump(instance, open(save_path, 'w', encoding='utf-8'), ensure_ascii=False, indent=1)  # indent=2 更加美观显示
    
        # 由json文件构建COCO
        def to_coco(self, json_path):
            self._init_categories()
            with open(file=json_path,mode='r',encoding="utf8") as f:
                for f_num, data in enumerate(f):
                    obj = json.loads(data)
                    print("Deal image ",f_num)
                    self.images.append(self._image(obj))
                    if "myareaobj" in obj:
                        shapes = obj["myareaobj"]
                        for shape in shapes:
                            annotation = self._annotation(shape)
                            self.annotations.append(annotation)
                            self.ann_id += 1
                    self.img_id += 1
            instance = {}
            instance['info'] = 'my created'
            instance['license'] = ['license']
            instance['images'] = self.images
            instance['annotations'] = self.annotations
            instance['categories'] = self.categories
            return instance
    
        # 构建类别
        def _init_categories(self):
            for k, v in classname_to_id.items():
                category = {}
                category['supercategory'] = v[1]
                category['id'] = v[0]
                category['name'] = k
                self.categories.append(category)
    
        # 构建COCO的image字段
        def _image(self, obj):
            image = {}
            image['height'] =obj["height"]
            image['width'] = obj["width"]
            image['id'] = self.img_id
            image['file_name'] = obj["pict_id"]
            return image
    
        # 构建COCO的annotation字段
        def _annotation(self, shape):
            label = shape['ats']['fly']
            points = shape["pointsdata"]
            annotation = {}
            annotation['id'] = self.ann_id
            annotation['image_id'] = self.img_id
            annotation['category_id'] = int(classname_to_id[label][0])
            # annotation['segmentation'] = [np.asarray(points).flatten().tolist()]
            annotation['segmentation'] = [[0,0]]
            #annotation['bbox'] = self._get_box(points)
            annotation['bbox'] = points
            annotation['iscrowd'] = 0
            annotation['area'] = 1.0
            return annotation
    
    
        # COCO的格式: [x1,y1,w,h] 对应COCO的bbox格式
        def _get_box(self, points):
            min_x = min_y = np.inf
            max_x = max_y = 0
            for x, y in points:
                min_x = min(min_x, x)
                min_y = min(min_y, y)
                max_x = max(max_x, x)
                max_y = max(max_y, y)
            return [min_x, min_y, max_x - min_x, max_y - min_y]
    
    
    if __name__ == '__main__':
        saved_coco_path = "F:\data\instances_train2017.json"
        train_path = r"F:\data\orgin\orign_data.json"
        # 把训练集转化为COCO的json格式
        l2c_train = Lable2CoCo()
        train_instance = l2c_train.to_coco(train_path)
        l2c_train.save_coco_json(train_instance, saved_coco_path)
    

    参考

      在目标检测和关键点检测任务中如何将自己的数据集转为coco格式 https://zhuanlan.zhihu.com/p/56881826
      COCO 数据集的使用 https://www.cnblogs.com/q735613050/p/8969452.html
      prepare_detection_dataset https://github.com/spytensor/prepare_detection_dataset
  • 相关阅读:
    JVM优化系列之一(-Xss调整Stack Space的大小)
    被kill问题之2:Docker环境下Java应用的JVM设置(容器中的JVM资源该如何被安全的限制)
    docker的坑
    docker容器内存占用 之 系统cache,docker下java的内存该如何配置--temp
    查看docker容器的内存占用
    使用Java监控工具出现 Can't attach to the process
    使用docker查看jvm状态,在docker中使用jmap,jstat
    在Docker中监控Java应用程序的5个方法
    HDU2552 三足鼎立 【数学推理】
    C++面向对象模型
  • 原文地址:https://www.cnblogs.com/ytwang/p/15741726.html
Copyright © 2020-2023  润新知