farquasar1/ConvLSTM

Data augmentation import

Opened this issue · 6 comments

Hi there,
how do you install "hal" for data augmentation? it is imported like this,

from hal.augmentation.geometric_transforms import random_rigid_transform, apply_geometric_transform

Hal is an external component . You can use the code

import numpy as np
from scipy import ndimage
from scipy.misc import imresize
INTERP_OPTIONS = {'nearest': 0, 'linear': 1, 'quadratic': 2, 'cubic': 3}

def random_rigid_transform(x, y, origin=None, scale=0.0, angle=0.0, shift=[0.0, 0.0]):
"""
Compose a displacement field with a random rigid transformation with
uniformly distributed scale, rotation and translation.
:param x: input x coordinate grid / point set (numpy array)
:param y: input y coordinate grid / point set (numpy array)
:param origin: (x0, y0) center of rotation, defaults to image center
:param scale:  random relative scale [1.0 - scale, 1.0 + scale], default scale = 0.0 (no scale variation)
:param angle:  random rotation [-angle, angle], default angle = 0.0 (no rotation)
:param shift:  random shift [-tx, tx], [-ty, ty], defult shift = [0.0, 0.0] (no translation)
:return x: output x coordinate grid / point set (numpy array)
:return y: output y coordinate grid / point set (numpy array)
"""

x0, y0 = origin if origin is not None else [x.shape[1] / 2, x.shape[0] / 2]
phi = np.pi / 180.0 * angle
tx, ty = shift

# Generate random transform
scale = 1.0 + scale * (2.0 * np.random.rand() - 1.0)  # uniform [1 - scale, 1 + scale]
phi *= (2.0 * np.random.rand() - 1.0)  # uniform [-phi_max, phi_max]
tx *= (2 * np.random.rand() - 1)  # uniform between [-tx, tx]
ty *= (2 * np.random.rand() - 1)  # uniform between [-ty, ty]

# Compute displacement and accumulate to output coordinates
dx = scale * (np.cos(phi) * (x - x0) + np.sin(phi) * (y - y0)) - x + x0 + tx
dy = scale * (np.cos(phi) * (y - y0) - np.sin(phi) * (x - x0)) - y + y0 + ty
x += dx
y += dy
return x, y

For the other function

def apply_geometric_transform(image, x, y, interp=None, border_mode='reflect', constant_values=0):
"""
Applies a geometric transform defined by the displacement field x, y.
:param image: input image
:param x: displacement vector x component
:param y: displacement vector y component
:param interp: interpolation option {nearest, linear, quadratic, cubic'},
default is nearest for integer image and cubic for floating point image.
:param border_mode: interpolation border mode option {‘constant’, ‘nearest’, ‘reflect’ or ‘wrap’},
default is 'reflect'
:param constant_values: fill value for border mode = 'constant', either a scalar value or a list
of values with the same number of elements as channels in the input image
:return: image: output image, transformed by applying the displacement field
"""
if image is None or image.ndim != 3:
# Not an image, could be a point set but that is not yet supported
return image

if interp is None:  # if not given use nearest neighbor for integer input
    interp = 'nearest' if issubclass(image.dtype.type, np.integer) else 'cubic'

assert interp in INTERP_OPTIONS, 'Unknown interpolation option "%s"' % interp
order = INTERP_OPTIONS[interp]

# Convert constant_values to list to match the number of image channels
if not isinstance(constant_values, list):
    constant_values = [constant_values] * image.shape[0]

# Apply transform with spline interpolation and restore original shape
image_shape = image.shape
for i in range(image.shape[0]):
    _img = ndimage.map_coordinates(image[i, ...], [y.ravel(), x.ravel()],
                                   order=order,
                                   mode=border_mode,
                                   cval=constant_values[i])
    image[i, ...] = _img.reshape(image_shape[1:])
return image

GEOMETRIC_TRANSFORMS = {'rigid': random_rigid_transform,
'deform': random_deformation}

awsomee! Thank you.
however there was a problem in this line,

image[i, ...] = _img.reshape(image_shape[1:])
ValueError: cannot reshape array of size 576 into shape (96,96)

So I replaced it with this line and it worked,
image[i, ...] = resize(_img, (image_shape[1], image_shape[2]))

I don't know how map_coordinates()works. so do you think this dimension mismatch makes sense?

I think is has to do with the fact that the dimensions are an odd number.

But the images are corrupted now!

val_078

here's without augmentation for your reference. I'm using the Kaggle Ultrasound Nerve Segmentation dataset.
val_001