Maskrcnn实现笔记---数据处理篇

目录


前言

在深度学习中,数据集一般是指用作网络训练的数据集合。数据集包含输入和真实输出(ground truth)两部分,视觉类深度学习中输入为图片,输出为分类结果、预测框及分割结果等。
数据集一般会分为训练集(train dataset)、验证集(valid dataset)和测试集(test dataset)三部分,训练集用于网络训练,验证集一般用于在训练是验证训练效果,根据训练效果保存训练最好的模型,测试集测试训练效果。

一、labelme标定

maskrcnn需要的输入为图片,输出为lable、box及mask。正常讲应该在标定的时候,label、box和mask都进行标定,但是实际上box可以由mask推出,所以只需要标定mask及label即可。
1.安装labelme
在anaconda中新建一个环境命名为lableme,安装labelme。

# python3
conda create --name=labelme python=3.6
source activate labelme
# install pyqt
pip install pyqt5  # pyqt5 can be installed via pip on python3
# instal labelme
pip install labelme

2.标记
cmd中或anaconda中:activate labelme,labeleme。打开labelme,create polygons,把需要检测分割的对象分割出来,打上标签。
Maskrcnn实现笔记---数据处理篇
一个个标注好了之后,将生成json文件。

二、对data进一步处理

1.数据增强

如果自己的数据比较少的话,为了避免过拟合等问题,最好进行下数据增强。可以加噪音,翻转等操作。

2.json_to_dataset

批量给它转成dataset
批量json to dataset,将生成四个文件,都放在一个文件夹下了。
也可以把里面的json_to_dataset.py文件复制到自己的项目中,修改一下,直接指定路径是自己标记好的Json文件夹,输出的路径也进一步修改下,可以把生成的dataset生成到项目文件夹下。修改如下:

import argparse
import base64
import json
import os
import os.path as osp

import imgviz
import PIL.Image

from labelme.logger import logger
from labelme import utils


def main():

    # 输入路径
    json_file = "./json_files"

    # 为了批量处理的改动1,获得目录下所有的.json后缀文件
    path = []
    file_name = []
    for root, dirs, files in os.walk(json_file):  # 获取所有文件
        for file in files:  # 遍历所有文件名
            if os.path.splitext(file)[1] == '.json':  # 指定尾缀
                file_name.append(file.split('.')[0])   # 为了获取**.json中的**
                path.append(os.path.join(root, file))  # 拼接绝对路径并放入列表
    print('总文件数目:', len(path))

    # 为了批量处理改动2,都放入循环中
    for i in range(len(path)):
        data = json.load(open(path[i]))
        imageData = data.get("imageData")

        if not imageData:
            imagePath = os.path.join(os.path.dirname(json_file), data["imagePath"])
            with open(imagePath, "rb") as f:
                imageData = f.read()
                imageData = base64.b64encode(imageData).decode("utf-8")
        img = utils.img_b64_to_arr(imageData)

        label_name_to_value = {"_background_": 0}
        for shape in sorted(data["shapes"], key=lambda x: x["label"]):
            label_name = shape["label"]
            if label_name in label_name_to_value:
                label_value = label_name_to_value[label_name]
            else:
                label_value = len(label_name_to_value)
                label_name_to_value[label_name] = label_value
        lbl, _ = utils.shapes_to_label(
            img.shape, data["shapes"], label_name_to_value
        )

        label_names = [None] * (max(label_name_to_value.values()) + 1)
        for name, value in label_name_to_value.items():
            label_names[value] = name

        lbl_viz = imgviz.label2rgb(
            label=lbl, img=imgviz.asgray(img), label_names=label_names, loc="rb"
        )

        # 输出路径
        if not os.path.exists("train_dataset"):
            os.mkdir("train_dataset")
        mask_path = "train_dataset/mask"
        if not os.path.exists(mask_path):
            os.mkdir(mask_path)
        img_path = "train_dataset/imgs"
        if not os.path.exists(img_path):
            os.mkdir(img_path)
        class_path = "train_dataset/classes"
        if not os.path.exists(class_path):
            os.mkdir(class_path)
        label_viz_path = "train_dataset/label_viz"
        if not os.path.exists(label_viz_path):
            os.mkdir(label_viz_path)

        # 改动3:下面加了四个filename,1和2都是为了输出的时候名字改变
        PIL.Image.fromarray(img).save(osp.join(img_path, file_name[i]+".png"))
        utils.lblsave(osp.join(mask_path, file_name[i]+"_label.png"), lbl)
        PIL.Image.fromarray(lbl_viz).save(osp.join(label_viz_path, file_name[i]+"_label_viz.png"))

        with open(osp.join(class_path, file_name[i]+"label_names.txt"), "w") as f:
            for lbl_name in label_names:
                f.write(lbl_name + "\n")

        logger.info("Saved {0} files".format(i+1))



if __name__ == "__main__":
    main()

我的文件夹结构:
Maskrcnn实现笔记---数据处理篇
以上数据集的准备任务就完成了,下面是实际训练的时候所用的函数。

三、实际训练数据集处理

定义一个自己的数据集类,对处理过的train_dataset进行读取解析。
映射式数据集,需要定义__init__()和__getitem__()方法,之后利用torch.utitls.Dataloader()进行加载,分为一个个batch进行训练。

class PennFudanDataset(object):
    def __init__(self, root, transforms):
        self.root = root
        self.transforms = transforms
        # load all image files, sorting them to
        # ensure that they are aligned
        self.imgs = list(sorted(os.listdir(os.path.join(root, "images"))))
        self.jsons = list(sorted(os.listdir(os.path.join(root, "jsons"))))

    def __getitem__(self, idx):
        # load images and masks
        img_path = os.path.join(self.root, "images", self.imgs[idx])
        json_path = os.path.join(self.root, "jsons", self.jsons[idx])
        img = Image.open(img_path).convert("RGB")

        mask = Image.open(json_path)

        mask = np.array(mask)
        # instances are encoded as different colors
        obj_ids = np.unique(mask)  # 原图被处理为,背景部分为0,第一个行人为1.第二个为2,以此类推。
        # first id is the background, so remove it
        obj_ids = obj_ids[1:]

        # split the color-encoded mask into a set
        # of binary masks
        masks = mask == obj_ids[:, None, None]

        # get bounding box coordinates for each mask
        num_objs = len(obj_ids)
        boxes = []
        """box是通过掩码得到的,那可以直接把mask改成抓取描述,由抓取描述也可以得到boxes吧"""
        for i in range(num_objs):
            pos = np.where(masks[i])
            xmin = np.min(pos[1])
            xmax = np.max(pos[1])
            ymin = np.min(pos[0])
            ymax = np.max(pos[0])
            boxes.append([xmin, ymin, xmax, ymax])

        boxes = torch.as_tensor(boxes, dtype=torch.float32)
        # there is only one class
        labels = torch.ones((num_objs,), dtype=torch.int64)
        masks = torch.as_tensor(masks, dtype=torch.uint8)

        image_id = torch.tensor([idx])
        area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])
        # suppose all instances are not crowd
        iscrowd = torch.zeros((num_objs,), dtype=torch.int64)

        target = {}
        target["boxes"] = boxes
        target["labels"] = labels
        target["masks"] = masks
        target["image_id"] = image_id
        target["area"] = area
        target["iscrowd"] = iscrowd

        if self.transforms is not None:
            img, target = self.transforms(img, target)

        return img, target

    def __len__(self):
        return len(self.imgs)
上一篇:BERT和GPT


下一篇:【密码学】Diffie–Hellman Key Exchange