1.如何处理mat文件
SBD数据集时常用于语义分割的数据集,图片数据的lbl文件时mat文件,这个文件要怎么处理啊
import numpy as np
import PIL.Image
import scipy.io
import torch
from torch.utils import data
lbl_file = '/home/mlxuan/project/DeepLearning/data/benchmark/benchmark_RELEASE/dataset/cls/2010_005556.mat'
mat = scipy.io.loadmat(lbl_file)
lbl = mat['GTcls'][0]['Segmentation'][0].astype(np.int32)
mat的格式很复杂 看不懂
lbl的值:lbl中只有0和另外一个值,表示这个图像中的类
lbl对应的原图:
使用tensorboardX将lbl可视化
from tensorboardX import SummaryWriter
writer = SummaryWriter()
lbl = torch.from_numpy(lbl).long()
writer.add_image('lbl2',lbl)
writer.close()
2.遍历trainloader时,
如果batch_size不是1,那么每次输入的batch_size个Tensor就需要有相同的size,否则就不能遍历
如果batch_size=2,trainset的getitem2次返回的Tensor大小不同时,报错
将返回的Tensor变为同一大小后,错误消失,根据data的格式可知,getitem返回的Tensor需要同一大小
读取一张图片为PIL Image,转变为Tensor并归一化,然后在反变换为PIL Image的代码
import torch as t
from PIL import Image
im = Image.open('/home/mlxuan/project/DeepLearning/data/benchmark/benchmark_RELEASE/dataset/img/2008_000002.jpg')
#变换为Tensor
from torchvision import transforms as T
trans = T.Compose([T.ToTensor(), T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
img = trans(im)
从Tensor反变换为PIL Image
trans = T.Compose([T.Normalize([-0.485/0.229,-0.456/0.224,-0.406/0.225],[1/0.229,1/0.224,1/0.225]) ])
img2 = trans(img)
img3=img2*255
img3
img4 = T.ToPILImage()(img2)
img4
3.几种图像大小变换的方式
深度学习,由于需要batchsize操作,许多时候需要把图片变为同一大小
常见的两种方式:
from PIL import Image
im = Image.open('/home/mlxuan/project/DeepLearning/data/benchmark/benchmark_RELEASE/dataset/img/2008_000002.jpg')
方式1:利用torchvision.transforms来操作,这种方式保持了纵横比信息,但是会丢掉边缘信息
T.Resize(224)保持图像的纵横比,按照窄边缩放为224
T.CenterCrop(224)中心裁剪为224
方式2:利用PIL Image的函数操作(这种方式失去了图像的纵横比信息,但是保持图像的边缘)
4.
将自己的图片定义为dataset,用dataloader遍历,并使用TensorBoardX可视化
'''定义自己的数据集'''
# coding:utf8
import os
from PIL import Image
from torch.utils import data
import numpy as np
from torchvision import transforms as T
import scipy.io
import torch
import utils
def picFulPath(txtPath,rootImg,rootLbl):
'''
给定只包含图片文件名的txt和图片所在路径
参数:txtPath 包含图片文件名的txt的路径
rootImg:图片所在的根文件夹
rootLbl:标记文件所在的根目录
:return: 包含图片绝对路径和图片文件名、包含标签绝对和标签和的txt文档
'''
#读取txtpath中的每一行,然后加上rootImag和rootLbl后写入新的txt文档
f = open('./ImagAndLal.txt','w')
fh = open(txtPath, 'r')
#读取txtPath中的每一行,每一行都是图片文件的文件名,在每一行中加上绝对路径
for line in fh:
line = line.rstrip() # 去掉改行最后的回车符号
line = rootImg+line+'.jpg'+' '+rootLbl+line+'.mat'+'\n'#此处最好改为文件名的相加,而不是单纯的字符串相加
f.write(line)
f.close()
fh.close()
class SBDClassSeg(data.Dataset):
def __init__(self, txt_path, transforms=None,train=True):#此处train val test(指定此次的数据时用来做什么的,不同用处的数据集图片预处理方法不同,可以传入不同的txt_path即可)的指定应该用union
'''
dataset是为了dataloader而定义,dataloader是为了按照batch遍历数据集,所以dataset要制定数据集、获得数据集元素的方法,数据集长度
dataset生成self.imgs,这是一个list,包含了数据集的所有图片组成的list
参数:txt_path包含了每张图片的路径和图片的标签(语义分割时就是标记好的图片的路径)
transforms表示该读取图片后,图片要进行的预处理,如果为None,则使用默认的预处理
'''
#1.指定数据集,常用的方法是给定图片路径的txt文档,将他们读入一个列表
imgs=[]
self.train=train
fh = open(txt_path, 'r')
#遍历整个txt文档,每张图片的路径作为list的一个元素
for line in fh:
line = line.rstrip()#去掉改行最后的回车符号
words = line.split()
imgs.append((words[0], words[1]))#words[0]是原图片的路径,words[1]是标记好的图片的标签
self.imgs = imgs
# 2.指定读入图片后的预处理
if transforms is None:
def transforms(img,lbl):
#T.Resize T.CenterCrop将图片保持纵横比缩放裁剪为同一大小,
#T.Tensor,T.Normalize 将图片转为[0,1]的Tensor,并归一化
trans = T.Compose([T.Resize(224),T.CenterCrop(224),
T.ToTensor(),
T.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])])
img = trans(img)
#lbl时mat格式,处理参考https://blog.csdn.net/qq_32425195/article/details/85202552
lbl = torch.from_numpy(np.array(lbl)).int()
lbl[lbl == 255] = 0
#T.ToPILImage()将tensor转为PILImage,然后做Resize和CenterCrop处理
trans = T.Compose([T.ToPILImage(),T.Resize(224),T.CenterCrop(224),
T.ToTensor()])
lbl = trans(lbl.unsqueeze(0))
return img,lbl
def untransforms(img,lbl):
#该trans是对已经归一化的tensor处理,得到归一化之前的Tensor
trans = T.Compose([T.Normalize([-0.485/0.229,-0.456/0.224,-0.406/0.225],[1/0.229,1/0.224,1/0.225])])
imgUntrans = torch.Tensor(img.shape)
for i in range(img.shape[0]):
imgUntrans[i]= trans(img[i])
return imgUntrans,lbl
# 常规的数据操作:(裁剪为统一大小,可选T.scale),(数据增强,如随机裁剪等 语义分割时一般不做这个),ToTensor()后+T.Normalize
if self.train:#如果此次是训练集(训练集和验证集可能读取数据方法一样,但是预处理的过程不一样)
self.transforms = transforms
self.untransforms = untransforms
fh.close()
def __getitem__(self, index):#该方法是给定索引或键值,返回对应的值,常用在enumerate遍历数据集时
'''返回一张图片的验证集和测试集的数据'''
#从list中获取图片的路径
img_path = self.imgs[index][0]
lbl_path = self.imgs[index][1]
#读取图片,为numpy格式
im = Image.open(img_path)
#lbl是mat格式,mat格式的处理参考https://blog.csdn.net/qq_32425195/article/details/85202552
mat = scipy.io.loadmat(lbl_path)
lbl = mat['GTcls'][0]['Segmentation'][0].astype(np.int32)
im,lbl = self.transforms(im,lbl)
return im,lbl
def __len__(self):
'''
返回为数据集中所有图片的个数
:return:
'''
return len(self.imgs)
if __name__ == '__main__':
picFulPath('/home/mlxuan/project/DeepLearning/data/benchmark/benchmark_RELEASE/dataset/train.txt','/home/mlxuan/project/DeepLearning/data/benchmark/benchmark_RELEASE/dataset/img/','/home/mlxuan/project/DeepLearning/data/benchmark/benchmark_RELEASE/dataset/cls/')
train_dataset = SBDClassSeg('./ImagAndLal.txt')
from torch.utils.data import DataLoader
trainloader = DataLoader(train_dataset,batch_size=2,shuffle=False,drop_last=True)
V = utils.Visualizer()
#按batch_size遍历trainloader
for i,(data,label) in enumerate(trainloader):# 如果batch_size不是1,那么每次输入的batch_size个Tensor就需要有相同的size,否则就不能遍历。还可以用for data,label in trainloader:遍历
#data,label = trainloader.dataset.untransforms(data,label)
#label.unsqueeze_(1)
V.plot_many('imgs'+str(i),data)
V.plot_img('imgs' + str(i), label)
V.close()
'''调用TensorBoardX中的函数,可视化
使用方法:
在文件当前目录执行tensorboard --logdir runs
首先调用 V = Visualizer()初始化类对象,在当前目录新建了文件
然后调用V.plotxx来绘图,绘图会实时显示
绘制完所有的图像,关闭当前的对象V.close()
'''
import torch
import torchvision.utils as vutils
import numpy as np
import torchvision.models as models
from torchvision import datasets
from tensorboardX import SummaryWriter
class Visualizer(object):
def __init__(self,): # env表示路径
self.writer = SummaryWriter()
def plot_many(self, tag,tensor):
"""
用于一次绘制多张图像,每张图像需要有相同的通道数和分辨率,输入为tensor(要显示的图片数,每张图片的通道,每张图片的宽,每张图片的高)
"""
__= vutils.make_grid(tensor)
#with self.writer:
self.writer.add_image(tag, __)
self.writer.file_writer.flush()
def plot_img(self,tag,img_tensor):
"""绘制一张图片"""
#with self.writer:
self.writer.add_image(tag,img_tensor)
self.writer.file_writer.flush()
def close(self):
self.writer.close()
if __name__ == '__main__':
V = Visualizer()
_ = torch.rand(32,3,64,64)
V.plot_many('img',_)
V.plot_img('tag',torch.rand(3,224,224))
V.close()
大小控制位224*224后的图片
label图
做了Normalize后直接显示的图片