Unverified Commit 06556c84 authored by Qiaofei Li's avatar Qiaofei Li Committed by GitHub
Browse files

Add shear augmentation (#526)

* Add shear augmentation

* Update geometric.py

* Update geometric.py
parent 15b37b0b
......@@ -3,7 +3,7 @@ from .colorspace import (bgr2gray, bgr2hls, bgr2hsv, bgr2rgb, bgr2ycbcr,
gray2bgr, gray2rgb, hls2bgr, hsv2bgr, imconvert,
rgb2bgr, rgb2gray, rgb2ycbcr, ycbcr2bgr, ycbcr2rgb)
from .geometric import (imcrop, imflip, imflip_, impad, impad_to_multiple,
imrescale, imresize, imresize_like, imrotate,
imrescale, imresize, imresize_like, imrotate, imshear,
rescale_size)
from .io import imfrombytes, imread, imwrite, supported_backends, use_backend
from .misc import tensor2imgs
......@@ -17,5 +17,6 @@ __all__ = [
'impad', 'impad_to_multiple', 'imrotate', 'imfrombytes', 'imread',
'imwrite', 'supported_backends', 'use_backend', 'imdenormalize',
'imnormalize', 'imnormalize_', 'iminvert', 'posterize', 'solarize',
'rgb2ycbcr', 'bgr2ycbcr', 'ycbcr2rgb', 'ycbcr2bgr', 'tensor2imgs'
'rgb2ycbcr', 'bgr2ycbcr', 'ycbcr2rgb', 'ycbcr2bgr', 'tensor2imgs',
'imshear'
]
......@@ -460,3 +460,67 @@ def impad_to_multiple(img, divisor, pad_val=0):
pad_h = int(np.ceil(img.shape[0] / divisor)) * divisor
pad_w = int(np.ceil(img.shape[1] / divisor)) * divisor
return impad(img, shape=(pad_h, pad_w))
def _get_shear_matrix(magnitude, direction='horizontal'):
"""Generate the shear matrix for transformation.
Args:
magnitude (int | float): The magnitude used for shear.
direction (str): Thie flip direction, either "horizontal"
or "vertical".
Returns:
ndarray: The shear matrix with dtype float32.
"""
if direction == 'horizontal':
shear_matrix = np.float32([[1, magnitude, 0], [0, 1, 0]])
elif direction == 'vertical':
shear_matrix = np.float32([[1, 0, 0], [magnitude, 1, 0]])
return shear_matrix
def imshear(img,
magnitude,
direction='horizontal',
border_value=0,
interpolation='bilinear'):
"""Shear an image.
Args:
img (ndarray): Image to be sheared with format (h, w)
or (h, w, c).
magnitude (int | float): The magnitude used for shear.
direction (str): Thie flip direction, either "horizontal"
or "vertical".
border_value (int | tuple[int]): Value used in case of a
constant border.
interpolation (str): Same as :func:`resize`.
Returns:
ndarray: The sheared image.
"""
assert direction in ['horizontal',
'vertical'], f'Invalid direction: {direction}'
height, width = img.shape[:2]
if img.ndim == 2:
channels = 1
elif img.ndim == 3:
channels = img.shape[-1]
if isinstance(border_value, int):
border_value = tuple([border_value] * channels)
elif isinstance(border_value, tuple):
assert len(border_value) == channels, \
'Expected the num of elements in tuple equals the channels' \
'of input image. Found {} vs {}'.format(
len(border_value), channels)
else:
raise ValueError(
f'Invalid type {type(border_value)} for `border_value`')
shear_matrix = _get_shear_matrix(magnitude, direction)
sheared = cv2.warpAffine(
img,
shear_matrix, (width, height),
borderValue=border_value,
flags=cv2_interp_codes[interpolation])
return sheared
......@@ -443,3 +443,44 @@ class TestGeometric:
with pytest.raises(ValueError):
mmcv.imrotate(img, 90, center=(0, 0), auto_bound=True)
def test_imshear(self):
img = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]).astype(np.uint8)
assert_array_equal(mmcv.imshear(img, 0), img)
# magnitude=1, horizontal
img_sheared = np.array([[1, 2, 3], [0, 4, 5], [0, 0, 7]],
dtype=np.uint8)
assert_array_equal(mmcv.imshear(img, 1), img_sheared)
# magnitude=-1, vertical
img_sheared = np.array([[1, 5, 9], [4, 8, 0], [7, 0, 0]],
dtype=np.uint8)
assert_array_equal(mmcv.imshear(img, -1, 'vertical'), img_sheared)
# magnitude=1, vertical, borderValue=100
borderValue = 100
img_sheared = np.array(
[[1, borderValue, borderValue], [4, 2, borderValue], [7, 5, 3]],
dtype=np.uint8)
assert_array_equal(
mmcv.imshear(img, 1, 'vertical', borderValue), img_sheared)
# magnitude=1, vertical, borderValue=100, img shape (h,w,3)
img = np.stack([img, img, img], axis=-1)
img_sheared = np.stack([img_sheared, img_sheared, img_sheared],
axis=-1)
assert_array_equal(
mmcv.imshear(img, 1, 'vertical', borderValue), img_sheared)
# test tuple format of borderValue
assert_array_equal(
mmcv.imshear(img, 1, 'vertical',
(borderValue, borderValue, borderValue)), img_sheared)
# test invalid length of borderValue
with pytest.raises(AssertionError):
mmcv.imshear(img, 0.5, 'horizontal', (borderValue, ))
# test invalid type of borderValue
with pytest.raises(ValueError):
mmcv.imshear(img, 0.5, 'horizontal', [borderValue])
# test invalid value of direction
with pytest.raises(AssertionError):
mmcv.imshear(img, 0.5, 'diagonal')
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment