├── README.md └── Rand_Augment.py /README.md: -------------------------------------------------------------------------------- 1 | # randaugment 2 | an personal implementation about google's Randaugment (testing accuracy in cifar-10) in computer vision. 3 | 4 | This repo a partly copy from https://github.com/DeepVoltaire/AutoAugment ,it a implemetation about autoaugment published by google . I just change some code about operations selected way. 5 | 6 | 7 | I must say a very important point here , there is no need to set the param magnitude as same as google's , there is different best max magnitude for different dataset , so I wrote a test fun for you to test every single operation with different magnitude. 8 | 9 | 10 | 11 | # 1: if you want to just call this class ,write like above , this is for call the whole function 12 | 13 | 14 | 15 | img_augment = Rand_Augment() 16 | img_origal = Image.open(r'0a38b552372d.png') 17 | img_final = img_augment(img_origal) 18 | plt.imshow(img_final) 19 | plt.show() 20 | print('how to call') 21 | 22 | # 2: if you want to test a single function,write like above 23 | 24 | img_augment = Rand_Augment() 25 | img_origal = Image.open(r'0a38b552372d.png') 26 | img_final = img_augment.test_single_operation(img_origal, 'shearX') 27 | plt.imshow(img_final) 28 | plt.show() 29 | print('how to test') 30 | 31 | 32 | Actually ,this is my first time to write a reposity in Github , if there is some bug here , just point it directly. I'm almost in the internet every day :) 33 | -------------------------------------------------------------------------------- /Rand_Augment.py: -------------------------------------------------------------------------------- 1 | from PIL import Image 2 | import matplotlib.pyplot as plt 3 | import numpy as np 4 | from PIL import Image, ImageEnhance, ImageOps 5 | import numpy as np 6 | import random 7 | 8 | 9 | class Rand_Augment(): 10 | def __init__(self, Numbers=None, max_Magnitude=None): 11 | self.transforms = ['autocontrast', 'equalize', 'rotate', 'solarize', 'color', 'posterize', 12 | 'contrast', 'brightness', 'sharpness', 'shearX', 'shearY', 'translateX', 'translateY'] 13 | if Numbers is None: 14 | self.Numbers = len(self.transforms) // 2 15 | else: 16 | self.Numbers = Numbers 17 | if max_Magnitude is None: 18 | self.max_Magnitude = 10 19 | else: 20 | self.max_Magnitude = max_Magnitude 21 | fillcolor = 128 22 | self.ranges = { 23 | # these Magnitude range , you must test it yourself , see what will happen after these operation , 24 | # it is no need to obey the value in autoaugment.py 25 | "shearX": np.linspace(0, 0.3, 10), 26 | "shearY": np.linspace(0, 0.3, 10), 27 | "translateX": np.linspace(0, 0.2, 10), 28 | "translateY": np.linspace(0, 0.2, 10), 29 | "rotate": np.linspace(0, 360, 10), 30 | "color": np.linspace(0.0, 0.9, 10), 31 | "posterize": np.round(np.linspace(8, 4, 10), 0).astype(np.int), 32 | "solarize": np.linspace(256, 231, 10), 33 | "contrast": np.linspace(0.0, 0.5, 10), 34 | "sharpness": np.linspace(0.0, 0.9, 10), 35 | "brightness": np.linspace(0.0, 0.3, 10), 36 | "autocontrast": [0] * 10, 37 | "equalize": [0] * 10, 38 | "invert": [0] * 10 39 | } 40 | self.func = { 41 | "shearX": lambda img, magnitude: img.transform( 42 | img.size, Image.AFFINE, (1, magnitude * random.choice([-1, 1]), 0, 0, 1, 0), 43 | Image.BICUBIC, fill=fillcolor), 44 | "shearY": lambda img, magnitude: img.transform( 45 | img.size, Image.AFFINE, (1, 0, 0, magnitude * random.choice([-1, 1]), 1, 0), 46 | Image.BICUBIC, fill=fillcolor), 47 | "translateX": lambda img, magnitude: img.transform( 48 | img.size, Image.AFFINE, (1, 0, magnitude * img.size[0] * random.choice([-1, 1]), 0, 1, 0), 49 | fill=fillcolor), 50 | "translateY": lambda img, magnitude: img.transform( 51 | img.size, Image.AFFINE, (1, 0, 0, 0, 1, magnitude * img.size[1] * random.choice([-1, 1])), 52 | fill=fillcolor), 53 | "rotate": lambda img, magnitude: self.rotate_with_fill(img, magnitude), 54 | # "rotate": lambda img, magnitude: img.rotate(magnitude * random.choice([-1, 1])), 55 | "color": lambda img, magnitude: ImageEnhance.Color(img).enhance(1 + magnitude * random.choice([-1, 1])), 56 | "posterize": lambda img, magnitude: ImageOps.posterize(img, magnitude), 57 | "solarize": lambda img, magnitude: ImageOps.solarize(img, magnitude), 58 | "contrast": lambda img, magnitude: ImageEnhance.Contrast(img).enhance( 59 | 1 + magnitude * random.choice([-1, 1])), 60 | "sharpness": lambda img, magnitude: ImageEnhance.Sharpness(img).enhance( 61 | 1 + magnitude * random.choice([-1, 1])), 62 | "brightness": lambda img, magnitude: ImageEnhance.Brightness(img).enhance( 63 | 1 + magnitude * random.choice([-1, 1])), 64 | "autocontrast": lambda img, magnitude: ImageOps.autocontrast(img), 65 | "equalize": lambda img, magnitude: img, 66 | "invert": lambda img, magnitude: ImageOps.invert(img) 67 | } 68 | 69 | def rand_augment(self): 70 | """Generate a set of distortions. 71 | Args: 72 | N: Number of augmentation transformations to apply sequentially. N is len(transforms)/2 will be best 73 | M: Max_Magnitude for all the transformations. should be <= self.max_Magnitude """ 74 | 75 | M = np.random.randint(0, self.max_Magnitude, self.Numbers) 76 | 77 | sampled_ops = np.random.choice(self.transforms, self.Numbers) 78 | return [(op, Magnitude) for (op, Magnitude) in zip(sampled_ops, M)] 79 | 80 | def __call__(self, image): 81 | operations = self.rand_augment() 82 | for (op_name, M) in operations: 83 | operation = self.func[op_name] 84 | mag = self.ranges[op_name][M] 85 | image = operation(image, mag) 86 | return image 87 | 88 | def rotate_with_fill(self, img, magnitude): 89 | # I don't know why rotate must change to RGBA , it is copy from Autoaugment - pytorch 90 | rot = img.convert("RGBA").rotate(magnitude) 91 | return Image.composite(rot, Image.new("RGBA", rot.size, (128,) * 4), rot).convert(img.mode) 92 | 93 | def test_single_operation(self, image, op_name, M=-1): 94 | ''' 95 | :param image: image 96 | :param op_name: operation name in self.transforms 97 | :param M: -1 stands for the max Magnitude in there operation 98 | :return: 99 | ''' 100 | operation = self.func[op_name] 101 | mag = self.ranges[op_name][M] 102 | image = operation(image, mag) 103 | return image 104 | 105 | 106 | if __name__ == '__main__': 107 | # # this is for call the whole fun 108 | # img_augment = Rand_Augment() 109 | # img_origal = Image.open(r'0a38b552372d.png') 110 | # img_final = img_augment(img_origal) 111 | # plt.imshow(img_final) 112 | # plt.show() 113 | # print('how to call') 114 | 115 | # this is for a single fun you want to test 116 | img_augment = Rand_Augment() 117 | img_origal = Image.open(r'0bfdedaa60b54078ab0fc3bc6582aa90.jpg') 118 | for i in range(0, 10): 119 | img_final = img_augment.test_single_operation(img_origal, 'invert', M=i) 120 | plt.subplot(5, 2, i + 1) 121 | plt.imshow(img_final) 122 | plt.show() 123 | 124 | print('how to test') 125 | --------------------------------------------------------------------------------