在学习中,碰到FCN的部分源码,对这部分做一个集中的学习
代码如下:
class SegmentationPresetTrain: #训练过程中图像预处理方法
def __init__(self, base_size, crop_size, hflip_prob=0.5, mean=(0.485, 0.456, 0.406), std=(0.229, 0.224, 0.225)):
min_size = int(0.5 * base_size) #520*0.5=260
max_size = int(2.0 * base_size) #520*2=1024
trans = [T.RandomResize(min_size, max_size)] #随机选取数值
if hflip_prob > 0: #随机水平翻转大于0
trans.append(T.RandomHorizontalFlip(hflip_prob)) #水平翻转
trans.extend([
T.RandomCrop(crop_size), #随机裁剪
T.ToTensor(),
T.Normalize(mean=mean, std=std),#标准化
])
self.transforms = T.Compose(trans) #将预处理方法进行打包
def __call__(self, img, target): #transforms方法是在call中被调用的
return self.transforms(img, target)
def get_transform(train): #train为true的话
base_size = 520
crop_size = 480
return SegmentationPresetTrain(base_size, crop_size) if train else SegmentationPresetEval(base_size)#后者是验证集的图片大小
当train为true时,调用SegmentationPresetTrain(base_size, crop_size),并且传参
base_size = 520 crop_size = 480
__call__方法中引用
self.transforms(img, target)
__init__方法
-
RandomResize(min_size, max_size):将img,target缩放为随机尺寸大小
class RandomResize(object): #随机裁剪
def __init__(self, min_size, max_size=None):
self.min_size = min_size
if max_size is None:
max_size = min_size #如果max_size没有传入值,则默认将min_size传入进来
self.max_size = max_size
def __call__(self, image, target):
size = random.randint(self.min_size, self.max_size) #随机选择一个整数,随机长宽比裁剪原始图片,最后将图片resize到设定好的size
# 这里size传入的是int类型,所以是将图像的最小边长缩放到size大小
image = F.resize(image, size)
# 这里的interpolation注意下,在torchvision(0.9.0)以后才有InterpolationMode.NEAREST
# 如果是之前的版本需要使用PIL.Image.NEAREST
target = F.resize(target, size, interpolation=T.InterpolationMode.NEAREST)
return image, target
-
水平翻转transforms.RandomHorizontalFlip
class torchvision.transforms.RandomHorizontalFlip(p=0.5)
功能:依据概率p对PIL图片进行水平翻转,水平翻转是左右翻转。180°
参数:
p- 概率,默认值为0.5
-
Python List append()方法
append() 方法用于在列表末尾添加新的对象
语法:
list.append(obj) #obj -- 添加到列表末尾的对象
该方法无返回值,但是会修改原来的列表
示例:
aList = [123, 'xyz', 'zara', 'abc']
aList.append( 2009 )
print("Updated List : ", aList)
#Updated List : [123, 'xyz', 'zara', 'abc', 2009]
-
Python List extend()方法
extend() 函数用于在列表末尾一次性追加另一个序列中的多个值(用新列表扩展原来的列表)。
语法:
list.extend(seq) #seq -- 元素列表
该方法没有返回值,但会在已存在的列表中添加新的列表内容。
示例:
aList = [123, 'xyz', 'zara', 'abc', 123];
bList = [2009, 'manni'];
aList.extend(bList)
print("Extended List : ", aList)
#Extended List : [123, 'xyz', 'zara', 'abc', 123, 2009, 'manni']
原文中的代码:
def append(self, *args, **kwargs): # real signature unknown
""" Append object to the end of the list. """
pass
def extend(self, *args, **kwargs): # real signature unknown
""" Extend list by appending elements from the iterable. """
pass
-
RandomCrop(min_size, max_size):将img,target裁剪为随机尺寸大小
T.RandomCrop(crop_size), #随机裁剪 crop_size=480
源码阅读:
def pad_if_smaller(img, size, fill=0):
# 如果图像最小边长小于给定size,则用数值fill进行padding
min_size = min(img.size)
if min_size < size: #图像边长小的时候
ow, oh = img.size
padh = size - oh if oh < size else 0 #一般使用0填充
padw = size - ow if ow < size else 0
img = F.pad(img, (0, 0, padw, padh), fill=fill)
return img
class RandomCrop(object): #从图片中随机位置裁剪出size大小的图片
def __init__(self, size):
self.size = size
def __call__(self, image, target):
image = pad_if_smaller(image, self.size) #如果图像最小边长小于给定size,则用数值fill进行padding
target = pad_if_smaller(target, self.size, fill=255) #填充的像素是没有意义的,所以标签设置255,求损失的时候会忽略
crop_params = T.RandomCrop.get_params(image, (self.size, self.size)) # get_params(img, output_size),返回i, j, th, tw
image = F.crop(image, *crop_params) #裁剪的大小
target = F.crop(target, *crop_params)
return image, target
def get_params(img: Tensor, output_size: Tuple[int, int]) -> Tuple[int, int, int, int]:
"""Get parameters for ``crop`` for a random crop.
Args:
img (PIL Image or Tensor): Image to be cropped.
output_size (tuple): Expected output size of the crop.
Returns:
tuple: params (i, j, h, w) to be passed to ``crop`` for random crop.
"""
w, h = F.get_image_size(img) #传入的img大小
th, tw = output_size #裁剪大小
if h + 1 < th or w + 1 < tw:
raise ValueError(
"Required crop size {} is larger then input image size {}".format((th, tw), (h, w))
) #如果填充后,得到的img图片大小小于裁剪大小则会报错
if w == tw and h == th: #填充后,img大小与裁剪大小相等
return 0, 0, h, w
#填充后,img图片大于裁剪大小,返回需要裁剪的地方(i,j)以及目标裁剪的高和宽
i = torch.randint(0, h - th + 1, size=(1, )).item()
j = torch.randint(0, w - tw + 1, size=(1, )).item()
return i, j, th, tw
版权声明:本文为qq_36998053原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。