8000 Refactor augmenters by aleju · Pull Request #407 · aleju/imgaug · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Refactor augmenters #407

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Sep 6, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 19 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,22 @@
Use `imgaug.augmenters.contrast.LinearContrast` instead. #396
* Renamed argument `X` of `imgaug.augmentables.kps.compute_geometric_median()`
to `points`. The old argument is still accepted, but now deprecated. #402
* Refactored `Affine` to improve code quality and minimize code
duplication. #407
* [rarely breaking] Removed `Affine.VALID_DTYPES_CV2_ORDER_0`.
* [rarely breaking] Removed `Affine.VALID_DTYPES_CV2_ORDER_NOT_0`.
* [rarely breaking] Removed `Affine.order_map_skimage_cv2`.
* [rarely breaking] Removed `Affine.mode_map_skimage_cv2`.
* Refactored `CropAndPad` to improve code quality and minimize code
duplication. #407
* Refactored module `size` to decrease code duplication between different
augmenters. #407
* Changed `imgaug.imgaug.pad` to automatically clip the `cval` argument
to the value range of the array to be padded. #407
* Moved matrix generation logic of augmenters in module `convolutional`
to classes, one per augmenter (i.e. one per category of convolutional
matrix). This should avoid errors related to pickling of functions. #407


## Improved Segmentation Map Augmentation #302

Expand Down Expand Up @@ -571,7 +587,9 @@ Changes:
augmentations. #385
* Fixed `Convolve` using an overly restrictive check when validating inputs
for `matrix` w.r.t. whether they are callables. The check should now also
support class methods (and possibly various other callables).
support class methods (and possibly various other callables). #407
* Fixed `CropAndPad`, `Pad` and `PadToFixedSize` still clipping `cval` samples
to the `uint8`. They now clip to the input array's dtype's value range. #407


# 0.2.9
Expand Down
257 changes: 141 additions & 116 deletions imgaug/augmenters/convolutional.py
Original file line number Diff line number Diff line change
Expand Up @@ -295,35 +295,41 @@ def __init__(self, alpha=0, lightness=1,
lightness, "lightness",
value_range=(0, None), tuple_to_uniform=True, list_to_choice=True)

def _create_matrices(_image, nb_channels, random_state_func):
alpha_sample = alpha_param.draw_sample(
random_state=random_state_func)
assert 0 <= alpha_sample <= 1.0, (
"Expected 'alpha' to be in the interval [0.0, 1.0], "
"got %.4f." % (alpha_sample,))
lightness_sample = lightness_param.draw_sample(
random_state=random_state_func)
matrix_nochange = np.array([
[0, 0, 0],
[0, 1, 0],
[0, 0, 0]
], dtype=np.float32)
matrix_effect = np.array([
[-1, -1, -1],
[-1, 8+lightness_sample, -1],
[-1, -1, -1]
], dtype=np.float32)
matrix = (
(1-alpha_sample) * matrix_nochange
+ alpha_sample * matrix_effect
)
return [matrix] * nb_channels
matrix_gen = _SharpeningMatrixGenerator(alpha_param, lightness_param)

super(Sharpen, self).__init__(
matrix=_create_matrices, name=name, deterministic=deterministic,
matrix=matrix_gen, name=name, deterministic=deterministic,
random_state=random_state)


class _SharpeningMatrixGenerator(object):
def __init__(self, alpha, lightness):
self.alpha = alpha
self.lightness = lightness

def __call__(self, _image, nb_channels, random_state):
alpha_sample = self.alpha.draw_sample(random_state=random_state)
assert 0 <= alpha_sample <= 1.0, (
"Expected 'alpha' to be in the interval [0.0, 1.0], "
"got %.4f." % (alpha_sample,))
lightness_sample = self.lightness.draw_sample(random_state=random_state)
matrix_nochange = np.array([
[0, 0, 0],
[0, 1, 0],
[0, 0, 0]
], dtype=np.float32)
matrix_effect = np.array([
[-1, -1, -1],
[-1, 8+lightness_sample, -1],
[-1, -1, -1]
], dtype=np.float32)
matrix = (
(1-alpha_sample) * matrix_nochange
+ alpha_sample * matrix_effect
)
return [matrix] * nb_channels


class Emboss(Convolve):
"""
Emboss images and alpha-blend the result with the original input images.
Expand Down Expand Up @@ -390,35 +396,41 @@ def __init__(self, alpha=0, strength=1,
strength, "strength",
value_range=(0, None), tuple_to_uniform=True, list_to_choice=True)

def _create_matrices(_image, nb_channels, random_state_func):
alpha_sample = alpha_param.draw_sample(
random_state=random_state_func)
assert 0 <= alpha_sample <= 1.0, (
"Expected 'alpha' to be in the interval [0.0, 1.0], "
"got %.4f." % (alpha_sample,))
strength_sample = strength_param.draw_sample(
random_state=random_state_func)
matrix_nochange = np.array([
[0, 0, 0],
[0, 1, 0],
[0, 0, 0]
], dtype=np.float32)
matrix_effect = np.array([
[-1-strength_sample, 0-strength_sample, 0],
[0-strength_sample, 1, 0+strength_sample],
[0, 0+strength_sample, 1+strength_sample]
], dtype=np.float32)
matrix = (
(1-alpha_sample) * matrix_nochange
+ alpha_sample * matrix_effect
)
return [matrix] * nb_channels
matrix_gen = _EmbossMatrixGenerator(alpha_param, strength_param)

super(Emboss, self).__init__(
matrix=_create_matrices, name=name, deterministic=deterministic,
matrix=matrix_gen, name=name, deterministic=deterministic,
random_state=random_state)


class _EmbossMatrixGenerator(object):
def __init__(self, alpha, strength):
self.alpha = alpha
self.strength = strength

def __call__(self, _image, nb_channels, random_state):
alpha_sample = self.alpha.draw_sample(random_state=random_state)
assert 0 <= alpha_sample <= 1.0, (
"Expected 'alpha' to be in the interval [0.0, 1.0], "
"got %.4f." % (alpha_sample,))
strength_sample = self.strength.draw_sample(random_state=random_state)
matrix_nochange = np.array([
[0, 0, 0],
[0, 1, 0],
[0, 0, 0]
], dtype=np.float32)
matrix_effect = np.array([
[-1-strength_sample, 0-strength_sample, 0],
[0-strength_sample, 1, 0+strength_sample],
[0, 0+strength_sample, 1+strength_sample]
], dtype=np.float32)
matrix = (
(1-alpha_sample) * matrix_nochange
+ alpha_sample * matrix_effect
)
return [matrix] * nb_channels


# TODO add tests
# TODO move this to edges.py?
class EdgeDetect(Convolve):
Expand Down Expand Up @@ -468,33 +480,39 @@ def __init__(self, alpha=0, name=None, deterministic=False,
alpha, "alpha",
value_range=(0, 1.0), tuple_to_uniform=True, list_to_choice=True)

def _create_matrices(_image, nb_channels, random_state_func):
alpha_sample = alpha_param.draw_sample(
random_state=random_state_func)
assert 0 <= alpha_sample <= 1.0, (
"Expected 'alpha' to be in the interval [0.0, 1.0], "
"got %.4f." % (alpha_sample,))
matrix_nochange = np.array([
[0, 0, 0],
[0, 1, 0],
[0, 0, 0]
], dtype=np.float32)
matrix_effect = np.array([
[0, 1, 0],
[1, -4, 1],
[0, 1, 0]
], dtype=np.float32)
matrix = (
(1-alpha_sample) * matrix_nochange
+ alpha_sample * matrix_effect
)
return [matrix] * nb_channels
matrix_gen = _EdgeDetectMatrixGenerator(alpha_param)

super(EdgeDetect, self).__init__(
matrix=_create_matrices, name=name, deterministic=deterministic,
matrix=matrix_gen, name=name, deterministic=deterministic,
random_state=random_state)


class _EdgeDetectMatrixGenerator(object):
def __init__(self, alpha):
self.alpha = alpha

def __call__(self, _image, nb_channels, random_state):
alpha_sample = self.alpha.draw_sample(random_state=random_state)
assert 0 <= alpha_sample <= 1.0, (
"Expected 'alpha' to be in the interval [0.0, 1.0], "
"got %.4f." % (alpha_sample,))
matrix_nochange = np.array([
[0, 0, 0],
[0, 1, 0],
[0, 0, 0]
], dtype=np.float32)
matrix_effect = np.array([
[0, 1, 0],
[1, -4, 1],
[0, 1, 0]
], dtype=np.float32)
matrix = (
(1-alpha_sample) * matrix_nochange
+ alpha_sample * matrix_effect
)
return [matrix] * nb_channels


# TODO add tests
# TODO merge EdgeDetect and DirectedEdgeDetect?
# TODO deprecate and rename to AngledEdgeDetect
Expand Down Expand Up @@ -588,52 +606,59 @@ def __init__(self, alpha=0, direction=(0.0, 1.0),
direction, "direction",
value_range=None, tuple_to_uniform=True, list_to_choice=True)

def _create_matrices(_image, nb_channels, random_state_func):
alpha_sample = alpha_param.draw_sample(
random_state=random_state_func)
assert 0 <= alpha_sample <= 1.0, (
"Expected 'alpha' to be in the interval [0.0, 1.0], "
"got %.4f." % (alpha_sample,))
direction_sample = direction_param.draw_sample(
random_state=random_state_func)

deg = int(direction_sample * 360) % 360
rad = np.deg2rad(deg)
x = np.cos(rad - 0.5*np.pi)
y = np.sin(rad - 0.5*np.pi)
direction_vector = np.array([x, y])

matrix_effect = np.array([
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
], dtype=np.float32)
for x, y in itertools.product([-1, 0, 1], [-1, 0, 1]):
if (x, y) != (0, 0):
cell_vector = np.array([x, y])
distance_deg = np.rad2deg(
ia.angle_between_vectors(cell_vector,
direction_vector))
distance = distance_deg / 180
similarity = (1 - distance)**4
matrix_effect[y+1, x+1] = similarity
matrix_effect = matrix_effect / np.sum(matrix_effect)
matrix_effect = matrix_effect * (-1)
matrix_effect[1, 1] = 1

matrix_nochange = np.array([
[0, 0, 0],
[0, 1, 0],
[0, 0, 0]
], dtype=np.float32)

matrix = (
(1-alpha_sample) * matrix_nochange
+ alpha_sample * matrix_effect
)

return [matrix] * nb_channels
matrix_gen = _DirectedEdgeDetectMatrixGenerator(alpha_param,
direction_param)

super(DirectedEdgeDetect, self).__init__(
matrix=_create_matrices, name=name, deterministic=deterministic,
matrix=matrix_gen, name=name, deterministic=deterministic,
random_state=random_state)


class _DirectedEdgeDetectMatrixGenerator(object):
def __init__(self, alpha, direction):
self.alpha = alpha
self.direction = direction

def __call__(self, _image, nb_channels, random_state):
alpha_sample = self.alpha.draw_sample(random_state=random_state)
assert 0 <= alpha_sample <= 1.0, (
"Expected 'alpha' to be in the interval [0.0, 1.0], "
"got %.4f." % (alpha_sample,))
direction_sample = self.direction.draw_sample(random_state=random_state)

deg = int(direction_sample * 360) % 360
rad = np.deg2rad(deg)
x = np.cos(rad - 0.5*np.pi)
y = np.sin(rad - 0.5*np.pi)
direction_vector = np.array([x, y])

matrix_effect = np.array([
[0, 0, 0],
[0, 0, 0],
[0, 0, 0]
], dtype=np.float32)
for x, y in itertools.product([-1, 0, 1], [-1, 0, 1]):
if (x, y) != (0, 0):
cell_vector = np.array([x, y])
distance_deg = np.rad2deg(
ia.angle_between_vectors(cell_vector,
direction_vector))
distance = distance_deg / 180
similarity = (1 - distance)**4
matrix_effect[y+1, x+1] = similarity
matrix_effect = matrix_effect / np.sum(matrix_effect)
matrix_effect = matrix_effect * (-1)
matrix_effect[1, 1] = 1

matrix_nochange = np.array([
[0, 0, 0],
[0, 1, 0],
[0, 0, 0]
], dtype=np.float32)

matrix = (
(1-alpha_sample) * matrix_nochange
+ alpha_sample * matrix_effect
)

return [matrix] * nb_channels
Loading
0