256 Star 931 Fork 105

MindSpore / mindarmour

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
image_transform.py 18.78 KB
一键复制 编辑 原始数据 按行查看 历史
jxl 提交于 2020-12-24 10:27 . Fix two bugs.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
# 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
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 = np.uint8(image*255)
return rgb, chw, normalized, gray3dim, 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.
"""
_, 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
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.
"""
_, 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
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.
"""
_, 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
class Noise(ImageTransform):
"""
Add noise of an image.
Args:
factor (float): 1 - 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]): 1 - 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.7, 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.
"""
_, chw, normalized, gray3dim, image = self._check(image)
noise = np.random.uniform(low=-1, high=1, size=np.shape(image))
trans_image = np.copy(image)
trans_image[noise < -self.factor] = 0
trans_image[noise > self.factor] = 1
trans_image = self._original_format(trans_image, chw, normalized,
gray3dim)
return trans_image
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.
"""
_, 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
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.
"""
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
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.
"""
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
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.
"""
_, 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
Python
1
https://gitee.com/mindspore/mindarmour.git
git@gitee.com:mindspore/mindarmour.git
mindspore
mindarmour
mindarmour
r1.1

搜索帮助