release code
This commit is contained in:
1
Dassl.ProGrad.pytorch/dassl/data/transforms/__init__.py
Normal file
1
Dassl.ProGrad.pytorch/dassl/data/transforms/__init__.py
Normal file
@@ -0,0 +1 @@
|
||||
from .transforms import build_transform
|
||||
273
Dassl.ProGrad.pytorch/dassl/data/transforms/autoaugment.py
Normal file
273
Dassl.ProGrad.pytorch/dassl/data/transforms/autoaugment.py
Normal file
@@ -0,0 +1,273 @@
|
||||
"""
|
||||
Source: https://github.com/DeepVoltaire/AutoAugment
|
||||
"""
|
||||
import numpy as np
|
||||
import random
|
||||
from PIL import Image, ImageOps, ImageEnhance
|
||||
|
||||
|
||||
class ImageNetPolicy:
|
||||
"""Randomly choose one of the best 24 Sub-policies on ImageNet.
|
||||
|
||||
Example:
|
||||
>>> policy = ImageNetPolicy()
|
||||
>>> transformed = policy(image)
|
||||
|
||||
Example as a PyTorch Transform:
|
||||
>>> transform=transforms.Compose([
|
||||
>>> transforms.Resize(256),
|
||||
>>> ImageNetPolicy(),
|
||||
>>> transforms.ToTensor()])
|
||||
"""
|
||||
|
||||
def __init__(self, fillcolor=(128, 128, 128)):
|
||||
self.policies = [
|
||||
SubPolicy(0.4, "posterize", 8, 0.6, "rotate", 9, fillcolor),
|
||||
SubPolicy(0.6, "solarize", 5, 0.6, "autocontrast", 5, fillcolor),
|
||||
SubPolicy(0.8, "equalize", 8, 0.6, "equalize", 3, fillcolor),
|
||||
SubPolicy(0.6, "posterize", 7, 0.6, "posterize", 6, fillcolor),
|
||||
SubPolicy(0.4, "equalize", 7, 0.2, "solarize", 4, fillcolor),
|
||||
SubPolicy(0.4, "equalize", 4, 0.8, "rotate", 8, fillcolor),
|
||||
SubPolicy(0.6, "solarize", 3, 0.6, "equalize", 7, fillcolor),
|
||||
SubPolicy(0.8, "posterize", 5, 1.0, "equalize", 2, fillcolor),
|
||||
SubPolicy(0.2, "rotate", 3, 0.6, "solarize", 8, fillcolor),
|
||||
SubPolicy(0.6, "equalize", 8, 0.4, "posterize", 6, fillcolor),
|
||||
SubPolicy(0.8, "rotate", 8, 0.4, "color", 0, fillcolor),
|
||||
SubPolicy(0.4, "rotate", 9, 0.6, "equalize", 2, fillcolor),
|
||||
SubPolicy(0.0, "equalize", 7, 0.8, "equalize", 8, fillcolor),
|
||||
SubPolicy(0.6, "invert", 4, 1.0, "equalize", 8, fillcolor),
|
||||
SubPolicy(0.6, "color", 4, 1.0, "contrast", 8, fillcolor),
|
||||
SubPolicy(0.8, "rotate", 8, 1.0, "color", 2, fillcolor),
|
||||
SubPolicy(0.8, "color", 8, 0.8, "solarize", 7, fillcolor),
|
||||
SubPolicy(0.4, "sharpness", 7, 0.6, "invert", 8, fillcolor),
|
||||
SubPolicy(0.6, "shearX", 5, 1.0, "equalize", 9, fillcolor),
|
||||
SubPolicy(0.4, "color", 0, 0.6, "equalize", 3, fillcolor),
|
||||
SubPolicy(0.4, "equalize", 7, 0.2, "solarize", 4, fillcolor),
|
||||
SubPolicy(0.6, "solarize", 5, 0.6, "autocontrast", 5, fillcolor),
|
||||
SubPolicy(0.6, "invert", 4, 1.0, "equalize", 8, fillcolor),
|
||||
SubPolicy(0.6, "color", 4, 1.0, "contrast", 8, fillcolor),
|
||||
SubPolicy(0.8, "equalize", 8, 0.6, "equalize", 3, fillcolor),
|
||||
]
|
||||
|
||||
def __call__(self, img):
|
||||
policy_idx = random.randint(0, len(self.policies) - 1)
|
||||
return self.policies[policy_idx](img)
|
||||
|
||||
def __repr__(self):
|
||||
return "AutoAugment ImageNet Policy"
|
||||
|
||||
|
||||
class CIFAR10Policy:
|
||||
"""Randomly choose one of the best 25 Sub-policies on CIFAR10.
|
||||
|
||||
Example:
|
||||
>>> policy = CIFAR10Policy()
|
||||
>>> transformed = policy(image)
|
||||
|
||||
Example as a PyTorch Transform:
|
||||
>>> transform=transforms.Compose([
|
||||
>>> transforms.Resize(256),
|
||||
>>> CIFAR10Policy(),
|
||||
>>> transforms.ToTensor()])
|
||||
"""
|
||||
|
||||
def __init__(self, fillcolor=(128, 128, 128)):
|
||||
self.policies = [
|
||||
SubPolicy(0.1, "invert", 7, 0.2, "contrast", 6, fillcolor),
|
||||
SubPolicy(0.7, "rotate", 2, 0.3, "translateX", 9, fillcolor),
|
||||
SubPolicy(0.8, "sharpness", 1, 0.9, "sharpness", 3, fillcolor),
|
||||
SubPolicy(0.5, "shearY", 8, 0.7, "translateY", 9, fillcolor),
|
||||
SubPolicy(0.5, "autocontrast", 8, 0.9, "equalize", 2, fillcolor),
|
||||
SubPolicy(0.2, "shearY", 7, 0.3, "posterize", 7, fillcolor),
|
||||
SubPolicy(0.4, "color", 3, 0.6, "brightness", 7, fillcolor),
|
||||
SubPolicy(0.3, "sharpness", 9, 0.7, "brightness", 9, fillcolor),
|
||||
SubPolicy(0.6, "equalize", 5, 0.5, "equalize", 1, fillcolor),
|
||||
SubPolicy(0.6, "contrast", 7, 0.6, "sharpness", 5, fillcolor),
|
||||
SubPolicy(0.7, "color", 7, 0.5, "translateX", 8, fillcolor),
|
||||
SubPolicy(0.3, "equalize", 7, 0.4, "autocontrast", 8, fillcolor),
|
||||
SubPolicy(0.4, "translateY", 3, 0.2, "sharpness", 6, fillcolor),
|
||||
SubPolicy(0.9, "brightness", 6, 0.2, "color", 8, fillcolor),
|
||||
SubPolicy(0.5, "solarize", 2, 0.0, "invert", 3, fillcolor),
|
||||
SubPolicy(0.2, "equalize", 0, 0.6, "autocontrast", 0, fillcolor),
|
||||
SubPolicy(0.2, "equalize", 8, 0.6, "equalize", 4, fillcolor),
|
||||
SubPolicy(0.9, "color", 9, 0.6, "equalize", 6, fillcolor),
|
||||
SubPolicy(0.8, "autocontrast", 4, 0.2, "solarize", 8, fillcolor),
|
||||
SubPolicy(0.1, "brightness", 3, 0.7, "color", 0, fillcolor),
|
||||
SubPolicy(0.4, "solarize", 5, 0.9, "autocontrast", 3, fillcolor),
|
||||
SubPolicy(0.9, "translateY", 9, 0.7, "translateY", 9, fillcolor),
|
||||
SubPolicy(0.9, "autocontrast", 2, 0.8, "solarize", 3, fillcolor),
|
||||
SubPolicy(0.8, "equalize", 8, 0.1, "invert", 3, fillcolor),
|
||||
SubPolicy(0.7, "translateY", 9, 0.9, "autocontrast", 1, fillcolor),
|
||||
]
|
||||
|
||||
def __call__(self, img):
|
||||
policy_idx = random.randint(0, len(self.policies) - 1)
|
||||
return self.policies[policy_idx](img)
|
||||
|
||||
def __repr__(self):
|
||||
return "AutoAugment CIFAR10 Policy"
|
||||
|
||||
|
||||
class SVHNPolicy:
|
||||
"""Randomly choose one of the best 25 Sub-policies on SVHN.
|
||||
|
||||
Example:
|
||||
>>> policy = SVHNPolicy()
|
||||
>>> transformed = policy(image)
|
||||
|
||||
Example as a PyTorch Transform:
|
||||
>>> transform=transforms.Compose([
|
||||
>>> transforms.Resize(256),
|
||||
>>> SVHNPolicy(),
|
||||
>>> transforms.ToTensor()])
|
||||
"""
|
||||
|
||||
def __init__(self, fillcolor=(128, 128, 128)):
|
||||
self.policies = [
|
||||
SubPolicy(0.9, "shearX", 4, 0.2, "invert", 3, fillcolor),
|
||||
SubPolicy(0.9, "shearY", 8, 0.7, "invert", 5, fillcolor),
|
||||
SubPolicy(0.6, "equalize", 5, 0.6, "solarize", 6, fillcolor),
|
||||
SubPolicy(0.9, "invert", 3, 0.6, "equalize", 3, fillcolor),
|
||||
SubPolicy(0.6, "equalize", 1, 0.9, "rotate", 3, fillcolor),
|
||||
SubPolicy(0.9, "shearX", 4, 0.8, "autocontrast", 3, fillcolor),
|
||||
SubPolicy(0.9, "shearY", 8, 0.4, "invert", 5, fillcolor),
|
||||
SubPolicy(0.9, "shearY", 5, 0.2, "solarize", 6, fillcolor),
|
||||
SubPolicy(0.9, "invert", 6, 0.8, "autocontrast", 1, fillcolor),
|
||||
SubPolicy(0.6, "equalize", 3, 0.9, "rotate", 3, fillcolor),
|
||||
SubPolicy(0.9, "shearX", 4, 0.3, "solarize", 3, fillcolor),
|
||||
SubPolicy(0.8, "shearY", 8, 0.7, "invert", 4, fillcolor),
|
||||
SubPolicy(0.9, "equalize", 5, 0.6, "translateY", 6, fillcolor),
|
||||
SubPolicy(0.9, "invert", 4, 0.6, "equalize", 7, fillcolor),
|
||||
SubPolicy(0.3, "contrast", 3, 0.8, "rotate", 4, fillcolor),
|
||||
SubPolicy(0.8, "invert", 5, 0.0, "translateY", 2, fillcolor),
|
||||
SubPolicy(0.7, "shearY", 6, 0.4, "solarize", 8, fillcolor),
|
||||
SubPolicy(0.6, "invert", 4, 0.8, "rotate", 4, fillcolor),
|
||||
SubPolicy(0.3, "shearY", 7, 0.9, "translateX", 3, fillcolor),
|
||||
SubPolicy(0.1, "shearX", 6, 0.6, "invert", 5, fillcolor),
|
||||
SubPolicy(0.7, "solarize", 2, 0.6, "translateY", 7, fillcolor),
|
||||
SubPolicy(0.8, "shearY", 4, 0.8, "invert", 8, fillcolor),
|
||||
SubPolicy(0.7, "shearX", 9, 0.8, "translateY", 3, fillcolor),
|
||||
SubPolicy(0.8, "shearY", 5, 0.7, "autocontrast", 3, fillcolor),
|
||||
SubPolicy(0.7, "shearX", 2, 0.1, "invert", 5, fillcolor),
|
||||
]
|
||||
|
||||
def __call__(self, img):
|
||||
policy_idx = random.randint(0, len(self.policies) - 1)
|
||||
return self.policies[policy_idx](img)
|
||||
|
||||
def __repr__(self):
|
||||
return "AutoAugment SVHN Policy"
|
||||
|
||||
|
||||
class SubPolicy(object):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
p1,
|
||||
operation1,
|
||||
magnitude_idx1,
|
||||
p2,
|
||||
operation2,
|
||||
magnitude_idx2,
|
||||
fillcolor=(128, 128, 128),
|
||||
):
|
||||
ranges = {
|
||||
"shearX": np.linspace(0, 0.3, 10),
|
||||
"shearY": np.linspace(0, 0.3, 10),
|
||||
"translateX": np.linspace(0, 150 / 331, 10),
|
||||
"translateY": np.linspace(0, 150 / 331, 10),
|
||||
"rotate": np.linspace(0, 30, 10),
|
||||
"color": np.linspace(0.0, 0.9, 10),
|
||||
"posterize": np.round(np.linspace(8, 4, 10), 0).astype(np.int),
|
||||
"solarize": np.linspace(256, 0, 10),
|
||||
"contrast": np.linspace(0.0, 0.9, 10),
|
||||
"sharpness": np.linspace(0.0, 0.9, 10),
|
||||
"brightness": np.linspace(0.0, 0.9, 10),
|
||||
"autocontrast": [0] * 10,
|
||||
"equalize": [0] * 10,
|
||||
"invert": [0] * 10,
|
||||
}
|
||||
|
||||
# from https://stackoverflow.com/questions/5252170/specify-image-filling-color-when-rotating-in-python-with-pil-and-setting-expand
|
||||
def rotate_with_fill(img, magnitude):
|
||||
rot = img.convert("RGBA").rotate(magnitude)
|
||||
return Image.composite(
|
||||
rot, Image.new("RGBA", rot.size, (128, ) * 4), rot
|
||||
).convert(img.mode)
|
||||
|
||||
func = {
|
||||
"shearX":
|
||||
lambda img, magnitude: img.transform(
|
||||
img.size,
|
||||
Image.AFFINE,
|
||||
(1, magnitude * random.choice([-1, 1]), 0, 0, 1, 0),
|
||||
Image.BICUBIC,
|
||||
fillcolor=fillcolor,
|
||||
),
|
||||
"shearY":
|
||||
lambda img, magnitude: img.transform(
|
||||
img.size,
|
||||
Image.AFFINE,
|
||||
(1, 0, 0, magnitude * random.choice([-1, 1]), 1, 0),
|
||||
Image.BICUBIC,
|
||||
fillcolor=fillcolor,
|
||||
),
|
||||
"translateX":
|
||||
lambda img, magnitude: img.transform(
|
||||
img.size,
|
||||
Image.AFFINE,
|
||||
(
|
||||
1, 0, magnitude * img.size[0] * random.choice([-1, 1]), 0,
|
||||
1, 0
|
||||
),
|
||||
fillcolor=fillcolor,
|
||||
),
|
||||
"translateY":
|
||||
lambda img, magnitude: img.transform(
|
||||
img.size,
|
||||
Image.AFFINE,
|
||||
(
|
||||
1, 0, 0, 0, 1, magnitude * img.size[1] * random.
|
||||
choice([-1, 1])
|
||||
),
|
||||
fillcolor=fillcolor,
|
||||
),
|
||||
"rotate":
|
||||
lambda img, magnitude: rotate_with_fill(img, magnitude),
|
||||
"color":
|
||||
lambda img, magnitude: ImageEnhance.Color(img).
|
||||
enhance(1 + magnitude * random.choice([-1, 1])),
|
||||
"posterize":
|
||||
lambda img, magnitude: ImageOps.posterize(img, magnitude),
|
||||
"solarize":
|
||||
lambda img, magnitude: ImageOps.solarize(img, magnitude),
|
||||
"contrast":
|
||||
lambda img, magnitude: ImageEnhance.Contrast(img).
|
||||
enhance(1 + magnitude * random.choice([-1, 1])),
|
||||
"sharpness":
|
||||
lambda img, magnitude: ImageEnhance.Sharpness(img).
|
||||
enhance(1 + magnitude * random.choice([-1, 1])),
|
||||
"brightness":
|
||||
lambda img, magnitude: ImageEnhance.Brightness(img).
|
||||
enhance(1 + magnitude * random.choice([-1, 1])),
|
||||
"autocontrast":
|
||||
lambda img, magnitude: ImageOps.autocontrast(img),
|
||||
"equalize":
|
||||
lambda img, magnitude: ImageOps.equalize(img),
|
||||
"invert":
|
||||
lambda img, magnitude: ImageOps.invert(img),
|
||||
}
|
||||
|
||||
self.p1 = p1
|
||||
self.operation1 = func[operation1]
|
||||
self.magnitude1 = ranges[operation1][magnitude_idx1]
|
||||
self.p2 = p2
|
||||
self.operation2 = func[operation2]
|
||||
self.magnitude2 = ranges[operation2][magnitude_idx2]
|
||||
|
||||
def __call__(self, img):
|
||||
if random.random() < self.p1:
|
||||
img = self.operation1(img, self.magnitude1)
|
||||
if random.random() < self.p2:
|
||||
img = self.operation2(img, self.magnitude2)
|
||||
return img
|
||||
363
Dassl.ProGrad.pytorch/dassl/data/transforms/randaugment.py
Normal file
363
Dassl.ProGrad.pytorch/dassl/data/transforms/randaugment.py
Normal file
@@ -0,0 +1,363 @@
|
||||
"""
|
||||
Credit to
|
||||
1) https://github.com/ildoonet/pytorch-randaugment
|
||||
2) https://github.com/kakaobrain/fast-autoaugment
|
||||
"""
|
||||
import numpy as np
|
||||
import random
|
||||
import PIL
|
||||
import torch
|
||||
import PIL.ImageOps
|
||||
import PIL.ImageDraw
|
||||
import PIL.ImageEnhance
|
||||
from PIL import Image
|
||||
|
||||
|
||||
def ShearX(img, v):
|
||||
assert -0.3 <= v <= 0.3
|
||||
if random.random() > 0.5:
|
||||
v = -v
|
||||
return img.transform(img.size, PIL.Image.AFFINE, (1, v, 0, 0, 1, 0))
|
||||
|
||||
|
||||
def ShearY(img, v):
|
||||
assert -0.3 <= v <= 0.3
|
||||
if random.random() > 0.5:
|
||||
v = -v
|
||||
return img.transform(img.size, PIL.Image.AFFINE, (1, 0, 0, v, 1, 0))
|
||||
|
||||
|
||||
def TranslateX(img, v):
|
||||
# [-150, 150] => percentage: [-0.45, 0.45]
|
||||
assert -0.45 <= v <= 0.45
|
||||
if random.random() > 0.5:
|
||||
v = -v
|
||||
v = v * img.size[0]
|
||||
return img.transform(img.size, PIL.Image.AFFINE, (1, 0, v, 0, 1, 0))
|
||||
|
||||
|
||||
def TranslateXabs(img, v):
|
||||
# [-150, 150] => percentage: [-0.45, 0.45]
|
||||
assert 0 <= v
|
||||
if random.random() > 0.5:
|
||||
v = -v
|
||||
return img.transform(img.size, PIL.Image.AFFINE, (1, 0, v, 0, 1, 0))
|
||||
|
||||
|
||||
def TranslateY(img, v):
|
||||
# [-150, 150] => percentage: [-0.45, 0.45]
|
||||
assert -0.45 <= v <= 0.45
|
||||
if random.random() > 0.5:
|
||||
v = -v
|
||||
v = v * img.size[1]
|
||||
return img.transform(img.size, PIL.Image.AFFINE, (1, 0, 0, 0, 1, v))
|
||||
|
||||
|
||||
def TranslateYabs(img, v):
|
||||
# [-150, 150] => percentage: [-0.45, 0.45]
|
||||
assert 0 <= v
|
||||
if random.random() > 0.5:
|
||||
v = -v
|
||||
return img.transform(img.size, PIL.Image.AFFINE, (1, 0, 0, 0, 1, v))
|
||||
|
||||
|
||||
def Rotate(img, v):
|
||||
assert -30 <= v <= 30
|
||||
if random.random() > 0.5:
|
||||
v = -v
|
||||
return img.rotate(v)
|
||||
|
||||
|
||||
def AutoContrast(img, _):
|
||||
return PIL.ImageOps.autocontrast(img)
|
||||
|
||||
|
||||
def Invert(img, _):
|
||||
return PIL.ImageOps.invert(img)
|
||||
|
||||
|
||||
def Equalize(img, _):
|
||||
return PIL.ImageOps.equalize(img)
|
||||
|
||||
|
||||
def Flip(img, _):
|
||||
return PIL.ImageOps.mirror(img)
|
||||
|
||||
|
||||
def Solarize(img, v):
|
||||
assert 0 <= v <= 256
|
||||
return PIL.ImageOps.solarize(img, v)
|
||||
|
||||
|
||||
def SolarizeAdd(img, addition=0, threshold=128):
|
||||
img_np = np.array(img).astype(np.int)
|
||||
img_np = img_np + addition
|
||||
img_np = np.clip(img_np, 0, 255)
|
||||
img_np = img_np.astype(np.uint8)
|
||||
img = Image.fromarray(img_np)
|
||||
return PIL.ImageOps.solarize(img, threshold)
|
||||
|
||||
|
||||
def Posterize(img, v):
|
||||
assert 4 <= v <= 8
|
||||
v = int(v)
|
||||
return PIL.ImageOps.posterize(img, v)
|
||||
|
||||
|
||||
def Contrast(img, v):
|
||||
assert 0.0 <= v <= 2.0
|
||||
return PIL.ImageEnhance.Contrast(img).enhance(v)
|
||||
|
||||
|
||||
def Color(img, v):
|
||||
assert 0.0 <= v <= 2.0
|
||||
return PIL.ImageEnhance.Color(img).enhance(v)
|
||||
|
||||
|
||||
def Brightness(img, v):
|
||||
assert 0.0 <= v <= 2.0
|
||||
return PIL.ImageEnhance.Brightness(img).enhance(v)
|
||||
|
||||
|
||||
def Sharpness(img, v):
|
||||
assert 0.0 <= v <= 2.0
|
||||
return PIL.ImageEnhance.Sharpness(img).enhance(v)
|
||||
|
||||
|
||||
def Cutout(img, v):
|
||||
# [0, 60] => percentage: [0, 0.2]
|
||||
assert 0.0 <= v <= 0.2
|
||||
if v <= 0.0:
|
||||
return img
|
||||
|
||||
v = v * img.size[0]
|
||||
return CutoutAbs(img, v)
|
||||
|
||||
|
||||
def CutoutAbs(img, v):
|
||||
# [0, 60] => percentage: [0, 0.2]
|
||||
# assert 0 <= v <= 20
|
||||
if v < 0:
|
||||
return img
|
||||
w, h = img.size
|
||||
x0 = np.random.uniform(w)
|
||||
y0 = np.random.uniform(h)
|
||||
|
||||
x0 = int(max(0, x0 - v/2.0))
|
||||
y0 = int(max(0, y0 - v/2.0))
|
||||
x1 = min(w, x0 + v)
|
||||
y1 = min(h, y0 + v)
|
||||
|
||||
xy = (x0, y0, x1, y1)
|
||||
color = (125, 123, 114)
|
||||
# color = (0, 0, 0)
|
||||
img = img.copy()
|
||||
PIL.ImageDraw.Draw(img).rectangle(xy, color)
|
||||
return img
|
||||
|
||||
|
||||
def SamplePairing(imgs):
|
||||
# [0, 0.4]
|
||||
def f(img1, v):
|
||||
i = np.random.choice(len(imgs))
|
||||
img2 = PIL.Image.fromarray(imgs[i])
|
||||
return PIL.Image.blend(img1, img2, v)
|
||||
|
||||
return f
|
||||
|
||||
|
||||
def Identity(img, v):
|
||||
return img
|
||||
|
||||
|
||||
class Lighting:
|
||||
"""Lighting noise (AlexNet - style PCA - based noise)."""
|
||||
|
||||
def __init__(self, alphastd, eigval, eigvec):
|
||||
self.alphastd = alphastd
|
||||
self.eigval = torch.Tensor(eigval)
|
||||
self.eigvec = torch.Tensor(eigvec)
|
||||
|
||||
def __call__(self, img):
|
||||
if self.alphastd == 0:
|
||||
return img
|
||||
|
||||
alpha = img.new().resize_(3).normal_(0, self.alphastd)
|
||||
rgb = (
|
||||
self.eigvec.type_as(img).clone().mul(
|
||||
alpha.view(1, 3).expand(3, 3)
|
||||
).mul(self.eigval.view(1, 3).expand(3, 3)).sum(1).squeeze()
|
||||
)
|
||||
|
||||
return img.add(rgb.view(3, 1, 1).expand_as(img))
|
||||
|
||||
|
||||
class CutoutDefault:
|
||||
"""
|
||||
Reference : https://github.com/quark0/darts/blob/master/cnn/utils.py
|
||||
"""
|
||||
|
||||
def __init__(self, length):
|
||||
self.length = length
|
||||
|
||||
def __call__(self, img):
|
||||
h, w = img.size(1), img.size(2)
|
||||
mask = np.ones((h, w), np.float32)
|
||||
y = np.random.randint(h)
|
||||
x = np.random.randint(w)
|
||||
|
||||
y1 = np.clip(y - self.length // 2, 0, h)
|
||||
y2 = np.clip(y + self.length // 2, 0, h)
|
||||
x1 = np.clip(x - self.length // 2, 0, w)
|
||||
x2 = np.clip(x + self.length // 2, 0, w)
|
||||
|
||||
mask[y1:y2, x1:x2] = 0.0
|
||||
mask = torch.from_numpy(mask)
|
||||
mask = mask.expand_as(img)
|
||||
img *= mask
|
||||
return img
|
||||
|
||||
|
||||
def randaugment_list():
|
||||
# 16 oeprations and their ranges
|
||||
# https://github.com/google-research/uda/blob/master/image/randaugment/policies.py#L57
|
||||
# augs = [
|
||||
# (Identity, 0., 1.0),
|
||||
# (ShearX, 0., 0.3), # 0
|
||||
# (ShearY, 0., 0.3), # 1
|
||||
# (TranslateX, 0., 0.33), # 2
|
||||
# (TranslateY, 0., 0.33), # 3
|
||||
# (Rotate, 0, 30), # 4
|
||||
# (AutoContrast, 0, 1), # 5
|
||||
# (Invert, 0, 1), # 6
|
||||
# (Equalize, 0, 1), # 7
|
||||
# (Solarize, 0, 110), # 8
|
||||
# (Posterize, 4, 8), # 9
|
||||
# # (Contrast, 0.1, 1.9), # 10
|
||||
# (Color, 0.1, 1.9), # 11
|
||||
# (Brightness, 0.1, 1.9), # 12
|
||||
# (Sharpness, 0.1, 1.9), # 13
|
||||
# # (Cutout, 0, 0.2), # 14
|
||||
# # (SamplePairing(imgs), 0, 0.4) # 15
|
||||
# ]
|
||||
|
||||
# https://github.com/tensorflow/tpu/blob/8462d083dd89489a79e3200bcc8d4063bf362186/models/official/efficientnet/autoaugment.py#L505
|
||||
augs = [
|
||||
(AutoContrast, 0, 1),
|
||||
(Equalize, 0, 1),
|
||||
(Invert, 0, 1),
|
||||
(Rotate, 0, 30),
|
||||
(Posterize, 4, 8),
|
||||
(Solarize, 0, 256),
|
||||
(SolarizeAdd, 0, 110),
|
||||
(Color, 0.1, 1.9),
|
||||
(Contrast, 0.1, 1.9),
|
||||
(Brightness, 0.1, 1.9),
|
||||
(Sharpness, 0.1, 1.9),
|
||||
(ShearX, 0.0, 0.3),
|
||||
(ShearY, 0.0, 0.3),
|
||||
(CutoutAbs, 0, 40),
|
||||
(TranslateXabs, 0.0, 100),
|
||||
(TranslateYabs, 0.0, 100),
|
||||
]
|
||||
|
||||
return augs
|
||||
|
||||
|
||||
def randaugment_list2():
|
||||
augs = [
|
||||
(AutoContrast, 0, 1),
|
||||
(Brightness, 0.1, 1.9),
|
||||
(Color, 0.1, 1.9),
|
||||
(Contrast, 0.1, 1.9),
|
||||
(Equalize, 0, 1),
|
||||
(Identity, 0, 1),
|
||||
(Invert, 0, 1),
|
||||
(Posterize, 4, 8),
|
||||
(Rotate, -30, 30),
|
||||
(Sharpness, 0.1, 1.9),
|
||||
(ShearX, -0.3, 0.3),
|
||||
(ShearY, -0.3, 0.3),
|
||||
(Solarize, 0, 256),
|
||||
(TranslateX, -0.3, 0.3),
|
||||
(TranslateY, -0.3, 0.3),
|
||||
]
|
||||
|
||||
return augs
|
||||
|
||||
|
||||
def fixmatch_list():
|
||||
# https://arxiv.org/abs/2001.07685
|
||||
augs = [
|
||||
(AutoContrast, 0, 1),
|
||||
(Brightness, 0.05, 0.95),
|
||||
(Color, 0.05, 0.95),
|
||||
(Contrast, 0.05, 0.95),
|
||||
(Equalize, 0, 1),
|
||||
(Identity, 0, 1),
|
||||
(Posterize, 4, 8),
|
||||
(Rotate, -30, 30),
|
||||
(Sharpness, 0.05, 0.95),
|
||||
(ShearX, -0.3, 0.3),
|
||||
(ShearY, -0.3, 0.3),
|
||||
(Solarize, 0, 256),
|
||||
(TranslateX, -0.3, 0.3),
|
||||
(TranslateY, -0.3, 0.3),
|
||||
]
|
||||
|
||||
return augs
|
||||
|
||||
|
||||
class RandAugment:
|
||||
|
||||
def __init__(self, n=2, m=10):
|
||||
assert 0 <= m <= 30
|
||||
self.n = n
|
||||
self.m = m
|
||||
self.augment_list = randaugment_list()
|
||||
|
||||
def __call__(self, img):
|
||||
ops = random.choices(self.augment_list, k=self.n)
|
||||
|
||||
for op, minval, maxval in ops:
|
||||
val = (self.m / 30) * (maxval-minval) + minval
|
||||
img = op(img, val)
|
||||
|
||||
return img
|
||||
|
||||
|
||||
class RandAugment2:
|
||||
|
||||
def __init__(self, n=2, p=0.6):
|
||||
self.n = n
|
||||
self.p = p
|
||||
self.augment_list = randaugment_list2()
|
||||
|
||||
def __call__(self, img):
|
||||
ops = random.choices(self.augment_list, k=self.n)
|
||||
|
||||
for op, minval, maxval in ops:
|
||||
if random.random() > self.p:
|
||||
continue
|
||||
m = random.random()
|
||||
val = m * (maxval-minval) + minval
|
||||
img = op(img, val)
|
||||
|
||||
return img
|
||||
|
||||
|
||||
class RandAugmentFixMatch:
|
||||
|
||||
def __init__(self, n=2):
|
||||
self.n = n
|
||||
self.augment_list = fixmatch_list()
|
||||
|
||||
def __call__(self, img):
|
||||
ops = random.choices(self.augment_list, k=self.n)
|
||||
|
||||
for op, minval, maxval in ops:
|
||||
m = random.random()
|
||||
val = m * (maxval-minval) + minval
|
||||
img = op(img, val)
|
||||
|
||||
return img
|
||||
341
Dassl.ProGrad.pytorch/dassl/data/transforms/transforms.py
Normal file
341
Dassl.ProGrad.pytorch/dassl/data/transforms/transforms.py
Normal file
@@ -0,0 +1,341 @@
|
||||
import numpy as np
|
||||
import random
|
||||
import torch
|
||||
from PIL import Image
|
||||
from torchvision.transforms import (
|
||||
Resize, Compose, ToTensor, Normalize, CenterCrop, RandomCrop, ColorJitter,
|
||||
RandomApply, GaussianBlur, RandomGrayscale, RandomResizedCrop,
|
||||
RandomHorizontalFlip
|
||||
)
|
||||
|
||||
from .autoaugment import SVHNPolicy, CIFAR10Policy, ImageNetPolicy
|
||||
from .randaugment import RandAugment, RandAugment2, RandAugmentFixMatch
|
||||
|
||||
AVAI_CHOICES = [
|
||||
"random_flip",
|
||||
"random_resized_crop",
|
||||
"normalize",
|
||||
"instance_norm",
|
||||
"random_crop",
|
||||
"random_translation",
|
||||
"center_crop", # This has become a default operation for test
|
||||
"cutout",
|
||||
"imagenet_policy",
|
||||
"cifar10_policy",
|
||||
"svhn_policy",
|
||||
"randaugment",
|
||||
"randaugment_fixmatch",
|
||||
"randaugment2",
|
||||
"gaussian_noise",
|
||||
"colorjitter",
|
||||
"randomgrayscale",
|
||||
"gaussian_blur",
|
||||
]
|
||||
|
||||
INTERPOLATION_MODES = {
|
||||
"bilinear": Image.BILINEAR,
|
||||
"bicubic": Image.BICUBIC,
|
||||
"nearest": Image.NEAREST,
|
||||
}
|
||||
|
||||
|
||||
class Random2DTranslation:
|
||||
"""Given an image of (height, width), we resize it to
|
||||
(height*1.125, width*1.125), and then perform random cropping.
|
||||
|
||||
Args:
|
||||
height (int): target image height.
|
||||
width (int): target image width.
|
||||
p (float, optional): probability that this operation takes place.
|
||||
Default is 0.5.
|
||||
interpolation (int, optional): desired interpolation. Default is
|
||||
``PIL.Image.BILINEAR``
|
||||
"""
|
||||
|
||||
def __init__(self, height, width, p=0.5, interpolation=Image.BILINEAR):
|
||||
self.height = height
|
||||
self.width = width
|
||||
self.p = p
|
||||
self.interpolation = interpolation
|
||||
|
||||
def __call__(self, img):
|
||||
if random.uniform(0, 1) > self.p:
|
||||
return img.resize((self.width, self.height), self.interpolation)
|
||||
|
||||
new_width = int(round(self.width * 1.125))
|
||||
new_height = int(round(self.height * 1.125))
|
||||
resized_img = img.resize((new_width, new_height), self.interpolation)
|
||||
|
||||
x_maxrange = new_width - self.width
|
||||
y_maxrange = new_height - self.height
|
||||
x1 = int(round(random.uniform(0, x_maxrange)))
|
||||
y1 = int(round(random.uniform(0, y_maxrange)))
|
||||
croped_img = resized_img.crop(
|
||||
(x1, y1, x1 + self.width, y1 + self.height)
|
||||
)
|
||||
|
||||
return croped_img
|
||||
|
||||
|
||||
class InstanceNormalization:
|
||||
"""Normalize data using per-channel mean and standard deviation.
|
||||
|
||||
Reference:
|
||||
- Ulyanov et al. Instance normalization: The missing in- gredient
|
||||
for fast stylization. ArXiv 2016.
|
||||
- Shu et al. A DIRT-T Approach to Unsupervised Domain Adaptation.
|
||||
ICLR 2018.
|
||||
"""
|
||||
|
||||
def __init__(self, eps=1e-8):
|
||||
self.eps = eps
|
||||
|
||||
def __call__(self, img):
|
||||
C, H, W = img.shape
|
||||
img_re = img.reshape(C, H * W)
|
||||
mean = img_re.mean(1).view(C, 1, 1)
|
||||
std = img_re.std(1).view(C, 1, 1)
|
||||
return (img-mean) / (std + self.eps)
|
||||
|
||||
|
||||
class Cutout:
|
||||
"""Randomly mask out one or more patches from an image.
|
||||
|
||||
https://github.com/uoguelph-mlrg/Cutout
|
||||
|
||||
Args:
|
||||
n_holes (int, optional): number of patches to cut out
|
||||
of each image. Default is 1.
|
||||
length (int, optinal): length (in pixels) of each square
|
||||
patch. Default is 16.
|
||||
"""
|
||||
|
||||
def __init__(self, n_holes=1, length=16):
|
||||
self.n_holes = n_holes
|
||||
self.length = length
|
||||
|
||||
def __call__(self, img):
|
||||
"""
|
||||
Args:
|
||||
img (Tensor): tensor image of size (C, H, W).
|
||||
|
||||
Returns:
|
||||
Tensor: image with n_holes of dimension
|
||||
length x length cut out of it.
|
||||
"""
|
||||
h = img.size(1)
|
||||
w = img.size(2)
|
||||
|
||||
mask = np.ones((h, w), np.float32)
|
||||
|
||||
for n in range(self.n_holes):
|
||||
y = np.random.randint(h)
|
||||
x = np.random.randint(w)
|
||||
|
||||
y1 = np.clip(y - self.length // 2, 0, h)
|
||||
y2 = np.clip(y + self.length // 2, 0, h)
|
||||
x1 = np.clip(x - self.length // 2, 0, w)
|
||||
x2 = np.clip(x + self.length // 2, 0, w)
|
||||
|
||||
mask[y1:y2, x1:x2] = 0.0
|
||||
|
||||
mask = torch.from_numpy(mask)
|
||||
mask = mask.expand_as(img)
|
||||
return img * mask
|
||||
|
||||
|
||||
class GaussianNoise:
|
||||
"""Add gaussian noise."""
|
||||
|
||||
def __init__(self, mean=0, std=0.15, p=0.5):
|
||||
self.mean = mean
|
||||
self.std = std
|
||||
self.p = p
|
||||
|
||||
def __call__(self, img):
|
||||
if random.uniform(0, 1) > self.p:
|
||||
return img
|
||||
noise = torch.randn(img.size()) * self.std + self.mean
|
||||
return img + noise
|
||||
|
||||
|
||||
def build_transform(cfg, is_train=True, choices=None):
|
||||
"""Build transformation function.
|
||||
|
||||
Args:
|
||||
cfg (CfgNode): config.
|
||||
is_train (bool, optional): for training (True) or test (False).
|
||||
Default is True.
|
||||
choices (list, optional): list of strings which will overwrite
|
||||
cfg.INPUT.TRANSFORMS if given. Default is None.
|
||||
"""
|
||||
if cfg.INPUT.NO_TRANSFORM:
|
||||
print("Note: no transform is applied!")
|
||||
return None
|
||||
|
||||
if choices is None:
|
||||
choices = cfg.INPUT.TRANSFORMS
|
||||
|
||||
for choice in choices:
|
||||
assert choice in AVAI_CHOICES
|
||||
|
||||
target_size = f"{cfg.INPUT.SIZE[0]}x{cfg.INPUT.SIZE[1]}"
|
||||
|
||||
normalize = Normalize(mean=cfg.INPUT.PIXEL_MEAN, std=cfg.INPUT.PIXEL_STD)
|
||||
|
||||
if is_train:
|
||||
return _build_transform_train(cfg, choices, target_size, normalize)
|
||||
else:
|
||||
return _build_transform_test(cfg, choices, target_size, normalize)
|
||||
|
||||
|
||||
def _build_transform_train(cfg, choices, target_size, normalize):
|
||||
print("Building transform_train")
|
||||
tfm_train = []
|
||||
|
||||
interp_mode = INTERPOLATION_MODES[cfg.INPUT.INTERPOLATION]
|
||||
|
||||
# Make sure the image size matches the target size
|
||||
conditions = []
|
||||
conditions += ["random_crop" not in choices]
|
||||
conditions += ["random_resized_crop" not in choices]
|
||||
if all(conditions):
|
||||
print(f"+ resize to {target_size}")
|
||||
tfm_train += [Resize(cfg.INPUT.SIZE, interpolation=interp_mode)]
|
||||
|
||||
if "random_translation" in choices:
|
||||
print("+ random translation")
|
||||
tfm_train += [
|
||||
Random2DTranslation(cfg.INPUT.SIZE[0], cfg.INPUT.SIZE[1])
|
||||
]
|
||||
|
||||
if "random_crop" in choices:
|
||||
crop_padding = cfg.INPUT.CROP_PADDING
|
||||
print("+ random crop (padding = {})".format(crop_padding))
|
||||
tfm_train += [RandomCrop(cfg.INPUT.SIZE, padding=crop_padding)]
|
||||
|
||||
if "random_resized_crop" in choices:
|
||||
print(f"+ random resized crop (size={cfg.INPUT.SIZE})")
|
||||
tfm_train += [
|
||||
RandomResizedCrop(cfg.INPUT.SIZE, interpolation=interp_mode)
|
||||
]
|
||||
|
||||
if "center_crop" in choices:
|
||||
print(f"+ center crop (size={cfg.INPUT.SIZE})")
|
||||
tfm_train += [CenterCrop(cfg.INPUT.SIZE)]
|
||||
|
||||
if "random_flip" in choices:
|
||||
print("+ random flip")
|
||||
tfm_train += [RandomHorizontalFlip()]
|
||||
|
||||
if "imagenet_policy" in choices:
|
||||
print("+ imagenet policy")
|
||||
tfm_train += [ImageNetPolicy()]
|
||||
|
||||
if "cifar10_policy" in choices:
|
||||
print("+ cifar10 policy")
|
||||
tfm_train += [CIFAR10Policy()]
|
||||
|
||||
if "svhn_policy" in choices:
|
||||
print("+ svhn policy")
|
||||
tfm_train += [SVHNPolicy()]
|
||||
|
||||
if "randaugment" in choices:
|
||||
n_ = cfg.INPUT.RANDAUGMENT_N
|
||||
m_ = cfg.INPUT.RANDAUGMENT_M
|
||||
print("+ randaugment (n={}, m={})".format(n_, m_))
|
||||
tfm_train += [RandAugment(n_, m_)]
|
||||
|
||||
if "randaugment_fixmatch" in choices:
|
||||
n_ = cfg.INPUT.RANDAUGMENT_N
|
||||
print("+ randaugment_fixmatch (n={})".format(n_))
|
||||
tfm_train += [RandAugmentFixMatch(n_)]
|
||||
|
||||
if "randaugment2" in choices:
|
||||
n_ = cfg.INPUT.RANDAUGMENT_N
|
||||
print("+ randaugment2 (n={})".format(n_))
|
||||
tfm_train += [RandAugment2(n_)]
|
||||
|
||||
if "colorjitter" in choices:
|
||||
print("+ color jitter")
|
||||
tfm_train += [
|
||||
ColorJitter(
|
||||
brightness=cfg.INPUT.COLORJITTER_B,
|
||||
contrast=cfg.INPUT.COLORJITTER_C,
|
||||
saturation=cfg.INPUT.COLORJITTER_S,
|
||||
hue=cfg.INPUT.COLORJITTER_H,
|
||||
)
|
||||
]
|
||||
|
||||
if "randomgrayscale" in choices:
|
||||
print("+ random gray scale")
|
||||
tfm_train += [RandomGrayscale(p=cfg.INPUT.RGS_P)]
|
||||
|
||||
if "gaussian_blur" in choices:
|
||||
print(f"+ gaussian blur (kernel={cfg.INPUT.GB_K})")
|
||||
tfm_train += [
|
||||
RandomApply([GaussianBlur(cfg.INPUT.GB_K)], p=cfg.INPUT.GB_P)
|
||||
]
|
||||
|
||||
print("+ to torch tensor of range [0, 1]")
|
||||
tfm_train += [ToTensor()]
|
||||
|
||||
if "cutout" in choices:
|
||||
cutout_n = cfg.INPUT.CUTOUT_N
|
||||
cutout_len = cfg.INPUT.CUTOUT_LEN
|
||||
print("+ cutout (n_holes={}, length={})".format(cutout_n, cutout_len))
|
||||
tfm_train += [Cutout(cutout_n, cutout_len)]
|
||||
|
||||
if "normalize" in choices:
|
||||
print(
|
||||
"+ normalization (mean={}, "
|
||||
"std={})".format(cfg.INPUT.PIXEL_MEAN, cfg.INPUT.PIXEL_STD)
|
||||
)
|
||||
tfm_train += [normalize]
|
||||
|
||||
if "gaussian_noise" in choices:
|
||||
print(
|
||||
"+ gaussian noise (mean={}, std={})".format(
|
||||
cfg.INPUT.GN_MEAN, cfg.INPUT.GN_STD
|
||||
)
|
||||
)
|
||||
tfm_train += [GaussianNoise(cfg.INPUT.GN_MEAN, cfg.INPUT.GN_STD)]
|
||||
|
||||
if "instance_norm" in choices:
|
||||
print("+ instance normalization")
|
||||
tfm_train += [InstanceNormalization()]
|
||||
|
||||
tfm_train = Compose(tfm_train)
|
||||
|
||||
return tfm_train
|
||||
|
||||
|
||||
def _build_transform_test(cfg, choices, target_size, normalize):
|
||||
print("Building transform_test")
|
||||
tfm_test = []
|
||||
|
||||
interp_mode = INTERPOLATION_MODES[cfg.INPUT.INTERPOLATION]
|
||||
|
||||
print(f"+ resize the smaller edge to {max(cfg.INPUT.SIZE)}")
|
||||
tfm_test += [Resize(max(cfg.INPUT.SIZE), interpolation=interp_mode)]
|
||||
|
||||
print(f"+ {target_size} center crop")
|
||||
tfm_test += [CenterCrop(cfg.INPUT.SIZE)]
|
||||
|
||||
print("+ to torch tensor of range [0, 1]")
|
||||
tfm_test += [ToTensor()]
|
||||
|
||||
if "normalize" in choices:
|
||||
print(
|
||||
"+ normalization (mean={}, "
|
||||
"std={})".format(cfg.INPUT.PIXEL_MEAN, cfg.INPUT.PIXEL_STD)
|
||||
)
|
||||
tfm_test += [normalize]
|
||||
|
||||
if "instance_norm" in choices:
|
||||
print("+ instance normalization")
|
||||
tfm_test += [InstanceNormalization()]
|
||||
|
||||
tfm_test = Compose(tfm_test)
|
||||
|
||||
return tfm_test
|
||||
Reference in New Issue
Block a user