Package: augmend
AugmendAugmentation library tailored towards the needs of microscopy images analysis.Augmendprovides a simple yet flexible augmentation pipeline without too many bells and whistlessupports 2D and 3D imagesoperates on numpy arrays and can interface with keras/tensorflow generatorsoffers optional GPU acceleration for compute intensive augmentions via OpenCLPlease note that this project is still experimental and the API might change anytime.-Currently implemented:flips and 90 degree rotationsscaling, elastic deformationGaussian noise, Intensity Shiftsetc...Installationpip install augmendFrom source:pip install git+https://github.com/stardist/augmend.gitUsageBasic augmentation pipeline (single images)First instantiate an augmentation pipeline class and then populate it with augmentation transforms (e.g. fliprotations, elastic transforms, etc).fromaugmendimportAugmendfromaugmendimportElastic,FlipRot90,AdditiveNoise# define augmentation pipelineaug=Augmend()# define transformsaug.add(FlipRot90(axis=(0,1)),probability=1)aug.add(Elastic(axis=(0,1)),probability=1)aug.add(AdditiveNoise(sigma=0.3),probability=1)#...Afterwards, it can be applied to an imageimgby simply callingaug(img)importnumpyasnpimportmatplotlib.pyplotasplt# inputimg=np.zeros((128,128),np.float32)img[::16]=1# outputresult=aug(img)plt.subplot(121);plt.title("img");plt.imshow(img)plt.subplot(122);plt.title("result");plt.imshow(result)Simultanously transforming several imagesOften, one is given several input images[X,Y,...]that need to be transformed the same way e.g. image/label pairs for supervised learning).
To that end,Augmend.addaccepts a list of transforms, which then will be applied to each image in the input with the same random seed.aug.add([FlipRot90(),FlipRot90()],probability=1)[X2,Y2]=aug([X,Y])Augmenting in 3DShould work the same way - in fact, almost all augmentations should accept nD arrays. The axis over which the transformation is applied can be typically set via theaxisparameter in the transform object, e.g.FlipRot90(axis = (0,1,2)).Example:importnumpyasnpfromaugmendimportAugmend,Elastic,FlipRot90# define augmentation pipelineaug=Augmend()aug.add([FlipRot90(axis=(0,1,2)),FlipRot90(axis=(0,1,2))],probability=0.9)aug.add([Elastic(axis=(0,1,2),amount=5,order=1),Elastic(axis=(0,1,2),amount=5,order=0)],probability=0.9)# example 3d image and labelx=np.zeros((100,)*3,np.float32)x[-20:,:20,:20]=1.x[30:40,-10:]=.8Xs=np.meshgrid(*((np.arange(0,100),)*3),indexing="ij")R=np.sqrt(np.sum([(X-c)**2forX,cinzip(Xs,(70,60,50))],axis=0))x[R<20]=1.4y=np.zeros((100,)*3,np.uint16)y[R<20]=200# resulting volumeres=aug([x,y])Should result in a similar output like this (From left to right: original and 4 augmented volumes. Top and bottom, imagexand labelsy).Usage with a data generatorIn a supervised learning setting, one often constructs a data generator  that yeilds batches of array pairs# a simple data generator (might as well return several arrays, as for a supervised data generator)defdata_gen():foriinrange(4):yieldx_batch,y_batchAugmend.flowallows to wrap that generator into the augmented one, like soaug=Augmend()aug.add([FlipRot90(axis=(1,2)),FlipRot90(axis=(1,2))],probability=0.9)aug_gen=aug.flow(data_gen)# get the results as tupleres=next(aug_gen)Usage withtensorflowdata pipelinesAugmend.tf_mapreturns atensorflowfunction that can be applied to an existingtf.datapipeline viadataset.map():importnumpyasnpimporttensorflowastffromaugmendimportAugmendfromaugmend.utilsimportcreate_test_patterny=create_test_pattern(n_samples=16,shape=(512,512),grid_w=(3,10)).astype(np.int16)x=(y+50*np.random.normal(0,1,y.shape)).astype(np.float32)aug=Augmend()aug.add([Elastic(axis=(0,1),amount=5,order=1),Elastic(axis=(0,1),amount=5,order=0)])dataset=tf.data.Dataset.from_tensor_slices((x,y))dataset=dataset.map(aug.tf_map,num_parallel_calls=tf.data.AUTOTUNE)x2,y2=next(iter(dataset))Usage with pytorch DatasetAugmend.torch_wrapwill wrap an existingtorchdataset:fromtorch.utils.dataimportTensorDatasetdata=TensorDataset(torch.tensor(x),torch.tensor(y))data=aug.torch_wrap(data)x2,y2=data[0]Transforming arrays on the GPUSome transforms (e.g.ElasticandScale) allow to use the GPU for the transformation (which can be a bottleneck) via the keyworduse_gpu. This requires additionally the installation ofgputoolsAvailable augmentations