248 Star 847 Fork 51

MindSpore / mindarmour

Create your Gitee Account
Explore and code with more than 6 million developers,Free private repositories !:)
Sign up
Clone or download
image_transform.py 19.60 KB
Copy Edit Web IDE Raw Blame History
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609
# Copyright 2019 Huawei Technologies Co., Ltd
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""
Image transform
"""
import numpy as np
from PIL import Image, ImageEnhance, ImageFilter
from mindspore.dataset.vision.py_transforms_util import is_numpy, \
to_pil, hwc_to_chw
from mindarmour.utils._check_param import check_param_multi_types, check_param_in_range, check_numpy_param
from mindarmour.utils.logger import LogUtil
LOGGER = LogUtil.get_instance()
TAG = 'Image Transformation'
def chw_to_hwc(img):
"""
Transpose the input image; shape (C, H, W) to shape (H, W, C).
Args:
img (numpy.ndarray): Image to be converted.
Returns:
img (numpy.ndarray), Converted image.
"""
if is_numpy(img):
return img.transpose(1, 2, 0).copy()
raise TypeError('img should be numpy.ndarray. Got {}'.format(type(img)))
def is_hwc(img):
"""
Check if the input image is shape (H, W, C).
Args:
img (numpy.ndarray): Image to be checked.
Returns:
Bool, True if input is shape (H, W, C).
"""
if is_numpy(img):
img_shape = np.shape(img)
if img_shape[2] == 3 and img_shape[1] > 3 and img_shape[0] > 3:
return True
return False
raise TypeError('img should be numpy.ndarray. Got {}'.format(type(img)))
def is_chw(img):
"""
Check if the input image is shape (H, W, C).
Args:
img (numpy.ndarray): Image to be checked.
Returns:
Bool, True if input is shape (H, W, C).
"""
if is_numpy(img):
img_shape = np.shape(img)
if img_shape[0] == 3 and img_shape[1] > 3 and img_shape[2] > 3:
return True
return False
raise TypeError('img should be numpy.ndarray. Got {}'.format(type(img)))
def is_rgb(img):
"""
Check if the input image is RGB.
Args:
img (numpy.ndarray): Image to be checked.
Returns:
Bool, True if input is RGB.
"""
if is_numpy(img):
img_shape = np.shape(img)
if len(np.shape(img)) == 3 and (img_shape[0] == 3 or img_shape[2] == 3):
return True
return False
raise TypeError('img should be numpy.ndarray. Got {}'.format(type(img)))
def is_normalized(img):
"""
Check if the input image is normalized between 0 to 1.
Args:
img (numpy.ndarray): Image to be checked.
Returns:
Bool, True if input is normalized between 0 to 1.
"""
if is_numpy(img):
minimal = np.min(img)
maximun = np.max(img)
if minimal >= 0 and maximun <= 1:
return True
return False
raise TypeError('img should be Numpy array. Got {}'.format(type(img)))
class ImageTransform:
"""
The abstract base class for all image transform classes.
"""
def __init__(self):
pass
def _check(self, image):
""" Check image format. If input image is RGB and its shape
is (C, H, W), it will be transposed to (H, W, C). If the value
of the image is not normalized , it will be normalized between 0 to 1."""
rgb = is_rgb(image)
chw = False
gray3dim = False
normalized = is_normalized(image)
if rgb:
chw = is_chw(image)
if chw:
image = chw_to_hwc(image)
else:
image = image
else:
if len(np.shape(image)) == 3:
gray3dim = True
image = image[0]
else:
image = image
if normalized:
image = image*255
return rgb, chw, normalized, gray3dim, np.uint8(image)
def _original_format(self, image, chw, normalized, gray3dim):
""" Return transformed image with original format. """
if not is_numpy(image):
image = np.array(image)
if chw:
image = hwc_to_chw(image)
if normalized:
image = image / 255
if gray3dim:
image = np.expand_dims(image, 0)
return image
def transform(self, image):
pass
class Contrast(ImageTransform):
"""
Contrast of an image.
Args:
factor (Union[float, int]): Control the contrast of an image. If 1.0,
gives the original image. If 0, gives a gray image. Default: 1.
"""
def __init__(self, factor=1):
super(Contrast, self).__init__()
self.set_params(factor)
def set_params(self, factor=1, auto_param=False):
"""
Set contrast parameters.
Args:
factor (Union[float, int]): Control the contrast of an image. If 1.0
gives the original image. If 0 gives a gray image. Default: 1.
auto_param (bool): True if auto generate parameters. Default: False.
"""
if auto_param:
self.factor = np.random.uniform(-5, 5)
else:
self.factor = check_param_multi_types('factor', factor, [int, float])
def transform(self, image):
"""
Transform the image.
Args:
image (numpy.ndarray): Original image to be transformed.
Returns:
numpy.ndarray, transformed image.
"""
image = check_numpy_param('image', image)
ori_dtype = image.dtype
_, chw, normalized, gray3dim, image = self._check(image)
image = to_pil(image)
img_contrast = ImageEnhance.Contrast(image)
trans_image = img_contrast.enhance(self.factor)
trans_image = self._original_format(trans_image, chw, normalized,
gray3dim)
return trans_image.astype(ori_dtype)
class Brightness(ImageTransform):
"""
Brightness of an image.
Args:
factor (Union[float, int]): Control the brightness of an image. If 1.0
gives the original image. If 0 gives a black image. Default: 1.
"""
def __init__(self, factor=1):
super(Brightness, self).__init__()
self.set_params(factor)
def set_params(self, factor=1, auto_param=False):
"""
Set brightness parameters.
Args:
factor (Union[float, int]): Control the brightness of an image. If 1
gives the original image. If 0 gives a black image. Default: 1.
auto_param (bool): True if auto generate parameters. Default: False.
"""
if auto_param:
self.factor = np.random.uniform(0, 5)
else:
self.factor = check_param_multi_types('factor', factor, [int, float])
def transform(self, image):
"""
Transform the image.
Args:
image (numpy.ndarray): Original image to be transformed.
Returns:
numpy.ndarray, transformed image.
"""
image = check_numpy_param('image', image)
ori_dtype = image.dtype
_, chw, normalized, gray3dim, image = self._check(image)
image = to_pil(image)
img_contrast = ImageEnhance.Brightness(image)
trans_image = img_contrast.enhance(self.factor)
trans_image = self._original_format(trans_image, chw, normalized,
gray3dim)
return trans_image.astype(ori_dtype)
class Blur(ImageTransform):
"""
Blurs the image using Gaussian blur filter.
Args:
radius(Union[float, int]): Blur radius, 0 means no blur. Default: 0.
"""
def __init__(self, radius=0):
super(Blur, self).__init__()
self.set_params(radius)
def set_params(self, radius=0, auto_param=False):
"""
Set blur parameters.
Args:
radius (Union[float, int]): Blur radius, 0 means no blur. Default: 0.
auto_param (bool): True if auto generate parameters. Default: False.
"""
if auto_param:
self.radius = np.random.uniform(-1.5, 1.5)
else:
self.radius = check_param_multi_types('radius', radius, [int, float])
def transform(self, image):
"""
Transform the image.
Args:
image (numpy.ndarray): Original image to be transformed.
Returns:
numpy.ndarray, transformed image.
"""
image = check_numpy_param('image', image)
ori_dtype = image.dtype
_, chw, normalized, gray3dim, image = self._check(image)
image = to_pil(image)
trans_image = image.filter(ImageFilter.GaussianBlur(radius=self.radius))
trans_image = self._original_format(trans_image, chw, normalized,
gray3dim)
return trans_image.astype(ori_dtype)
class Noise(ImageTransform):
"""
Add noise of an image.
Args:
factor (float): factor is the ratio of pixels to add noise.
If 0 gives the original image. Default 0.
"""
def __init__(self, factor=0):
super(Noise, self).__init__()
self.set_params(factor)
def set_params(self, factor=0, auto_param=False):
"""
Set noise parameters.
Args:
factor (Union[float, int]): factor is the ratio of pixels to
add noise. If 0 gives the original image. Default 0.
auto_param (bool): True if auto generate parameters. Default: False.
"""
if auto_param:
self.factor = np.random.uniform(0, 1)
else:
self.factor = check_param_multi_types('factor', factor, [int, float])
def transform(self, image):
"""
Transform the image.
Args:
image (numpy.ndarray): Original image to be transformed.
Returns:
numpy.ndarray, transformed image.
"""
image = check_numpy_param('image', image)
ori_dtype = image.dtype
_, chw, normalized, gray3dim, image = self._check(image)
noise = np.random.uniform(low=-1, high=1, size=np.shape(image))
trans_image = np.copy(image)
threshold = 1 - self.factor
trans_image[noise < -threshold] = 0
trans_image[noise > threshold] = 1
trans_image = self._original_format(trans_image, chw, normalized,
gray3dim)
return trans_image.astype(ori_dtype)
class Translate(ImageTransform):
"""
Translate an image.
Args:
x_bias (Union[int, float]): X-direction translation, x = x + x_bias*image_length.
Default: 0.
y_bias (Union[int, float]): Y-direction translation, y = y + y_bias*image_wide.
Default: 0.
"""
def __init__(self, x_bias=0, y_bias=0):
super(Translate, self).__init__()
self.set_params(x_bias, y_bias)
def set_params(self, x_bias=0, y_bias=0, auto_param=False):
"""
Set translate parameters.
Args:
x_bias (Union[float, int]): X-direction translation, and x_bias should be in range of (-1, 1). Default: 0.
y_bias (Union[float, int]): Y-direction translation, and y_bias should be in range of (-1, 1). Default: 0.
auto_param (bool): True if auto generate parameters. Default: False.
"""
x_bias = check_param_in_range('x_bias', x_bias, -1, 1)
y_bias = check_param_in_range('y_bias', y_bias, -1, 1)
self.auto_param = auto_param
if auto_param:
self.x_bias = np.random.uniform(-0.3, 0.3)
self.y_bias = np.random.uniform(-0.3, 0.3)
else:
self.x_bias = check_param_multi_types('x_bias', x_bias,
[int, float])
self.y_bias = check_param_multi_types('y_bias', y_bias,
[int, float])
def transform(self, image):
"""
Transform the image.
Args:
image(numpy.ndarray): Original image to be transformed.
Returns:
numpy.ndarray, transformed image.
"""
image = check_numpy_param('image', image)
ori_dtype = image.dtype
_, chw, normalized, gray3dim, image = self._check(image)
img = to_pil(image)
image_shape = np.shape(image)
self.x_bias = image_shape[1]*self.x_bias
self.y_bias = image_shape[0]*self.y_bias
trans_image = img.transform(img.size, Image.AFFINE,
(1, 0, self.x_bias, 0, 1, self.y_bias))
trans_image = self._original_format(trans_image, chw, normalized,
gray3dim)
return trans_image.astype(ori_dtype)
class Scale(ImageTransform):
"""
Scale an image in the middle.
Args:
factor_x (Union[float, int]): Rescale in X-direction, x=factor_x*x.
Default: 1.
factor_y (Union[float, int]): Rescale in Y-direction, y=factor_y*y.
Default: 1.
"""
def __init__(self, factor_x=1, factor_y=1):
super(Scale, self).__init__()
self.set_params(factor_x, factor_y)
def set_params(self, factor_x=1, factor_y=1, auto_param=False):
"""
Set scale parameters.
Args:
factor_x (Union[float, int]): Rescale in X-direction, x=factor_x*x.
Default: 1.
factor_y (Union[float, int]): Rescale in Y-direction, y=factor_y*y.
Default: 1.
auto_param (bool): True if auto generate parameters. Default: False.
"""
if auto_param:
self.factor_x = np.random.uniform(0.7, 3)
self.factor_y = np.random.uniform(0.7, 3)
else:
self.factor_x = check_param_multi_types('factor_x', factor_x,
[int, float])
self.factor_y = check_param_multi_types('factor_y', factor_y,
[int, float])
def transform(self, image):
"""
Transform the image.
Args:
image(numpy.ndarray): Original image to be transformed.
Returns:
numpy.ndarray, transformed image.
"""
image = check_numpy_param('image', image)
ori_dtype = image.dtype
rgb, chw, normalized, gray3dim, image = self._check(image)
if rgb:
h, w, _ = np.shape(image)
else:
h, w = np.shape(image)
move_x_centor = w / 2*(1 - self.factor_x)
move_y_centor = h / 2*(1 - self.factor_y)
img = to_pil(image)
trans_image = img.transform(img.size, Image.AFFINE,
(self.factor_x, 0, move_x_centor,
0, self.factor_y, move_y_centor))
trans_image = self._original_format(trans_image, chw, normalized,
gray3dim)
return trans_image.astype(ori_dtype)
class Shear(ImageTransform):
"""
Shear an image, for each pixel (x, y) in the sheared image, the new value is
taken from a position (x+factor_x*y, factor_y*x+y) in the origin image. Then
the sheared image will be rescaled to fit original size.
Args:
factor_x (Union[float, int]): Shear factor of horizontal direction.
Default: 0.
factor_y (Union[float, int]): Shear factor of vertical direction.
Default: 0.
"""
def __init__(self, factor_x=0, factor_y=0):
super(Shear, self).__init__()
self.set_params(factor_x, factor_y)
def set_params(self, factor_x=0, factor_y=0, auto_param=False):
"""
Set shear parameters.
Args:
factor_x (Union[float, int]): Shear factor of horizontal direction.
Default: 0.
factor_y (Union[float, int]): Shear factor of vertical direction.
Default: 0.
auto_param (bool): True if auto generate parameters. Default: False.
"""
if factor_x != 0 and factor_y != 0:
msg = 'At least one of factor_x and factor_y is zero.'
LOGGER.error(TAG, msg)
raise ValueError(msg)
if auto_param:
if np.random.uniform(-1, 1) > 0:
self.factor_x = np.random.uniform(-2, 2)
self.factor_y = 0
else:
self.factor_x = 0
self.factor_y = np.random.uniform(-2, 2)
else:
self.factor_x = check_param_multi_types('factor', factor_x,
[int, float])
self.factor_y = check_param_multi_types('factor', factor_y,
[int, float])
def transform(self, image):
"""
Transform the image.
Args:
image(numpy.ndarray): Original image to be transformed.
Returns:
numpy.ndarray, transformed image.
"""
image = check_numpy_param('image', image)
ori_dtype = image.dtype
rgb, chw, normalized, gray3dim, image = self._check(image)
img = to_pil(image)
if rgb:
h, w, _ = np.shape(image)
else:
h, w = np.shape(image)
if self.factor_x != 0:
boarder_x = [0, -w, -self.factor_x*h, -w - self.factor_x*h]
min_x = min(boarder_x)
max_x = max(boarder_x)
scale = (max_x - min_x) / w
move_x_cen = (w - scale*w - scale*h*self.factor_x) / 2
move_y_cen = h*(1 - scale) / 2
else:
boarder_y = [0, -h, -self.factor_y*w, -h - self.factor_y*w]
min_y = min(boarder_y)
max_y = max(boarder_y)
scale = (max_y - min_y) / h
move_y_cen = (h - scale*h - scale*w*self.factor_y) / 2
move_x_cen = w*(1 - scale) / 2
trans_image = img.transform(img.size, Image.AFFINE,
(scale, scale*self.factor_x, move_x_cen,
scale*self.factor_y, scale, move_y_cen))
trans_image = self._original_format(trans_image, chw, normalized,
gray3dim)
return trans_image.astype(ori_dtype)
class Rotate(ImageTransform):
"""
Rotate an image of degrees counter clockwise around its center.
Args:
angle(Union[float, int]): Degrees counter clockwise. Default: 0.
"""
def __init__(self, angle=0):
super(Rotate, self).__init__()
self.set_params(angle)
def set_params(self, angle=0, auto_param=False):
"""
Set rotate parameters.
Args:
angle(Union[float, int]): Degrees counter clockwise. Default: 0.
auto_param (bool): True if auto generate parameters. Default: False.
"""
if auto_param:
self.angle = np.random.uniform(0, 360)
else:
self.angle = check_param_multi_types('angle', angle, [int, float])
def transform(self, image):
"""
Transform the image.
Args:
image(numpy.ndarray): Original image to be transformed.
Returns:
numpy.ndarray, transformed image.
"""
image = check_numpy_param('image', image)
ori_dtype = image.dtype
_, chw, normalized, gray3dim, image = self._check(image)
img = to_pil(image)
trans_image = img.rotate(self.angle, expand=False)
trans_image = self._original_format(trans_image, chw, normalized,
gray3dim)
return trans_image.astype(ori_dtype)
Python
1
https://gitee.com/mindspore/mindarmour.git
git@gitee.com:mindspore/mindarmour.git
mindspore
mindarmour
mindarmour
master

Search

102255 3a0e046c 1850385 102255 7aaa926c 1850385