tensorlayer3/tensorlayer/dataflow/mindspore_image.py

306 lines
8.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import mindspore.dataset as ms
import mindspore.dataset.vision.c_transforms as c_vision
import mindspore.dataset.vision.py_transforms as py_vision
import mindspore.dataset.vision.py_transforms_util as py_util
import numpy as np
from PIL import Image, ImageOps, ImageEnhance, __version__
__all__ = [
'CentralCrop', 'HsvToRgb', 'AdjustBrightness', 'AdjustContrast', 'AdjustHue', 'Crop', 'FlipHorizontal',
'FlipVertical', 'GrayToRgb', 'RgbToGray', 'PadToBoundingBox'
]
augment_error_message = 'img should be PIL image. Got {}. Use Decode() for encoded data or ToPIL() for decoded data.'
def CentralCrop(image, central_fraction=None, size=None):
'''
Parameters
----------
image :
input Either a 3-D float Tensor of shape [height, width, depth],
or a 4-D Tensor of shape [batch_size, height, width, depth].
central_fraction :
float (0, 1], fraction of size to crop
size:
size (Union[int, sequence]) The output size of the cropped image. If size is an integer, a square crop of size (size, size) is returned.
If size is a sequence of length 2, it should be (height, width).
Returns :
3-D / 4-D float Tensor, as per the input.
-------
'''
if size is None and central_fraction is None:
raise ValueError('central_fraction and size can not be both None')
if size is None:
outshape = np.shape(image)
if len(outshape) == 3:
h_axis = 0
w_axis = 1
elif len(outshape) == 4:
h_axis = 1
w_axis = 2
height = outshape[h_axis]
width = outshape[w_axis]
target_height = height * central_fraction
target_width = width * central_fraction
size = (target_height, target_width)
return py_util.center_crop(image, size)
def HsvToRgb(image, is_hwc=True):
image = np.asarray(image)
return py_util.hsv_to_rgbs(image, is_hwc=is_hwc)
def AdjustBrightness(image, factor):
'''
Parameters
----------
image:
input NumPy image array or PIL image
factor:
factor should be in the range (-1,1)
Returns:
-------
np darray image
'''
image = np.asarray(image)
image = image / 255
image = image + factor
index = np.where(image > 1)
image[index] = 1
index = np.where(image < 0)
image[index] = 0
image = image * 255
return image
def AdjustContrast(image, factor):
if isinstance(image, np.ndarray):
image = Image.fromarray(image)
if not isinstance(image, Image.Image):
raise TypeError(augment_error_message.format(type(image)))
image = ImageEnhance.Contrast(image).enhance(factor)
image = np.array(image)
return image
def AdjustHue(image, factor):
if isinstance(image, np.ndarray):
image = Image.fromarray(image)
if not isinstance(image, Image.Image):
raise TypeError(augment_error_message.format(type(image)))
image_hue_factor = factor
if not -1 <= image_hue_factor <= 1:
raise ValueError('image_hue_factor {} is not in [-1, 1].'.format(image_hue_factor))
if not isinstance(image, Image.Image):
raise TypeError(augment_error_message.format(type(image)))
mode = image.mode
if mode in {'L', '1', 'I', 'F'}:
return image
hue, saturation, value = image.convert('HSV').split()
np_hue = np.array(hue, dtype=np.uint8)
with np.errstate(over='ignore'):
np_hue += np.uint8(image_hue_factor * 255)
hue = Image.fromarray(np_hue, 'L')
image = Image.merge('HSV', (hue, saturation, value)).convert(mode)
return image
def AdjustSaturation(image, factor):
if isinstance(image, np.ndarray):
image = Image.fromarray(image)
if not isinstance(image, Image.Image):
raise TypeError(augment_error_message.format(type(image)))
enhancer = ImageEnhance.Color(image)
image = enhancer.enhance(factor)
return image
def Crop(image, offset_height, offset_width, target_height, target_width):
if isinstance(image, np.ndarray):
image = Image.fromarray(image)
if not isinstance(image, Image.Image):
raise TypeError(augment_error_message.format(type(image)))
image = np.array(
image.crop((offset_width, offset_height, offset_width + target_width, offset_width + target_height))
)
return image
def FlipHorizontal(image):
if isinstance(image, np.ndarray):
image = Image.fromarray(image)
if not isinstance(image, Image.Image):
raise TypeError(augment_error_message.format(type(image)))
image = np.array(image.transpose(Image.FLIP_LEFT_RIGHT))
return image
def FlipVertical(image):
if isinstance(image, np.ndarray):
image = Image.fromarray(image)
if not isinstance(image, Image.Image):
raise TypeError(augment_error_message.format(type(image)))
image = np.array(image.transpose(Image.FLIP_TOP_BOTTOM))
return image
def GrayToRgb(image):
image = np.asarray(image)
shape = image.shape
output_image = np.zeros((shape[0], shape[1], 3), dtype=np.uint8)
if len(shape) == 3:
for i in range(3):
output_image[:, :, i] = image[:, :, 1]
elif len(shape) == 2:
for i in range(3):
output_image[:, :, i] = image
return output_image
def RgbToGray(image):
if isinstance(image, np.ndarray):
image = Image.fromarray(image)
if not isinstance(image, Image.Image):
raise TypeError(augment_error_message.format(type(image)))
'''
将彩色图像转换为灰度模式“L”库使用ITU-R 601-2 Luma转换
L = R * 299/1000 + G * 587/1000 + B * 114/1000
'''
image = image.convert('L')
image = np.asarray(image)
return image
def PadToBoundingBox(image, offset_height, offset_width, target_height, target_width):
'''
Parameters
----------
image:
A PIL image
offset_height:
Number of rows of zeros to add on top.
offset_width:
Number of columns of zeros to add on the left.
target_height:
Height of output image.
target_width
Width of output image.
Returns
A numpy ndarray image
-------
'''
if offset_height < 0:
raise ValueError("offset_height must be >= 0")
if offset_width < 0:
raise ValueError("offset_width must be >= 0")
image = np.array(image)
shape = image.shape
top = offset_height
bottom = target_height - shape[0] - top
left = offset_width
right = target_width - shape[1] - left
if bottom < 0:
raise ValueError("target_height must be >= offset_height + height")
if right < 0:
raise ValueError("target_width must be >= offset_width + width")
return np.pad(image, ((top, bottom), (left, right), (0, 0)), mode='constant')
def Standardization(image, mean=None, std=None, channel_mode=False):
'''
Parameters
----------
image:
An n-D Tensor with at least 3 dimensions, the last 3 of which are the dimensions of each image.
mean:
List or tuple of mean values for each channel, with respect to channel order.
std:
List or tuple of standard deviations for each channel.
channel_mode:
Decide to implement standardization on whole image or each channel of image.
Returns:
A Tensor with the same shape and dtype as image.
-------
'''
image = np.array(image, dtype=np.float32)
num_shape = image.shape
if mean is not None and std is not None:
if len(mean) != len(std):
raise ValueError("Length of mean and std must be equal")
if len(mean) == 1:
mean = [mean[0]] * num_shape[2]
std = [std[0]] * num_shape[2]
mean = np.array(mean, dtype=image.dtype)
std = np.array(std, dtype=image.dtype)
return (image - mean[:, None, None]) / std[:, None, None]
elif mean is None and std is None:
if channel_mode:
num_pixels = num_shape[0] * num_shape[1]
image_mean = np.mean(image, axis=(0, 1))
stddev = np.std(image, axis=(0, 1))
min_sttdev = 1 / np.sqrt(num_pixels)
min_sttdev = [min_sttdev] * num_shape[2]
adjusted_sttdev = np.maximum(stddev, min_sttdev)
image -= image_mean
image = np.divide(image, adjusted_sttdev)
return image
else:
num_pixels = num_shape[0] * num_shape[1] * num_shape[2]
image_mean = np.mean(image, axis=(0, 1, 2))
image_mean = [image_mean] * 3
stddev = np.std(image, axis=(0, 1, 2))
min_sttdev = 1 / np.sqrt(num_pixels)
adjusted_sttdev = np.maximum(stddev, min_sttdev)
adjusted_sttdev = [adjusted_sttdev] * 3
image -= image_mean
image = np.divide(image, adjusted_sttdev)
return image
else:
raise ValueError('std and mean must both be None or not None')