花园宝宝战队 ----- 一阶段代码注释成果 #10

Open
bjutsecurity22 wants to merge 139 commits from bjutsecurity22/mindspore2022:master into master
1 changed files with 166 additions and 613 deletions
Showing only changes of commit 4839673eb5 - Show all commits

View File

@ -1,4 +1,4 @@
# Copyright 2019-2022 Huawei Technologies Co., Ltd
# Copyright 2019 Huawei Technologies Co., Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -13,625 +13,178 @@
# limitations under the License.
# ==============================================================================
"""
The module vision.py_transforms is mainly implemented based on Python PIL, which
provides many kinds of image augmentation methods and conversion methods between
PIL.Image.Image and numpy.ndarray. For users who prefer using Python PIL in computer vision
tasks, this module is a good choice to process images. Users can also self-define
their own augmentation methods with Python PIL.
The module transforms.py_transform is implemented based on Python. It provides common
operations including OneHotOp.
"""
import numbers
import random
import json
import sys
import numpy as np
from PIL import Image
import mindspore.dataset.transforms.py_transforms as py_transforms
from .validators import check_one_hot_op, check_compose_list, check_random_apply, check_transforms_list, \
check_compose_call
from . import py_transforms_util as util
from .c_transforms import parse_padding
from .py_transforms_util import is_pil
from .utils import Border, Inter
from .validators import check_adjust_gamma, check_alpha, check_auto_contrast, check_center_crop, check_cutout, \
check_five_crop, check_hsv_to_rgb, check_linear_transform, check_mix_up, check_normalize_py, \
check_normalizepad_py, check_num_channels, check_pad, check_positive_degrees, check_prob, check_random_affine, \
check_random_color_adjust, check_random_crop, check_random_erasing, check_random_perspective, \
check_random_resize_crop, check_random_rotation, check_resize_interpolation, check_rgb_to_bgr, check_rgb_to_hsv, \
check_ten_crop, check_uniform_augment_py
from .c_transforms import TensorOperation
DE_PY_BORDER_TYPE = {Border.CONSTANT: 'constant',
Border.EDGE: 'edge',
Border.REFLECT: 'reflect',
Border.SYMMETRIC: 'symmetric'}
DE_PY_INTER_MODE = {Inter.NEAREST: Image.NEAREST,
Inter.ANTIALIAS: Image.ANTIALIAS,
Inter.LINEAR: Image.LINEAR,
Inter.CUBIC: Image.CUBIC}
class AdjustGamma(py_transforms.PyTensorOperation):
# 定义AdjustGamma类用于调整图像的gamma值
@check_adjust_gamma
def __init__(self, gamma, gain=1.0):
# 初始化AdjustGamma类参数为gamma值和gain值
self.gamma = gamma
self.gain = gain
self.random = False
def __call__(self, img):
# 调用adjust_gamma函数输入图像和gamma值和gain值
return util.adjust_gamma(img, self.gamma, self.gain)
class AutoContrast(py_transforms.PyTensorOperation):
# 定义AutoContrast类实现__init__方法参数cutoff为阈值ignore为忽略的像素
@check_auto_contrast
def __init__(self, cutoff=0.0, ignore=None):
self.cutoff = cutoff
self.ignore = ignore
self.random = False
# 定义__call__方法参数img为图像
def __call__(self, img):
# 调用util.auto_contrast函数参数imgcutoffignore
return util.auto_contrast(img, self.cutoff, self.ignore)
class CenterCrop(py_transforms.PyTensorOperation):
# 初始化函数,设置裁剪的大小
@check_center_crop
def __init__(self, size):
self.size = size
self.random = False
# 调用util.center_crop函数参数img, size
def __call__(self, img):
return util.center_crop(img, self.size)
# 从输入图像数组中随机裁剪出给定数量的正方形区域。
class Cutout(py_transforms.PyTensorOperation):
# 初始化Cutout类参数为length num_patches
@check_cutout
def __init__(self, length, num_patches=1):
self.length = length
self.num_patches = num_patches
self.random = False
# 定义__call__方法用于调用Cutout类
def __call__(self, np_img):
# 如果np_img不是NumPy数组抛出类型错误异常
if not isinstance(np_img, np.ndarray):
raise TypeError(
"img should be NumPy array. Got {}.".format(type(np_img)))
# 如果np_img的维度不是3抛出类型错误异常
if np_img.ndim != 3:
raise TypeError(
'img dimension should be 3. Got {}.'.format(np_img.ndim))
# 获取np_img的高度和宽度
_, image_h, image_w = np_img.shape
# 计算图片裁剪规模
scale = (self.length * self.length) / (image_h * image_w)
# 将bounded赋值为False
bounded = False
# 遍历num_patches次
for _ in range(self.num_patches):
# 获取i,j,erase_h(擦除区域高度),erase_w擦除区域宽度,erase_value擦除区域的像素填充值
i, j, erase_h, erase_w, erase_value = util.get_erase_params(np_img, (scale, scale), (1, 1), 0, bounded,
1)
# 使用util.erase函数将np_img中的像素值替换为erase_value
np_img = util.erase(np_img, i, j, erase_h, erase_w, erase_value)
# 返回np_img
return np_img
# 将输入的压缩图像解码为RGB格式
class Decode(py_transforms.PyTensorOperation):
# 定义Decode类
def __init__(self):
self.random = False
def __call__(self, img):
# 调用util.decode函数输入img
return util.decode(img)
# 对输入图像进行直方图均衡化。
class Equalize(py_transforms.PyTensorOperation):
# 定义Decode类
def __init__(self):
self.random = False
def __call__(self, img):
# 调用util.equalize函数输入img返回比较图像
return util.equalize(img)
# 定义一个类FiveCrop用来对图像进行五分类
class FiveCrop(py_transforms.PyTensorOperation):
@check_five_crop
def __init__(self, size):
# 初始化类FiveCrop参数为size
self.size = size
self.random = False
def __call__(self, img):
# 返回五分类图像
return util.five_crop(img, self.size)
# 将输入PIL图像转换为灰度图
class Grayscale(py_transforms.PyTensorOperation):
# 定义Grayscale类
@check_num_channels
def __init__(self, num_output_channels=1):
# 初始化类参数num_output_channels表示输出通道数
self.num_output_channels = num_output_channels
self.random = False
def __call__(self, img):
# 返回一个黑白图像
return util.grayscale(img, num_output_channels=self.num_output_channels)
# 将输入的HSV格式numpy.ndarray图像转换为RGB格式。
class HsvToRgb(py_transforms.PyTensorOperation):
# 定义HsvToRgb类参数为is_hwc默认为False
@check_hsv_to_rgb
def __init__(self, is_hwc=False):
# 初始化HsvToRgb类参数为is_hwc
self.is_hwc = is_hwc
# 设置随机数为False
self.random = False
def __call__(self, hsv_imgs):
# 调用util.hsv_to_rgbs函数传入hsv_imgsis_hwc参数
return util.hsv_to_rgbs(hsv_imgs, self.is_hwc)
# 将输入图像的shape从 <H, W, C> 转换为 <C, H, W>
class HWC2CHW(py_transforms.PyTensorOperation):
def __init__(self):
self.random = False
def __call__(self, img):
return util.hwc_to_chw(img)
# 在 RGB 模式下对输入图像应用像素反转。
class Invert(py_transforms.PyTensorOperation):
# 定义Invert类初始化random变量
def __init__(self):
self.random = False
# 返回util.invert_color函数的调用结果
def __call__(self, img):
return util.invert_color(img)
# 使用指定的变换方阵和均值向量对输入numpy.ndarray图像进行线性变换。
class LinearTransformation(py_transforms.PyTensorOperation):
# 定义LinearTransformation类参数transformation_matrix mean_vector
@check_linear_transform
def __init__(self, transformation_matrix, mean_vector):
self.transformation_matrix = transformation_matrix
self.mean_vector = mean_vector
self.random = False
def __call__(self, np_img):
# 返回线性变换后的图像
return util.linear_transform(np_img, self.transformation_matrix, self.mean_vector)
# 随机混合一批输入的numpy.ndarray图像及其标签。
class MixUp(py_transforms.PyTensorOperation):
# 定义MixUp类参数image, label, batch_size, alpha, is_single
@check_mix_up
def __init__(self, batch_size, alpha, is_single=True):
# 初始化image和label
self.image = 0
self.label = 0
self.is_first = True
self.batch_size = batch_size
self.alpha = alpha
self.is_single = is_single
self.random = False
# 返回mix_up_single函数
def __call__(self, image, label):
# 如果is_single为True则返回mix_up_single函数
if self.is_single:
return util.mix_up_single(self.batch_size, image, label, self.alpha)
# 否则返回mix_up_muti函数
return util.mix_up_muti(self, self.batch_size, image, label, self.alpha)
# 根据均值和标准差对输入图像进行归一化
class Normalize(py_transforms.PyTensorOperation):
@check_normalize_py
def __init__(self, mean, std):
'''
初始化函数用于初始化模型参数
:param mean: 均值
:param std: 标准差
'''
#设置均值
self.mean = mean
#设置标准差
self.std = std
self.random = False
def __call__(self, img):
#返回一个normalize对象
return util.normalize(img, self.mean, self.std)
# 根据均值和标准差对输入图像进行归一化,然后填充一个全零的额外通道
class NormalizePad(py_transforms.PyTensorOperation):
# 初始化NormalizePad类参数mean, std, dtype
@check_normalizepad_py
def __init__(self, mean, std, dtype="float32"):
self.mean = mean
self.std = std
self.dtype = dtype
self.random = False
# 定义__call__函数用于调用normalize函数
def __call__(self, img):
# 调用util.normalize函数将img参数转换为输入的格式并且设置pad_channel为Truedtype为self.dtype
return util.normalize(img, self.mean, self.std, pad_channel=True, dtype=self.dtype)
# 填充图像
class Pad(py_transforms.PyTensorOperation):
@check_pad
def __init__(self, padding, fill_value=0, padding_mode=Border.CONSTANT):
# 初始化NormalizePad类参数padding, fill_value, padding_mode
# 解析padding
parse_padding(padding)
self.padding = padding
self.fill_value = fill_value
self.padding_mode = DE_PY_BORDER_TYPE[padding_mode]
self.random = False
# 定义__call__方法用于处理图像
def __call__(self, img):
# 调用util.pad函数处理图像
return util.pad(img, self.padding, self.fill_value, self.padding_mode)
# 对输入图像应用随机仿射变换
class RandomAffine(py_transforms.PyTensorOperation):
# 根据参数degrees,translate,scale,shear,resample,fill_value初始化RandomAffine类
@check_random_affine
def __init__(self, degrees, translate=None, scale=None, shear=None, resample=Inter.NEAREST, fill_value=0):
# 如果shear不为空则将shear转换为数组
if shear is not None:
if isinstance(shear, numbers.Number):
shear = (-1 * shear, shear)
else:
if len(shear) == 2:
shear = [shear[0], shear[1], 0., 0.]
elif len(shear) == 4:
shear = [s for s in shear]
# 如果degrees不为空则将degrees转换为数组
if isinstance(degrees, numbers.Number):
degrees = (-degrees, degrees)
self.degrees = degrees
self.translate = translate
self.scale_ranges = scale
self.shear = shear
self.resample = DE_PY_INTER_MODE[resample]
self.fill_value = fill_value
# 返回一个随机变换后的图像
def __call__(self, img):
# 调用util.random_affine函数参数img,self.degrees,self.translate,self.scale_ranges,self.shear,self.resample,self.fill_value
return util.random_affine(img,
self.degrees,
self.translate,
self.scale_ranges,
self.shear,
self.resample,
self.fill_value)
# 随机调整输入图像的颜色
class RandomColor(py_transforms.PyTensorOperation):
# 定义一个RandomColor类参数为degrees用于控制随机颜色的范围
@check_positive_degrees
def __init__(self, degrees=(0.1, 1.9)):
self.degrees = degrees
def __call__(self, img):
# 调用py_transforms.PyTensorOperation的__call__方法传入img参数
return util.random_color(img, self.degrees)
class RandomColorAdjust(py_transforms.PyTensorOperation):
# 定义一个RandomColorAdjust类接收三个参数brightness、contrast、saturation和hue
@check_random_color_adjust
def __init__(self, brightness=(1, 1), contrast=(1, 1), saturation=(1, 1), hue=(0, 0)):
self.brightness = brightness
self.contrast = contrast
self.saturation = saturation
self.hue = hue
def __call__(self, img):
# 调用PyTensorOperation类的__call__方法传入img参数返回一个改变图像的图像
return util.random_color_adjust(img, self.brightness, self.contrast, self.saturation, self.hue)
# 对输入图像进行随机区域的裁剪
class RandomCrop(py_transforms.PyTensorOperation):
# 初始化RandomCrop类参数size为裁剪大小padding为边界pad_if_needed为是否需要裁剪fill_value为填充值padding_mode为填充模式
@check_random_crop
def __init__(self, size, padding=None, pad_if_needed=False, fill_value=0, padding_mode=Border.CONSTANT):
# 如果padding为空则padding为(0, 0, 0, 0)
if padding is None:
padding = (0, 0, 0, 0)
else:
# 将padding转换为元组
padding = parse_padding(padding)
self.size = size
self.padding = padding
self.pad_if_needed = pad_if_neededm
self.fill_value = fill_value
self.padding_mode = DE_PY_BORDER_TYPE[padding_mode]
# 定义__call__方法用于调用RandomCrop类的构造函数
def __call__(self, img):
# 调用util.random_crop函数输入imgself.sizeself.paddingself.pad_if_neededself.fill_valueself.padding_mode
return util.random_crop(img, self.size, self.padding, self.pad_if_needed,
self.fill_value, self.padding_mode)
# 按照指定的概率擦除输入numpy.ndarray图像上随机矩形区域内的像素
class RandomErasing(py_transforms.PyTensorOperation):
# 定义一个RandomErasing类参数prob, scale, ratio, value, inplace, max_attempts
@check_random_erasing
def __init__(self, prob=0.5, scale=(0.02, 0.33), ratio=(0.3, 3.3), value=0, inplace=False, max_attempts=10):
self.prob = prob
self.scale = scale
self.ratio = ratio
self.value = value
self.inplace = inplace
self.max_attempts = max_attempts
def __call__(self, np_img):
# 调用父类的__call__函数
bounded = True
# 如果概率大于随机的,则进行擦除
if self.prob > random.random():
# 获取擦除参数
i, j, erase_h, erase_w, erase_value = util.get_erase_params(np_img, self.scale, self.ratio,
self.value, bounded, self.max_attempts)
# 进行擦除
return util.erase(np_img, i, j, erase_h, erase_w, erase_value, self.inplace)
return np_img
# 按照指定的概率将输入PIL图像转换为灰度图
class RandomGrayscale(py_transforms.PyTensorOperation):
# 定义RandomGrayscale类参数prob
@check_prob
def __init__(self, prob=0.1):
self.prob = prob
# 定义操作
def __call__(self, img):
# 如果图像类型为L则输出通道数为1
if img.mode == 'L':
num_output_channels = 1
else:
# 否则输出通道数为3
num_output_channels = 3
# 如果概率大于随机数,则进行灰度变换
if self.prob > random.random():
return util.grayscale(img, num_output_channels=num_output_channels)
# 否则返回原图
return img
# 对输入图像按给定的概率进行水平随机翻转
class RandomHorizontalFlip(py_transforms.PyTensorOperation):
# 初始化函数接收一个prob参数默认为0.5
@check_prob
def __init__(self, prob=0.5):
self.prob = prob
# 定义函数,返回一个随机水平翻转的图像
def __call__(self, img):
# 返回一个随机水平翻转的图像并将prob参数赋值给img
return util.random_horizontal_flip(img, self.prob)
# 将AlexNet PCA的噪声添加到图像中
class RandomLighting(py_transforms.PyTensorOperation):
# 定义一个RandomLighting类
@check_alpha
def __init__(self, alpha=0.05):
self.alpha = alpha
def __call__(self, img):
# 调用随机亮度函数
return util.random_lighting(img, self.alpha)
# 按照指定的概率对输入PIL图像进行透视变换
class RandomPerspective(py_transforms.PyTensorOperation):
# 定义RandomPerspective类接收一个参数distortion_scale用于控制随机投影的概率prob用于控制随机投影的插值方式
@check_random_perspective
def __init__(self, distortion_scale=0.5, prob=0.5, interpolation=Inter.BICUBIC):
self.distortion_scale = distortion_scale
self.prob = prob
# 将interpolation转换为插值方式
self.interpolation = DE_PY_INTER_MODE[interpolation]
def __call__(self, img):
# 定义__call__方法接收一个参数img用于处理图像
if not is_pil(img):
raise ValueError("Input image should be a Pillow image.")
# 如果prob大于随机生成的值则获取随机投影的起点和终点
if self.prob > random.random():
start_points, end_points = util.get_perspective_params(
img, self.distortion_scale)
# 返回投影后的图像
return util.perspective(img, start_points, end_points, self.interpolation)
# 如果prob小于随机生成的值则返回原图
return img
# 对输入图像进行随机裁剪,并使用指定的 mindspore.dataset.vision.Inter 插值方式去调整为指定的尺寸大小
class RandomResizedCrop(py_transforms.PyTensorOperation):
# 定义RandomResizedCrop类用来对图像进行随机裁剪
@check_random_resize_crop
def __init__(self, size, scale=(0.08, 1.0), ratio=(3. / 4., 4. / 3.),
interpolation=Inter.BILINEAR, max_attempts=10):
# 初始化RandomResizedCrop类设置裁剪尺寸裁剪比例裁剪方式最大尝试次数
self.size = size
self.scale = scale
self.ratio = ratio
self.interpolation = DE_PY_INTER_MODE[interpolation]
self.max_attempts = max_attempts
def __call__(self, img):
# 返回随机裁剪后的图像
return util.random_resize_crop(img, self.size, self.scale, self.ratio,
self.interpolation, self.max_attempts)
# 在指定的角度范围内,随机旋转输入图像
class RandomRotation(py_transforms.PyTensorOperation):
@check_random_rotation
# 定义RandomRotation类参数degrees, resample, expand, center, fill_value
def __init__(self, degrees, resample=Inter.NEAREST, expand=False, center=None, fill_value=0):
self.degrees = degrees
self.resample = DE_PY_INTER_MODE[resample]
self.expand = expand
self.center = center
self.fill_value = fill_value
def __call__(self, img):
# 返回随机旋转图像
return util.random_rotation(img, self.degrees, self.resample, self.expand, self.center, self.fill_value)
# 在固定或随机的范围调整输入图像的锐度
class RandomSharpness(py_transforms.PyTensorOperation):
# 定义RandomSharpness类参数为degrees表示角度
@check_positive_degrees
def __init__(self, degrees=(0.1, 1.9)):
self.degrees = degrees
# 定义__call__函数
def __call__(self, img):
# 调用util.random_sharpness函数参数为img和self.degrees
return util.random_sharpness(img, self.degrees)
class RandomVerticalFlip(py_transforms.PyTensorOperation):
# 定义RandomVerticalFlip类参数为prob
@check_prob
def __init__(self, prob=0.5):
self.prob = prob
def __call__(self, img):
# 返回随机翻转图像
return util.random_vertical_flip(img, self.prob)
# 对输入图像使用给定的 mindspore.dataset.vision.Inter 插值方式去调整为给定的尺寸大小
class Resize(py_transforms.PyTensorOperation):
# 定义Resize类接收size和interpolation参数
@check_resize_interpolation
def __init__(self, size, interpolation=Inter.BILINEAR):
self.size = size
self.interpolation = DE_PY_INTER_MODE[interpolation]
self.random = False
def __call__(self, img):
# 返回resize函数传入图像和size和interpolation参数
return util.resize(img, self.size, self.interpolation)
# 将输入的RGB格式numpy.ndarray图像转换为BGR格式
class RgbToBgr(py_transforms.PyTensorOperation):
@check_rgb_to_bgr
def __init__(self, is_hwc=False):
self.is_hwc = is_hwc
self.random = False
def __call__(self, rgb_imgs):
return util.rgb_to_bgrs(rgb_imgs, self.is_hwc)
# 将输入的RGB格式numpy.ndarray图像转换为HSV格式
class RgbToHsv(py_transforms.PyTensorOperation):
@check_rgb_to_hsv
def __init__(self, is_hwc=False):
self.is_hwc = is_hwc
self.random = False
def __call__(self, rgb_imgs):
return util.rgb_to_hsvs(rgb_imgs, self.is_hwc)
# 在输入PIL图像的中心与四个角处分别裁剪指定尺寸大小的子图并将其翻转图一并返回
class TenCrop(py_transforms.PyTensorOperation):
# 定义TenCrop类接收一个size参数use_vertical_flip参数
@check_ten_crop
def __init__(self, size, use_vertical_flip=False):
# 如果size参数是int类型则将size转换为元组否则直接赋值
if isinstance(size, int):
size = (size, size)
self.size = size
self.use_vertical_flip = use_vertical_flip
# 将random设置为False
self.random = False
# 定义__call__方法接收一个img参数
def __call__(self, img):
# 调用util.ten_crop函数传入img和self.sizeself.use_vertical_flip
return util.ten_crop(img, self.size, self.use_vertical_flip)
# 将已解码的numpy.ndarray图像转换为PIL图像
class ToPIL(py_transforms.PyTensorOperation):
def __init__(self):
self.random = False
def __call__(self, img):
return util.to_pil(img)
# 将输入PIL图像或numpy.ndarray图像转换为指定类型的numpy.ndarray图像
# 图像的像素值范围将从[0, 255]放缩为[0.0, 1.0]shape将从<H, W, C>调整为<C, H, W>
class ToTensor(py_transforms.PyTensorOperation):
# 初始化ToTensor类输入参数output_type为np.float32
def __init__(self, output_type=np.float32):
self.output_type = output_type
self.random = False
# 定义__call__方法输入参数img返回util.to_tensor函数的输出
def __call__(self, img):
return util.to_tensor(img, self.output_type)
# 将输入转换为指定的MindSpore数据类型或NumPy数据类型
class ToType(py_transforms.PyTensorOperation):
# 定义ToType类设置output_type参数
def __init__(self, output_type):
self.output_type = output_type
# 定义random变量默认为False
self.random = False
# 定义__call__方法将img参数转换为output_type类型
def __call__(self, img):
return util.to_type(img, self.output_type)
# 从指定序列中均匀采样一批数据处理操作,并按顺序随机执行,即采样出的操作也可能不被执行
class UniformAugment(py_transforms.PyTensorOperation):
'''
使用随机操作增强图像
'''
@check_uniform_augment_py
def __init__(self, transforms, num_ops=2):
'''
:param transforms: 增强函数列表
:param num_ops: 增强次数
'''
self.transforms = transforms
self.num_ops = num_ops
self.random = False
def __call__(self, img):
'''
:param img: 图像
:return: 增强后的图像
'''
return util.uniform_augment(img, self.transforms.copy(), self.num_ops)
def not_random(func):
def not_random(function):
"""
Specify the function as "not random", i.e., it produces deterministic result.
A Python function can only be cached after it is specified as "not random".
"""
func.random = False
return func
function.random = False
return function
class PyTensorOperation:
"""
Base Python Tensor Operations class
"""
def to_json(self):
"""
Base to_json for Python tensor operations class
"""
json_obj = {}
json_trans = {}
if "transforms" in self.__dict__.keys():
# operations which have transforms as input, need to call _to_json() for each transform to serialize
json_list = []
for transform in self.transforms:
json_list.append(json.loads(transform.to_json()))
json_trans["transforms"] = json_list
self.__dict__.pop("transforms")
if "output_type" in self.__dict__.keys():
json_trans["output_type"] = np.dtype(
self.__dict__["output_type"]).name
self.__dict__.pop("output_type")
json_obj["tensor_op_params"] = self.__dict__
# append transforms to the tensor_op_params of the operation
json_obj["tensor_op_params"].update(json_trans)
json_obj["tensor_op_name"] = self.__class__.__name__
json_obj["python_module"] = self.__class__.__module__
return json.dumps(json_obj)
@classmethod
def from_json(cls, json_string):
"""
Base from_json for Python tensor operations class
"""
json_obj = json.loads(json_string)
new_op = cls.__new__(cls)
new_op.__dict__ = json_obj
if "transforms" in json_obj.keys():
# operations which have transforms as input, need to call _from_json() for each transform to deseriallize
transforms = []
for json_op in json_obj["transforms"]:
transforms.append(getattr(
sys.modules[json_op["python_module"]], json_op["tensor_op_name"]).from_json(
json.dumps(json_op["tensor_op_params"])))
new_op.transforms = transforms
if "output_type" in json_obj.keys():
output_type = np.dtype(json_obj["output_type"])
new_op.output_type = output_type
return new_op
class OneHotOp(PyTensorOperation):
# 定义OneHotOp类参数num_classes, smoothing_rate
@check_one_hot_op
def __init__(self, num_classes, smoothing_rate=0.0):
# 初始化num_classes和smoothing_rate
self.num_classes = num_classes
self.smoothing_rate = smoothing_rate
self.random = False
def __call__(self, label):
# 返回one_hot_encoding函数的结果
return util.one_hot_encoding(label, self.num_classes, self.smoothing_rate)
# 将多个数据增强操作组合使用
class Compose(PyTensorOperation):
@check_compose_list
def __init__(self, transforms):
'''
参数
transformsPyTensorOperation对象列表
'''
self.transforms = transforms
if all(hasattr(transform, "random") and not transform.random for transform in self.transforms):
self.random = False
@check_compose_call
def __call__(self, *args):
# 返回组合后的PyTensorOperation对象
return util.compose(self.transforms, *args)
@staticmethod
def reduce(operations):
# import nn and ops locally for type check
from mindspore import nn, ops
# 检查输入的运算是否包含像mindspore.nn或mindspore.ops的运算
for item in operations:
if isinstance(item, (nn.Cell, ops.Primitive)):
raise ValueError("Input operations should not contain network computing operator like in "
"mindspore.nn or mindspore.ops, got operation:", str(item))
# 检查输入的运算是否为空
if len(operations) == 1:
# 检查输入的运算是否为张量运算,如果是返回运算
if str(operations).find("c_transform") >= 0 or isinstance(operations[0], TensorOperation):
return operations
# 如果不是返回util.FuncWrapper的运算结果
return [util.FuncWrapper(operations[0])]
# 重新设置数值
new_ops, start_ind, end_ind = [], 0, 0
# 循环遍历运算
for i, op in enumerate(operations):
# 检查当前运算为 Compose
if str(op).find("c_transform") >= 0:
# 为new_ops添加新的数值
if start_ind!= end_ind:
new_ops.append(Compose(operations[start_ind:end_ind]))
# 添加当前运算符
new_ops.append(op)
start_ind, end_ind = i + 1, i + 1
# 检查当前运算为 Compose
else:
# 让end_ind 加一
end_ind += 1
# 额外检查以防最后一个运算为Python运算
if start_ind!= end_ind:
new_ops.append(Compose(operations[start_ind:end_ind]))
return new_ops
# 指定一组数据增强处理及其被应用的概率,在运算时按概率随机应用其中的增强处理
class RandomApply(PyTensorOperation):
# 定义RandomApply类参数transforms和prob概率
@check_random_apply
def __init__(self, transforms, prob=0.5):
self.prob = prob
self.transforms = transforms
def __call__(self, img):
# 返回随机应用于img的结果
return util.random_apply(img, self.transforms, self.prob)
# 在一组数据增强中随机选择部分增强处理进行应用
class RandomChoice(PyTensorOperation):
# 定义RandomChoice类继承PyTensorOperation类
@check_transforms_list
def __init__(self, transforms):
# 初始化transforms参数
self.transforms = transforms
def __call__(self, img):
# 调用PyTensorOperation类的__call__方法传入img参数
return util.random_choice(img, self.transforms)
# 给一个数据增强的列表,随机打乱数据增强处理的顺序
class RandomOrder(PyTensorOperation):
# 定义一个RandomOrder类用于接收一个可调用的transforms列表
@check_transforms_list
def __init__(self, transforms):
self.transforms = transforms
def __call__(self, img):
# 调用PyTensorOperation的__call__方法传入img参数并将返回值赋值给img
return util.random_order(img, self.transforms)