栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Python

<计算机视觉三> pytorch读取自己标定的数据集

Python 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

<计算机视觉三> pytorch读取自己标定的数据集

        上章节讲到了如何将要数据模型转换成网络训练的时候方便读取的数据格式,本文讲解下pytorch模块如何使用这个转换后的数据代码块如下:

#!/usr/bin/env python
# -*- encoding: utf-8 -*-
'''
@File    : datasets.py
@Time    : 2021/08/19 16:37:10
@Author  : XIA Yan
@Contact : 2440212215@qq.com
@Version : 0.1
@License : Apache License Version 2.0, January 2004
@Language: python3.8
@Desc    : torch的训练数据生成
'''

import glob
import random
import numpy as np
from PIL import Image
import torch
import json

import torch.nn.functional as F
from torch.utils.data import Dataset
import torchvision.transforms as transforms



def pad_to_square(img, pad_value = 0):
    c, h, w = img.shape
    dim_diff = np.abs(h - w)
    # (upper / left) padding and (lower / right) padding
    pad1, pad2 = dim_diff // 2, dim_diff - dim_diff // 2
    # Determine padding
    pad = (0, 0, pad1, pad2) if h <= w else (pad1, pad2, 0, 0)
    # Add padding
    img = F.pad(img, pad, "constant", value=pad_value)

    return img, pad



def resize(image, size):
    image = F.interpolate(image.unsqueeze(0), size=size, mode="nearest").squeeze(0)
    return image



class ImageFolder(Dataset):
    def __init__(self, folder_path, img_size=416):
        self.files = sorted(glob.glob("%s/*.*" % folder_path))
        self.img_size = img_size

    def __getitem__(self, index):
        img_path = self.files[index % len(self.files)]
        # 图片解析成pytorch格式的tensor
        img = transforms.ToTensor()(Image.open(img_path).convert("RGB"))
        # Pad to square resolution
        img, _ = pad_to_square(img, 0)
        # Resize
        img = resize(img, self.img_size)

        return img_path, img

    def __len__(self):
        return len(self.files)



class ListDataset(Dataset): 
    '''
    @description:
        加载图像和标签在train阶段或者test阶段
    @Args:
        json_path :(string) 数据的json格式,由createdata/create_targets.py产生
        img_size  :(int) 图像尺寸默认416
        augment   :(bool) 是否采用数据增强方式
    @Return:
        img_path, img, targets
    '''

    def __init__(self, json_path, img_size = 416, augment = None):
        
        with open(json_path, "r") as fp:
            self.json_dict = json.load(fp)     #读取json中字典
        
        self.img_size   = img_size
        self.image_path = list(self.json_dict.keys()) #提取json文件中的image路径
        self.augment    = augment


    def __getitem__(self, index):

        # --------
        #  Image
        # --------


        img_path = self.image_path[index % len(self.image_path)] #获取当前index的图像路径
        labels = np.array(self.json_dict[img_path])              #获取当前index图像的targets

        img = transforms.ToTensor()(Image.open(str(img_path)).convert('RGB'))


        _, h, w = img.shape
        img, pad = pad_to_square(img, 0)
        _, padded_h, padded_w = img.shape


        # ---------
        #  Label
        # ---------
        # 解析坐标(原标记坐标是非normal的[x1,y1,x2,y2]坐标)
        boxes = torch.from_numpy(labels.reshape(-1, 5))
        x1 = boxes[:,1]
        y1 = boxes[:,2]
        x2 = boxes[:,3]
        y2 = boxes[:,4]

        # Adjust for added padding
        x1 += pad[0]
        y1 += pad[2]
        x2 += pad[1]
        y2 += pad[3]

        # Returns (x, y, w, h)
        cx  = (x1 + x2) / 2
        cy  = (y1 + y2) / 2
        w   = x2  - x1
        h   = y2  - y1

        # normal coords
        boxes[:, 1]  = cx / padded_w
        boxes[:, 2]  = cy / padded_h
        boxes[:, 3]  = w  / padded_w
        boxes[:, 4]  = h  / padded_h

        targets = torch.zeros((len(boxes), 6))
        targets[:, 1:] = boxes

        # TODO 数据增强
        if self.augment:
            pass

        return img_path, img, targets

    def collate_fn(self, batch):
        '''
        @description:
            重写collate_fn方法,用于处理每个batch信息
        @Args:
            batch:
        @Return:
            返回经过batch处理后的,图片路径,图片,targets
        '''
        
        paths, imgs, targets = list(zip(*batch))
        for i, boxes in enumerate(targets):
            boxes[:, 0] = i  
        imgs = torch.stack([resize(img, self.img_size) for img in imgs])           
        return paths, imgs, torch.cat(targets, 0)
    
    def __len__(self):
        return len(self.image_path)



if __name__ == '__main__':
    
    dataset = ListDataset('data/data.json')

    print(dataset[0])

 pytorch中给网络模型产生数据的主要模块是torch.utils.data中的Dataset

 from torch.utils.data import Dataset

 首先使用如下代码讲之前的转换的json数据进行解析

    def __init__(self, json_path, img_size = 416, augment = None):
        
        with open(json_path, "r") as fp:
            self.json_dict = json.load(fp)     #读取json中字典
        
        self.img_size   = img_size
        self.image_path = list(self.json_dict.keys()) #提取json文件中的image路径
        self.augment    = augment

self.image_path是获取了所有的图像路径

_, h, w = img.shape                    # 获取图像的通道数、高和宽
img, pad = pad_to_square(img, 0)       # 将图像填充为正方形
_, padded_h, padded_w = img.shape      # 获取填充后的数据格式

下面给出本模块的示意图:

        图中将本模块的大致功能讲解了一下,通过读取图像数据和对应的图像标签数据,需要将数据转换成tensor格式,因为图像数据标注的时候有长宽比例不一致的情况,因此在这里需要将图像规范为正方形,那这边就牵涉到图像的正方形填充。填充完毕后需要记录下填充后的多少个内容,这样在将图像映射回原图的时候能够正确绘出矩形框。

        这里顺便提示下,由于我之前参加一个项目是利用红外摄像头读取数据进行检测,然后读取检测后的图像温度,红外一起的尺寸为640*512的分辨率。采集数据和实际使用数据都是这个分辨率,这个项目中我并没有使用图像的正方形化,训练的时候就是用得640*512尺寸。这样的好处是省去了图像生成和推理的时间。因此我们在知道为什么需要填充成正方形的原因才能知道什么情况下不使用。算法和技巧并不是一成不变的,需要灵活应用。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/994162.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号