Elf_encoder / src /TensorImageNoised.py
thomaswarford's picture
Upload 77 files
90f531c verified
raw
history blame
2.37 kB
#!/usr/bin/env python
"""
TensorImageNoised class, and corresponding transforms.
This class exists so autoencoder inputs can be subjected to augmentation transforms without the outputs being affected when using fastai dataloaders.
"""
from fastai import *
from fastai.vision.all import *
class PILImageNoised(PILImage): pass
class TensorImageNoised(TensorImage): pass
PILImageNoised._tensor_cls = TensorImageNoised
class AddNoiseTransform(Transform):
"Add noise to image"
split_idx=0
order = 11
def __init__(self, noise_factor=0.3): self.noise_factor = noise_factor
def encodes(self, o:TensorImageNoised): return o + (self.noise_factor * torch.randn(*o.shape).to(o.device))
class RandomErasingTransform(RandTransform):
"Randomly selects a rectangle region in an image and randomizes its pixels."
order = 100 # After Normalize
def __init__(self,
p:float=0.5, # Probability of appying Random Erasing
sl:float=0., # Minimum proportion of erased area
sh:float=0.3, # Maximum proportion of erased area
min_aspect:float=0.3, # Minimum aspect ratio of erased area
max_count:int=1 # Maximum number of erasing blocks per image, area per box is scaled by count
):
store_attr()
super().__init__(p=p)
self.log_ratio = (math.log(min_aspect), math.log(1/min_aspect))
def _bounds(self, area, img_h, img_w):
r_area = random.uniform(self.sl,self.sh) * area
aspect = math.exp(random.uniform(*self.log_ratio))
return self._slice(r_area*aspect, img_h) + self._slice(r_area/aspect, img_w)
def _slice(self, area, sz):
bound = int(round(math.sqrt(area)))
loc = random.randint(0, max(sz-bound, 0))
return loc,loc+bound
def cutout_gaussian(self,
x:TensorImageNoised, # Input image
areas:list # List of areas to cutout. Order rl,rh,cl,ch
):
"Replace all `areas` in `x` with N(0,1) noise"
chan,img_h,img_w = x.shape[-3:]
for rl,rh,cl,ch in areas: x[..., rl:rh, cl:ch].normal_()
return x
def encodes(self,x:TensorImageNoised):
count = random.randint(1, self.max_count)
_,img_h,img_w = x.shape[-3:]
area = img_h*img_w/count
areas = [self._bounds(area, img_h, img_w) for _ in range(count)]
return self.cutout_gaussian(x, areas)