接上一篇,PaddleSeg 自定义数据类 https://blog.csdn.net/HaoZiHuang/article/details/125566058 这里再说一下 Normalize 操作
咱们自己写 Transform 时,总会担心一些细节,比如:
/255
做了没)上一篇PaddleSeg说到,在Compose结尾,会做输入通道数的转换(Transpose),而看源代码:
batch_sampler = paddle.io.DistributedBatchSampler(
eval_dataset, batch_size=1, shuffle=False, drop_last=False)
loader = paddle.io.DataLoader(
eval_dataset,
batch_sampler=batch_sampler,
num_workers=num_workers,
return_list=True, )
这个是实例化,Dataset 和 DataLoader 的部分,尽管 eval_dataset
返回的每个数据都是 np.ndarray,但是 paddle.io.DataLoader
这个类,会直接返回 Paddle.Tensor 类的数据,也就是无需再做 paddle.to_tensor
操作
OK, 接下里的这三项:
就是 Normalize 部分的操作了,来看看它实现的源码
paddleseg\transforms\transforms.py
中 Normalize
类
@manager.TRANSFORMS.add_component
class Normalize:
"""
Normalize an image.
Args:
mean (list, optional): The mean value of a data set. Default: [0.5, 0.5, 0.5].
std (list, optional): The standard deviation of a data set. Default: [0.5, 0.5, 0.5].
Raises:
ValueError: When mean/std is not list or any value in std is 0.
"""
def __init__(self, mean=(0.5, 0.5, 0.5), std=(0.5, 0.5, 0.5)):
self.mean = mean
self.std = std
if not (isinstance(self.mean,
(list, tuple)) and isinstance(self.std,
(list, tuple))):
raise ValueError(
"{}: input type is invalid. It should be list or tuple".format(
self))
from functools import reduce
if reduce(lambda x, y: x * y, self.std) == 0:
raise ValueError('{}: std is invalid!'.format(self))
def __call__(self, im, label=None):
"""
Args:
im (np.ndarray): The Image data.
label (np.ndarray, optional): The label data. Default: None.
Returns:
(tuple). When label is None, it returns (im, ), otherwise it returns (im, label).
"""
mean = np.array(self.mean)[np.newaxis, np.newaxis, :]
std = np.array(self.std)[np.newaxis, np.newaxis, :]
im = functional.normalize(im, mean, std)
if label is None:
return (im, )
else:
return (im, label)
paddleseg\transforms\functional.py
中 normalize
函数
def normalize(im, mean, std):
im = im.astype(np.float32, copy=False) / 255.0
im -= mean
im /= std
return im
可以看到 在 normalize
函数中,做了转 np.float32, 归一化
然后 -0.5
之后 /0.5
如果你对这两行感兴趣:
mean = np.array(self.mean)[np.newaxis, np.newaxis, :]
std = np.array(self.std )[np.newaxis, np.newaxis, :]
自己打印看看吧,就是个原来的array维度前面加了两个1
shape 从 (3,) 变成了 (1, 1, 3)
而 np.newaxis
其实就是 None
(np.newaxis == None) == True
如果对 Normalize __init__函数中的 reduce 感兴趣:
可以看看这个:
functools下的reduce函数