def crop(x, wrg, hrg, is_random=False, row_index=0, col_index=1):
    """Randomly or centrally crop an image.

    Parameters
    ----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    wrg : int
        Size of width.
    hrg : int
        Size of height.
    is_random : boolean,
        If True, randomly crop, else central crop. Default is False.
    row_index: int
        index of row.
    col_index: int
        index of column.

    Returns
    -------
    numpy.array
        A processed image.

    """
    h, w = x.shape[row_index], x.shape[col_index]

    if (h < hrg) or (w < wrg):
        raise AssertionError("The size of cropping should smaller than or equal to the original image")

    if is_random:
        h_offset = int(np.random.uniform(0, h - hrg))
        w_offset = int(np.random.uniform(0, w - wrg))
        # tl.logging.info(h_offset, w_offset, x[h_offset: hrg+h_offset ,w_offset: wrg+w_offset].shape)
        return x[h_offset:hrg + h_offset, w_offset:wrg + w_offset]
    else:  # central crop
        h_offset = int(np.floor((h - hrg) / 2.))
        w_offset = int(np.floor((w - wrg) / 2.))
        h_end = h_offset + hrg
        w_end = w_offset + wrg
        return x[h_offset:h_end, w_offset:w_end]


def crop_multi(x, wrg, hrg, is_random=False, row_index=0, col_index=1):
    """Randomly or centrally crop multiple images.

    Parameters
    ----------
    x : list of numpy.array
        List of images with dimension of [n_images, row, col, channel] (default).
    others : args
        See ``tl.prepro.crop``.

    Returns
    -------
    numpy.array
        A list of processed images.

    """
    h, w = x[0].shape[row_index], x[0].shape[col_index]

    if (h < hrg) or (w < wrg):
        raise AssertionError("The size of cropping should smaller than or equal to the original image")

    if is_random:
        h_offset = int(np.random.uniform(0, h - hrg))
        w_offset = int(np.random.uniform(0, w - wrg))
        results = []
        for data in x:
            results.append(data[h_offset:hrg + h_offset, w_offset:wrg + w_offset])
        return np.asarray(results)
    else:
        # central crop
        h_offset = (h - hrg) / 2
        w_offset = (w - wrg) / 2
        results = []
        for data in x:
            results.append(data[h_offset:h - h_offset, w_offset:w - w_offset])
        return np.asarray(results)

Randomly or centrally crop multiple images .


def flip_axis(x, axis=1, is_random=False):
    """Flip the axis of an image, such as flip left and right, up and down, randomly or non-randomly,

    Parameters
    ----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    axis : int
        Which axis to flip.
            - 0, flip up and down
            - 1, flip left and right
            - 2, flip channel
    is_random : boolean
        If True, randomly flip. Default is False.

    Returns
    -------
    numpy.array
        A processed image.

    """
    if is_random:
        factor = np.random.uniform(-1, 1)
        if factor > 0:
            x = np.asarray(x).swapaxes(axis, 0)
            x = x[::-1, ...]
            x = x.swapaxes(0, axis)
            return x
        else:
            return x
    else:
        x = np.asarray(x).swapaxes(axis, 0)
        x = x[::-1, ...]
        x = x.swapaxes(0, axis)
        return x

def flip_axis ( x , axis = 1 , is_random = False ) : if is_random : factor = np . random . uniform ( - 1 , 1 ) if factor > 0 : x = np . asarray ( x ) . swapaxes ( axis , 0 ) x = x [ : : - 1 , ... ] x = x . swapaxes ( 0 , axis ) return x else : return x else : x = np . asarray ( x ) . swapaxes ( axis , 0 ) x = x [ : : - 1 , ... ] x = x . swapaxes ( 0 , axis ) return x

Flip the axis of an image such as flip left and right up and down randomly or non - randomly


def flip_axis_multi(x, axis, is_random=False):
    """Flip the axises of multiple images together, such as flip left and right, up and down, randomly or non-randomly,

    Parameters
    -----------
    x : list of numpy.array
        List of images with dimension of [n_images, row, col, channel] (default).
    others : args
        See ``tl.prepro.flip_axis``.

    Returns
    -------
    numpy.array
        A list of processed images.

    """
    if is_random:
        factor = np.random.uniform(-1, 1)
        if factor > 0:
            # x = np.asarray(x).swapaxes(axis, 0)
            # x = x[::-1, ...]
            # x = x.swapaxes(0, axis)
            # return x
            results = []
            for data in x:
                data = np.asarray(data).swapaxes(axis, 0)
                data = data[::-1, ...]
                data = data.swapaxes(0, axis)
                results.append(data)
            return np.asarray(results)
        else:
            return np.asarray(x)
    else:
        # x = np.asarray(x).swapaxes(axis, 0)
        # x = x[::-1, ...]
        # x = x.swapaxes(0, axis)
        # return x
        results = []
        for data in x:
            data = np.asarray(data).swapaxes(axis, 0)
            data = data[::-1, ...]
            data = data.swapaxes(0, axis)
            results.append(data)
        return np.asarray(results)

def
flip_axis_multi
(
x
,
axis
,
is_random
=
False
)
:
if
is_random
:
factor
=
np
.
random
.
uniform
(
1
,
1
)
if
factor
>
0
:
# x = np.asarray(x).swapaxes(axis, 0)
# x = x[::-1, ...]
# x = x.swapaxes(0, axis)
# return x
results
=
[
]
for
data
in
x
:
data
=
np
.
asarray
(
data
)
.
swapaxes
(
axis
,
0
)
data
=
data
[
:
:
1
,
...
]
data
=
data
.
swapaxes
(
0
,
axis
)
results
.
append
(
data
)
return
np
.
asarray
(
results
)
else
:
return
np
.
asarray
(
x
)
else
:
# x = np.asarray(x).swapaxes(axis, 0)
# x = x[::-1, ...]
# x = x.swapaxes(0, axis)
# return x
results
=
[
]
for
data
in
x
:
data
=
np
.
asarray
(
data
)
.
swapaxes
(
axis
,
0
)
data
=
data
[
:
:
1
,
...
]
data
=
data
.
swapaxes
(
0
,
axis
)
results
.
append
(
data
)
return
np
.
asarray
(
results
)

Flip the axises of multiple images together such as flip left and right up and down randomly or non - randomly


def shift(
        x, wrg=0.1, hrg=0.1, is_random=False, row_index=0, col_index=1, channel_index=2, fill_mode='nearest', cval=0.,
        order=1
):
    """Shift an image randomly or non-randomly.

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    wrg : float
        Percentage of shift in axis x, usually -0.25 ~ 0.25.
    hrg : float
        Percentage of shift in axis y, usually -0.25 ~ 0.25.
    is_random : boolean
        If True, randomly shift. Default is False.
    row_index col_index and channel_index : int
        Index of row, col and channel, default (0, 1, 2), for theano (1, 2, 0).
    fill_mode : str
        Method to fill missing pixel, default `nearest`, more options `constant`, `reflect` or `wrap`, see `scipy ndimage affine_transform <https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.ndimage.interpolation.affine_transform.html>`__
    cval : float
        Value used for points outside the boundaries of the input if mode='constant'. Default is 0.0.
    order : int
        The order of interpolation. The order has to be in the range 0-5. See ``tl.prepro.affine_transform`` and `scipy ndimage affine_transform <https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.ndimage.interpolation.affine_transform.html>`__

    Returns
    -------
    numpy.array
        A processed image.

    """
    h, w = x.shape[row_index], x.shape[col_index]
    if is_random:
        tx = np.random.uniform(-hrg, hrg) * h
        ty = np.random.uniform(-wrg, wrg) * w
    else:
        tx, ty = hrg * h, wrg * w
    translation_matrix = np.array([[1, 0, tx], [0, 1, ty], [0, 0, 1]])

    transform_matrix = translation_matrix  # no need to do offset
    x = affine_transform(x, transform_matrix, channel_index, fill_mode, cval, order)
    return x

def
shift
(
x
,
wrg
=
0.1
,
hrg
=
0.1
,
is_random
=
False
,
row_index
=
0
,
col_index
=
1
,
channel_index
=
2
,
fill_mode
=
'nearest'
,
cval
=
0.
,
order
=
1
)
:
h
,
w
=
x
.
shape
[
row_index
]
,
x
.
shape
[
col_index
]
if
is_random
:
tx
=
np
.
random
.
uniform
(
hrg
,
hrg
)
*
h
ty
=
np
.
random
.
uniform
(
wrg
,
wrg
)
*
w
else
:
tx
,
ty
=
hrg
*
h
,
wrg
*
w
translation_matrix
=
np
.
array
(
[
[
1
,
0
,
tx
]
,
[
0
,
1
,
ty
]
,
[
0
,
0
,
1
]
]
)
transform_matrix
=
translation_matrix
# no need to do offset
x
=
affine_transform
(
x
,
transform_matrix
,
channel_index
,
fill_mode
,
cval
,
order
)
return
x

Shift an image randomly or non - randomly .


def brightness(x, gamma=1, gain=1, is_random=False):
    """Change the brightness of a single image, randomly or non-randomly.

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    gamma : float
        Non negative real number. Default value is 1.
            - Small than 1 means brighter.
            - If `is_random` is True, gamma in a range of (1-gamma, 1+gamma).
    gain : float
        The constant multiplier. Default value is 1.
    is_random : boolean
        If True, randomly change brightness. Default is False.

    Returns
    -------
    numpy.array
        A processed image.

    References
    -----------
    - `skimage.exposure.adjust_gamma <http://scikit-image.org/docs/dev/api/skimage.exposure.html>`__
    - `chinese blog <http://www.cnblogs.com/denny402/p/5124402.html>`__

    """
    if is_random:
        gamma = np.random.uniform(1 - gamma, 1 + gamma)
    x = exposure.adjust_gamma(x, gamma, gain)
    return x

def brightness ( x , gamma = 1 , gain = 1 , is_random = False ) : if is_random : gamma = np . random . uniform ( 1 - gamma , 1 + gamma ) x = exposure . adjust_gamma ( x , gamma , gain ) return x

Change the brightness of a single image randomly or non - randomly .


def illumination(x, gamma=1., contrast=1., saturation=1., is_random=False):
    """Perform illumination augmentation for a single image, randomly or non-randomly.

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    gamma : float
        Change brightness (the same with ``tl.prepro.brightness``)
            - if is_random=False, one float number, small than one means brighter, greater than one means darker.
            - if is_random=True, tuple of two float numbers, (min, max).
    contrast : float
        Change contrast.
            - if is_random=False, one float number, small than one means blur.
            - if is_random=True, tuple of two float numbers, (min, max).
    saturation : float
        Change saturation.
            - if is_random=False, one float number, small than one means unsaturation.
            - if is_random=True, tuple of two float numbers, (min, max).
    is_random : boolean
        If True, randomly change illumination. Default is False.

    Returns
    -------
    numpy.array
        A processed image.

    Examples
    ---------
    Random

    >>> x = tl.prepro.illumination(x, gamma=(0.5, 5.0), contrast=(0.3, 1.0), saturation=(0.7, 1.0), is_random=True)

    Non-random

    >>> x = tl.prepro.illumination(x, 0.5, 0.6, 0.8, is_random=False)

    """
    if is_random:
        if not (len(gamma) == len(contrast) == len(saturation) == 2):
            raise AssertionError("if is_random = True, the arguments are (min, max)")

        ## random change brightness  # small --> brighter
        illum_settings = np.random.randint(0, 3)  # 0-brighter, 1-darker, 2 keep normal

        if illum_settings == 0:  # brighter
            gamma = np.random.uniform(gamma[0], 1.0)  # (.5, 1.0)
        elif illum_settings == 1:  # darker
            gamma = np.random.uniform(1.0, gamma[1])  # (1.0, 5.0)
        else:
            gamma = 1
        im_ = brightness(x, gamma=gamma, gain=1, is_random=False)

        # tl.logging.info("using contrast and saturation")
        image = PIL.Image.fromarray(im_)  # array -> PIL
        contrast_adjust = PIL.ImageEnhance.Contrast(image)
        image = contrast_adjust.enhance(np.random.uniform(contrast[0], contrast[1]))  #0.3,0.9))

        saturation_adjust = PIL.ImageEnhance.Color(image)
        image = saturation_adjust.enhance(np.random.uniform(saturation[0], saturation[1]))  # (0.7,1.0))
        im_ = np.array(image)  # PIL -> array
    else:
        im_ = brightness(x, gamma=gamma, gain=1, is_random=False)
        image = PIL.Image.fromarray(im_)  # array -> PIL
        contrast_adjust = PIL.ImageEnhance.Contrast(image)
        image = contrast_adjust.enhance(contrast)

        saturation_adjust = PIL.ImageEnhance.Color(image)
        image = saturation_adjust.enhance(saturation)
        im_ = np.array(image)  # PIL -> array
    return np.asarray(im_)

Perform illumination augmentation for a single image randomly or non - randomly .


def adjust_hue(im, hout=0.66, is_offset=True, is_clip=True, is_random=False):
    """Adjust hue of an RGB image.

    This is a convenience method that converts an RGB image to float representation, converts it to HSV, add an offset to the hue channel, converts back to RGB and then back to the original data type.
    For TF, see `tf.image.adjust_hue <https://www.tensorflow.org/api_docs/python/tf/image/adjust_hue>`__.and `tf.image.random_hue <https://www.tensorflow.org/api_docs/python/tf/image/random_hue>`__.

    Parameters
    -----------
    im : numpy.array
        An image with values between 0 and 255.
    hout : float
        The scale value for adjusting hue.
            - If is_offset is False, set all hue values to this value. 0 is red; 0.33 is green; 0.66 is blue.
            - If is_offset is True, add this value as the offset to the hue channel.
    is_offset : boolean
        Whether `hout` is added on HSV as offset or not. Default is True.
    is_clip : boolean
        If HSV value smaller than 0, set to 0. Default is True.
    is_random : boolean
        If True, randomly change hue. Default is False.

    Returns
    -------
    numpy.array
        A processed image.

    Examples
    ---------
    Random, add a random value between -0.2 and 0.2 as the offset to every hue values.

    >>> im_hue = tl.prepro.adjust_hue(image, hout=0.2, is_offset=True, is_random=False)

    Non-random, make all hue to green.

    >>> im_green = tl.prepro.adjust_hue(image, hout=0.66, is_offset=False, is_random=False)

    References
    -----------
    - `tf.image.random_hue <https://www.tensorflow.org/api_docs/python/tf/image/random_hue>`__.
    - `tf.image.adjust_hue <https://www.tensorflow.org/api_docs/python/tf/image/adjust_hue>`__.
    - `StackOverflow: Changing image hue with python PIL <https://stackoverflow.com/questions/7274221/changing-image-hue-with-python-pil>`__.

    """
    hsv = rgb_to_hsv(im)
    if is_random:
        hout = np.random.uniform(-hout, hout)

    if is_offset:
        hsv[..., 0] += hout
    else:
        hsv[..., 0] = hout

    if is_clip:
        hsv[..., 0] = np.clip(hsv[..., 0], 0, np.inf)  # Hao : can remove green dots

    rgb = hsv_to_rgb(hsv)
    return rgb

def
adjust_hue
(
im
,
hout
=
0.66
,
is_offset
=
True
,
is_clip
=
True
,
is_random
=
False
)
:
hsv
=
rgb_to_hsv
(
im
)
if
is_random
:
hout
=
np
.
random
.
uniform
(
hout
,
hout
)
if
is_offset
:
hsv
[
...
,
0
]
+=
hout
else
:
hsv
[
...
,
0
]
=
hout
if
is_clip
:
hsv
[
...
,
0
]
=
np
.
clip
(
hsv
[
...
,
0
]
,
0
,
np
.
inf
)
# Hao : can remove green dots
rgb
=
hsv_to_rgb
(
hsv
)
return
rgb


def imresize(x, size=None, interp='bicubic', mode=None):
    """Resize an image by given output size and method.

    Warning, this function will rescale the value to [0, 255].

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    size : list of 2 int or None
        For height and width.
    interp : str
        Interpolation method for re-sizing (`nearest`, `lanczos`, `bilinear`, `bicubic` (default) or `cubic`).
    mode : str
        The PIL image mode (`P`, `L`, etc.) to convert image before resizing.

    Returns
    -------
    numpy.array
        A processed image.

    References
    ------------
    - `scipy.misc.imresize <https://docs.scipy.org/doc/scipy/reference/generated/scipy.misc.imresize.html>`__

    """
    if size is None:
        size = [100, 100]

    if x.shape[-1] == 1:
        # greyscale
        x = scipy.misc.imresize(x[:, :, 0], size, interp=interp, mode=mode)
        return x[:, :, np.newaxis]
    else:
        # rgb, bgr, rgba
        return scipy.misc.imresize(x, size, interp=interp, mode=mode)

def
imresize
(
x
,
size
=
,
interp
=
'bicubic'
,
mode
=
)
:
if
size
is
:
size
=
[
100
,
100
]
if
x
.
shape
[
1
]
==
1
:
# greyscale
x
=
scipy
.
misc
.
imresize
(
x
[
:
,
:
,
0
]
,
size
,
interp
=
interp
,
mode
=
mode
)
return
x
[
:
,
:
,
np
.
newaxis
]
else
:
# rgb, bgr, rgba
return
scipy
.
misc
.
imresize
(
x
,
size
,
interp
=
interp
,
mode
=
mode
)

Resize an image by given output size and method .


def pixel_value_scale(im, val=0.9, clip=None, is_random=False):
    """Scales each value in the pixels of the image.

    Parameters
    -----------
    im : numpy.array
        An image.
    val : float
        The scale value for changing pixel value.
            - If is_random=False, multiply this value with all pixels.
            - If is_random=True, multiply a value between [1-val, 1+val] with all pixels.
    clip : tuple of 2 numbers
        The minimum and maximum value.
    is_random : boolean
        If True, see ``val``.

    Returns
    -------
    numpy.array
        A processed image.

    Examples
    ----------
    Random

    >>> im = pixel_value_scale(im, 0.1, [0, 255], is_random=True)

    Non-random

    >>> im = pixel_value_scale(im, 0.9, [0, 255], is_random=False)

    """

    clip = clip if clip is not None else (-np.inf, np.inf)

    if is_random:
        scale = 1 + np.random.uniform(-val, val)
        im = im * scale
    else:
        im = im * val

    if len(clip) == 2:
        im = np.clip(im, clip[0], clip[1])
    else:
        raise Exception("clip : tuple of 2 numbers")

    return im

def
pixel_value_scale
(
im
,
val
=
0.9
,
clip
=
,
is_random
=
False
)
:
clip
=
clip
if
clip
is
not
else
(
np
.
inf
,
np
.
inf
)
if
is_random
:
scale
=
1
+
np
.
random
.
uniform
(
val
,
val
)
im
=
im
*
scale
else
:
im
=
im
*
val
if
len
(
clip
)
==
2
:
im
=
np
.
clip
(
im
,
clip
[
0
]
,
clip
[
1
]
)
else
:
raise
Exception
(
"clip : tuple of 2 numbers"
)
return
im

Scales each value in the pixels of the image .


def samplewise_norm(
        x, rescale=None, samplewise_center=False, samplewise_std_normalization=False, channel_index=2, epsilon=1e-7
):
    """Normalize an image by rescale, samplewise centering and samplewise centering in order.

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    rescale : float
        Rescaling factor. If None or 0, no rescaling is applied, otherwise we multiply the data by the value provided (before applying any other transformation)
    samplewise_center : boolean
        If True, set each sample mean to 0.
    samplewise_std_normalization : boolean
        If True, divide each input by its std.
    epsilon : float
        A small position value for dividing standard deviation.

    Returns
    -------
    numpy.array
        A processed image.

    Examples
    --------
    >>> x = samplewise_norm(x, samplewise_center=True, samplewise_std_normalization=True)
    >>> print(x.shape, np.mean(x), np.std(x))
    (160, 176, 1), 0.0, 1.0

    Notes
    ------
    When samplewise_center and samplewise_std_normalization are True.
    - For greyscale image, every pixels are subtracted and divided by the mean and std of whole image.
    - For RGB image, every pixels are subtracted and divided by the mean and std of this pixel i.e. the mean and std of a pixel is 0 and 1.

    """
    if rescale:
        x *= rescale

    if x.shape[channel_index] == 1:
        # greyscale
        if samplewise_center:
            x = x - np.mean(x)
        if samplewise_std_normalization:
            x = x / np.std(x)
        return x
    elif x.shape[channel_index] == 3:
        # rgb
        if samplewise_center:
            x = x - np.mean(x, axis=channel_index, keepdims=True)
        if samplewise_std_normalization:
            x = x / (np.std(x, axis=channel_index, keepdims=True) + epsilon)
        return x
    else:
        raise Exception("Unsupported channels %d" % x.shape[channel_index])

def
samplewise_norm
(
x
,
rescale
=
,
samplewise_center
=
False
,
samplewise_std_normalization
=
False
,
channel_index
=
2
,
epsilon
=
1e-7
)
:
if
rescale
:
x
*=
rescale
if
x
.
shape
[
channel_index
]
==
1
:
# greyscale
if
samplewise_center
:
x
=
x
np
.
mean
(
x
)
if
samplewise_std_normalization
:
x
=
x
/
np
.
std
(
x
)
return
x
elif
x
.
shape
[
channel_index
]
==
3
:
# rgb
if
samplewise_center
:
x
=
x
np
.
mean
(
x
,
axis
=
channel_index
,
keepdims
=
True
)
if
samplewise_std_normalization
:
x
=
x
/
(
np
.
std
(
x
,
axis
=
channel_index
,
keepdims
=
True
)
+
epsilon
)
return
x
else
:
raise
Exception
(
"Unsupported channels %d"
%
x
.
shape
[
channel_index
]
)

Normalize an image by rescale samplewise centering and samplewise centering in order .


def featurewise_norm(x, mean=None, std=None, epsilon=1e-7):
    """Normalize every pixels by the same given mean and std, which are usually
    compute from all examples.

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    mean : float
        Value for subtraction.
    std : float
        Value for division.
    epsilon : float
        A small position value for dividing standard deviation.

    Returns
    -------
    numpy.array
        A processed image.

    """
    if mean:
        x = x - mean
    if std:
        x = x / (std + epsilon)
    return x

def featurewise_norm ( x , mean = None , std = None , epsilon = 1e-7 ) : if mean : x = x - mean if std : x = x / ( std + epsilon ) return x

Normalize every pixels by the same given mean and std which are usually compute from all examples .


def get_zca_whitening_principal_components_img(X):
    """Return the ZCA whitening principal components matrix.

    Parameters
    -----------
    x : numpy.array
        Batch of images with dimension of [n_example, row, col, channel] (default).

    Returns
    -------
    numpy.array
        A processed image.

    """
    flatX = np.reshape(X, (X.shape[0], X.shape[1] * X.shape[2] * X.shape[3]))
    tl.logging.info("zca : computing sigma ..")
    sigma = np.dot(flatX.T, flatX) / flatX.shape[0]
    tl.logging.info("zca : computing U, S and V ..")
    U, S, _ = linalg.svd(sigma)  # USV
    tl.logging.info("zca : computing principal components ..")
    principal_components = np.dot(np.dot(U, np.diag(1. / np.sqrt(S + 10e-7))), U.T)
    return principal_components

Return the ZCA whitening principal components matrix .


def zca_whitening(x, principal_components):
    """Apply ZCA whitening on an image by given principal components matrix.

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    principal_components : matrix
        Matrix from ``get_zca_whitening_principal_components_img``.

    Returns
    -------
    numpy.array
        A processed image.

    """
    flatx = np.reshape(x, (x.size))
    # tl.logging.info(principal_components.shape, x.shape)  # ((28160, 28160), (160, 176, 1))
    # flatx = np.reshape(x, (x.shape))
    # flatx = np.reshape(x, (x.shape[0], ))
    # tl.logging.info(flatx.shape)  # (160, 176, 1)
    whitex = np.dot(flatx, principal_components)
    x = np.reshape(whitex, (x.shape[0], x.shape[1], x.shape[2]))
    return x

Apply ZCA whitening on an image by given principal components matrix .


def drop(x, keep=0.5):
    """Randomly set some pixels to zero by a given keeping probability.

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] or [row, col].
    keep : float
        The keeping probability (0, 1), the lower more values will be set to zero.

    Returns
    -------
    numpy.array
        A processed image.

    """
    if len(x.shape) == 3:
        if x.shape[-1] == 3:  # color
            img_size = x.shape
            mask = np.random.binomial(n=1, p=keep, size=x.shape[:-1])
            for i in range(3):
                x[:, :, i] = np.multiply(x[:, :, i], mask)
        elif x.shape[-1] == 1:  # greyscale image
            img_size = x.shape
            x = np.multiply(x, np.random.binomial(n=1, p=keep, size=img_size))
        else:
            raise Exception("Unsupported shape {}".format(x.shape))
    elif len(x.shape) == 2 or 1:  # greyscale matrix (image) or vector
        img_size = x.shape
        x = np.multiply(x, np.random.binomial(n=1, p=keep, size=img_size))
    else:
        raise Exception("Unsupported shape {}".format(x.shape))
    return x

def
drop
(
x
,
keep
=
0.5
)
:
if
len
(
x
.
shape
)
==
3
:
if
x
.
shape
[
1
]
==
3
:
# color
img_size
=
x
.
shape
mask
=
np
.
random
.
binomial
(
n
=
1
,
p
=
keep
,
size
=
x
.
shape
[
:
1
]
)
for
i
in
range
(
3
)
:
x
[
:
,
:
,
i
]
=
np
.
multiply
(
x
[
:
,
:
,
i
]
,
mask
)
elif
x
.
shape
[
1
]
==
1
:
# greyscale image
img_size
=
x
.
shape
x
=
np
.
multiply
(
x
,
np
.
random
.
binomial
(
n
=
1
,
p
=
keep
,
size
=
img_size
)
)
else
:
raise
Exception
(
"Unsupported shape {}"
.
format
(
x
.
shape
)
)
elif
len
(
x
.
shape
)
==
2
or
1
:
# greyscale matrix (image) or vector
img_size
=
x
.
shape
x
=
np
.
multiply
(
x
,
np
.
random
.
binomial
(
n
=
1
,
p
=
keep
,
size
=
img_size
)
)
else
:
raise
Exception
(
"Unsupported shape {}"
.
format
(
x
.
shape
)
)
return
x

Randomly set some pixels to zero by a given keeping probability .


def pt2map(list_points=None, size=(100, 100), val=1):
    """Inputs a list of points, return a 2D image.

    Parameters
    --------------
    list_points : list of 2 int
        [[x, y], [x, y]..] for point coordinates.
    size : tuple of 2 int
        (w, h) for output size.
    val : float or int
        For the contour value.

    Returns
    -------
    numpy.array
        An image.

    """
    if list_points is None:
        raise Exception("list_points : list of 2 int")
    i_m = np.zeros(size)
    if len(list_points) == 0:
        return i_m
    for xx in list_points:
        for x in xx:
            # tl.logging.info(x)
            i_m[int(np.round(x[0]))][int(np.round(x[1]))] = val
    return i_m

def
pt2map
(
list_points
=
,
size
=
(
100
,
100
)
,
val
=
1
)
:
if
list_points
is
:
raise
Exception
(
"list_points : list of 2 int"
)
i_m
=
np
.
zeros
(
size
)
if
len
(
list_points
)
==
0
:
return
i_m
for
xx
in
list_points
:
for
x
in
xx
:
# tl.logging.info(x)
i_m
[
int
(
np
.
round
(
x
[
0
]
)
)
]
[
int
(
np
.
round
(
x
[
1
]
)
)
]
=
val
return
i_m

Inputs a list of points return a 2D image .


def parse_darknet_ann_str_to_list(annotations):
    r"""Input string format of class, x, y, w, h, return list of list format.

    Parameters
    -----------
    annotations : str
        The annotations in darkent format "class, x, y, w, h ...." seperated by "\\n".

    Returns
    -------
    list of list of 4 numbers
        List of bounding box.

    """
    annotations = annotations.split("\n")
    ann = []
    for a in annotations:
        a = a.split()
        if len(a) == 5:
            for i, _v in enumerate(a):
                if i == 0:
                    a[i] = int(a[i])
                else:
                    a[i] = float(a[i])
            ann.append(a)
    return ann

def parse_darknet_ann_str_to_list ( annotations ) : annotations = annotations . split ( "\n" ) ann = [ ] for a in annotations : a = a . split ( ) if len ( a ) == 5 : for i , _v in enumerate ( a ) : if i == 0 : a [ i ] = int ( a [ i ] ) else : a [ i ] = float ( a [ i ] ) ann . append ( a ) return ann

r Input string format of class x y w h return list of list format .


def parse_darknet_ann_list_to_cls_box(annotations):
    """Parse darknet annotation format into two lists for class and bounding box.

    Input list of [[class, x, y, w, h], ...], return two list of [class ...] and [[x, y, w, h], ...].

    Parameters
    ------------
    annotations : list of list
        A list of class and bounding boxes of images e.g. [[class, x, y, w, h], ...]

    Returns
    -------
    list of int
        List of class labels.

    list of list of 4 numbers
        List of bounding box.

    """
    class_list = []
    bbox_list = []
    for ann in annotations:
        class_list.append(ann[0])
        bbox_list.append(ann[1:])
    return class_list, bbox_list

def parse_darknet_ann_list_to_cls_box ( annotations ) : class_list = [ ] bbox_list = [ ] for ann in annotations : class_list . append ( ann [ 0 ] ) bbox_list . append ( ann [ 1 : ] ) return class_list , bbox_list

Parse darknet annotation format into two lists for class and bounding box .


def obj_box_horizontal_flip(im, coords=None, is_rescale=False, is_center=False, is_random=False):
    """Left-right flip the image and coordinates for object detection.

    Parameters
    ----------
    im : numpy.array
        An image with dimension of [row, col, channel] (default).
    coords : list of list of 4 int/float or None
        Coordinates [[x, y, w, h], [x, y, w, h], ...].
    is_rescale : boolean
        Set to True, if the input coordinates are rescaled to [0, 1]. Default is False.
    is_center : boolean
        Set to True, if the x and y of coordinates are the centroid (i.e. darknet format). Default is False.
    is_random : boolean
        If True, randomly flip. Default is False.

    Returns
    -------
    numpy.array
        A processed image
    list of list of 4 numbers
        A list of new bounding boxes.

    Examples
    --------
    >>> im = np.zeros([80, 100])    # as an image with shape width=100, height=80
    >>> im, coords = obj_box_left_right_flip(im, coords=[[0.2, 0.4, 0.3, 0.3], [0.1, 0.5, 0.2, 0.3]], is_rescale=True, is_center=True, is_random=False)
    >>> print(coords)
      [[0.8, 0.4, 0.3, 0.3], [0.9, 0.5, 0.2, 0.3]]
    >>> im, coords = obj_box_left_right_flip(im, coords=[[0.2, 0.4, 0.3, 0.3]], is_rescale=True, is_center=False, is_random=False)
    >>> print(coords)
      [[0.5, 0.4, 0.3, 0.3]]
    >>> im, coords = obj_box_left_right_flip(im, coords=[[20, 40, 30, 30]], is_rescale=False, is_center=True, is_random=False)
    >>> print(coords)
      [[80, 40, 30, 30]]
    >>> im, coords = obj_box_left_right_flip(im, coords=[[20, 40, 30, 30]], is_rescale=False, is_center=False, is_random=False)
    >>> print(coords)
      [[50, 40, 30, 30]]

    """
    if coords is None:
        coords = []

    def _flip(im, coords):
        im = flip_axis(im, axis=1, is_random=False)
        coords_new = list()

        for coord in coords:

            if len(coord) != 4:
                raise AssertionError("coordinate should be 4 values : [x, y, w, h]")

            if is_rescale:
                if is_center:
                    # x_center' = 1 - x
                    x = 1. - coord[0]
                else:
                    # x_center' = 1 - x - w
                    x = 1. - coord[0] - coord[2]
            else:
                if is_center:
                    # x' = im.width - x
                    x = im.shape[1] - coord[0]
                else:
                    # x' = im.width - x - w
                    x = im.shape[1] - coord[0] - coord[2]
            coords_new.append([x, coord[1], coord[2], coord[3]])
        return im, coords_new

    if is_random:
        factor = np.random.uniform(-1, 1)
        if factor > 0:
            return _flip(im, coords)
        else:
            return im, coords
    else:
        return _flip(im, coords)

Left - right flip the image and coordinates for object detection .


def obj_box_imresize(im, coords=None, size=None, interp='bicubic', mode=None, is_rescale=False):
    """Resize an image, and compute the new bounding box coordinates.

    Parameters
    -------------
    im : numpy.array
        An image with dimension of [row, col, channel] (default).
    coords : list of list of 4 int/float or None
        Coordinates [[x, y, w, h], [x, y, w, h], ...]
    size interp and mode : args
        See ``tl.prepro.imresize``.
    is_rescale : boolean
        Set to True, if the input coordinates are rescaled to [0, 1], then return the original coordinates. Default is False.

    Returns
    -------
    numpy.array
        A processed image
    list of list of 4 numbers
        A list of new bounding boxes.

    Examples
    --------
    >>> im = np.zeros([80, 100, 3])    # as an image with shape width=100, height=80
    >>> _, coords = obj_box_imresize(im, coords=[[20, 40, 30, 30], [10, 20, 20, 20]], size=[160, 200], is_rescale=False)
    >>> print(coords)
      [[40, 80, 60, 60], [20, 40, 40, 40]]
    >>> _, coords = obj_box_imresize(im, coords=[[20, 40, 30, 30]], size=[40, 100], is_rescale=False)
    >>> print(coords)
      [[20, 20, 30, 15]]
    >>> _, coords = obj_box_imresize(im, coords=[[20, 40, 30, 30]], size=[60, 150], is_rescale=False)
    >>> print(coords)
      [[30, 30, 45, 22]]
    >>> im2, coords = obj_box_imresize(im, coords=[[0.2, 0.4, 0.3, 0.3]], size=[160, 200], is_rescale=True)
    >>> print(coords, im2.shape)
      [[0.2, 0.4, 0.3, 0.3]] (160, 200, 3)

    """
    if coords is None:
        coords = []
    if size is None:
        size = [100, 100]

    imh, imw = im.shape[0:2]
    imh = imh * 1.0  # * 1.0 for python2 : force division to be float point
    imw = imw * 1.0
    im = imresize(im, size=size, interp=interp, mode=mode)

    if is_rescale is False:
        coords_new = list()

        for coord in coords:

            if len(coord) != 4:
                raise AssertionError("coordinate should be 4 values : [x, y, w, h]")

            # x' = x * (imw'/imw)
            x = int(coord[0] * (size[1] / imw))
            # y' = y * (imh'/imh)
            # tl.logging.info('>>', coord[1], size[0], imh)
            y = int(coord[1] * (size[0] / imh))
            # w' = w * (imw'/imw)
            w = int(coord[2] * (size[1] / imw))
            # h' = h * (imh'/imh)
            h = int(coord[3] * (size[0] / imh))
            coords_new.append([x, y, w, h])
        return im, coords_new
    else:
        return im, coords

Resize an image and compute the new bounding box coordinates .


def remove_pad_sequences(sequences, pad_id=0):
    """Remove padding.

    Parameters
    -----------
    sequences : list of list of int
        All sequences where each row is a sequence.
    pad_id : int
        The pad ID.

    Returns
    ----------
    list of list of int
        The processed sequences.

    Examples
    ----------
    >>> sequences = [[2,3,4,0,0], [5,1,2,3,4,0,0,0], [4,5,0,2,4,0,0,0]]
    >>> print(remove_pad_sequences(sequences, pad_id=0))
    [[2, 3, 4], [5, 1, 2, 3, 4], [4, 5, 0, 2, 4]]

    """
    sequences_out = copy.deepcopy(sequences)

    for i, _ in enumerate(sequences):
        # for j in range(len(sequences[i])):
        #     if sequences[i][j] == pad_id:
        #         sequences_out[i] = sequences_out[i][:j]
        #         break
        for j in range(1, len(sequences[i])):
            if sequences[i][-j] != pad_id:
                sequences_out[i] = sequences_out[i][0:-j + 1]
                break

    return sequences_out


def sequences_get_mask(sequences, pad_val=0):
    """Return mask for sequences.

    Parameters
    -----------
    sequences : list of list of int
        All sequences where each row is a sequence.
    pad_val : int
        The pad value.

    Returns
    ----------
    list of list of int
        The mask.

    Examples
    ---------
    >>> sentences_ids = [[4, 0, 5, 3, 0, 0],
    ...                  [5, 3, 9, 4, 9, 0]]
    >>> mask = sequences_get_mask(sentences_ids, pad_val=0)
    [[1 1 1 1 0 0]
     [1 1 1 1 1 0]]

    """
    mask = np.ones_like(sequences)
    for i, seq in enumerate(sequences):
        for i_w in reversed(range(len(seq))):
            if seq[i_w] == pad_val:
                mask[i, i_w] = 0
            else:
                break  # <-- exit the for loop, prepcess next sequence
    return mask


def keypoint_random_crop(image, annos, mask=None, size=(368, 368)):
    """Randomly crop an image and corresponding keypoints without influence scales, given by ``keypoint_random_resize_shortestedge``.

    Parameters
    -----------
    image : 3 channel image
        The given image for augmentation.
    annos : list of list of floats
        The keypoints annotation of people.
    mask : single channel image or None
        The mask if available.
    size : tuple of int
        The size of returned image.

    Returns
    ----------
    preprocessed image, annotation, mask

    """

    _target_height = size[0]
    _target_width = size[1]
    target_size = (_target_width, _target_height)

    if len(np.shape(image)) == 2:
        image = cv2.cvtColor(image, cv2.COLOR_GRAY2RGB)
    height, width, _ = np.shape(image)

    for _ in range(50):
        x = random.randrange(0, width - target_size[0]) if width > target_size[0] else 0
        y = random.randrange(0, height - target_size[1]) if height > target_size[1] else 0

        # check whether any face is inside the box to generate a reasonably-balanced datasets
        for joint in annos:
            if x <= joint[0][0] < x + target_size[0] and y <= joint[0][1] < y + target_size[1]:
                break

    def pose_crop(image, annos, mask, x, y, w, h):  # TODO : speed up with affine transform
        # adjust image
        target_size = (w, h)

        img = image
        resized = img[y:y + target_size[1], x:x + target_size[0], :]
        resized_mask = mask[y:y + target_size[1], x:x + target_size[0]]
        # adjust meta data
        adjust_joint_list = []
        for joint in annos:
            adjust_joint = []
            for point in joint:
                if point[0] < -10 or point[1] < -10:
                    adjust_joint.append((-1000, -1000))
                    continue
                new_x, new_y = point[0] - x, point[1] - y
                # should not crop outside the image
                if new_x > w - 1 or new_y > h - 1:
                    adjust_joint.append((-1000, -1000))
                    continue
                adjust_joint.append((new_x, new_y))
            adjust_joint_list.append(adjust_joint)

        return resized, adjust_joint_list, resized_mask

    return pose_crop(image, annos, mask, x, y, target_size[0], target_size[1])

Randomly crop an image and corresponding keypoints without influence scales given by keypoint_random_resize_shortestedge .


def keypoint_random_flip(
        image, annos, mask=None, prob=0.5, flip_list=(0, 1, 5, 6, 7, 2, 3, 4, 11, 12, 13, 8, 9, 10, 15, 14, 17, 16, 18)
):
    """Flip an image and corresponding keypoints.

    Parameters
    -----------
    image : 3 channel image
        The given image for augmentation.
    annos : list of list of floats
        The keypoints annotation of people.
    mask : single channel image or None
        The mask if available.
    prob : float, 0 to 1
        The probability to flip the image, if 1, always flip the image.
    flip_list : tuple of int
        Denotes how the keypoints number be changed after flipping which is required for pose estimation task.
        The left and right body should be maintained rather than switch.
        (Default COCO format).
        Set to an empty tuple if you don't need to maintain left and right information.

    Returns
    ----------
    preprocessed image, annos, mask

    """

    _prob = np.random.uniform(0, 1.0)
    if _prob < prob:
        return image, annos, mask

    _, width, _ = np.shape(image)
    image = cv2.flip(image, 1)
    mask = cv2.flip(mask, 1)
    new_joints = []
    for people in annos:  # TODO : speed up with affine transform
        new_keypoints = []
        for k in flip_list:
            point = people[k]
            if point[0] < 0 or point[1] < 0:
                new_keypoints.append((-1000, -1000))
                continue
            if point[0] > image.shape[1] - 1 or point[1] > image.shape[0] - 1:
                new_keypoints.append((-1000, -1000))
                continue
            if (width - point[0]) > image.shape[1] - 1:
                new_keypoints.append((-1000, -1000))
                continue
            new_keypoints.append((width - point[0], point[1]))
        new_joints.append(new_keypoints)
    annos = new_joints

    return image, annos, mask

def
keypoint_random_flip
(
image
,
annos
,
mask
=
,
prob
=
0.5
,
flip_list
=
(
0
,
1
,
5
,
6
,
7
,
2
,
3
,
4
,
11
,
12
,
13
,
8
,
9
,
10
,
15
,
14
,
17
,
16
,
18
)
)
:
_prob
=
np
.
random
.
uniform
(
0
,
1.0
)
if
_prob
<
prob
:
return
image
,
annos
,
mask
_
,
width
,
_
=
np
.
shape
(
image
)
image
=
cv2
.
flip
(
image
,
1
)
mask
=
cv2
.
flip
(
mask
,
1
)
new_joints
=
[
]
for
people
in
annos
:
# TODO : speed up with affine transform
new_keypoints
=
[
]
for
k
in
flip_list
:
point
=
people
[
k
]
if
point
[
0
]
<
0
or
point
[
1
]
<
0
:
new_keypoints
.
append
(
(
1000
,
1000
)
)
continue
if
point
[
0
]
>
image
.
shape
[
1
]
1
or
point
[
1
]
>
image
.
shape
[
0
]
1
:
new_keypoints
.
append
(
(
1000
,
1000
)
)
continue
if
(
width
point
[
0
]
)
>
image
.
shape
[
1
]
1
:
new_keypoints
.
append
(
(
1000
,
1000
)
)
continue
new_keypoints
.
append
(
(
width
point
[
0
]
,
point
[
1
]
)
)
new_joints
.
append
(
new_keypoints
)
annos
=
new_joints
return
image
,
annos
,
mask

Flip an image and corresponding keypoints .


def keypoint_random_resize(image, annos, mask=None, zoom_range=(0.8, 1.2)):
    """Randomly resize an image and corresponding keypoints.
    The height and width of image will be changed independently, so the scale will be changed.

    Parameters
    -----------
    image : 3 channel image
        The given image for augmentation.
    annos : list of list of floats
        The keypoints annotation of people.
    mask : single channel image or None
        The mask if available.
    zoom_range : tuple of two floats
        The minimum and maximum factor to zoom in or out, e.g (0.5, 1) means zoom out 1~2 times.

    Returns
    ----------
    preprocessed image, annos, mask

    """
    height = image.shape[0]
    width = image.shape[1]
    _min, _max = zoom_range
    scalew = np.random.uniform(_min, _max)
    scaleh = np.random.uniform(_min, _max)

    neww = int(width * scalew)
    newh = int(height * scaleh)

    dst = cv2.resize(image, (neww, newh), interpolation=cv2.INTER_AREA)
    if mask is not None:
        mask = cv2.resize(mask, (neww, newh), interpolation=cv2.INTER_AREA)
    # adjust meta data
    adjust_joint_list = []
    for joint in annos:  # TODO : speed up with affine transform
        adjust_joint = []
        for point in joint:
            if point[0] < -100 or point[1] < -100:
                adjust_joint.append((-1000, -1000))
                continue
            adjust_joint.append((int(point[0] * scalew + 0.5), int(point[1] * scaleh + 0.5)))
        adjust_joint_list.append(adjust_joint)
    if mask is not None:
        return dst, adjust_joint_list, mask
    else:
        return dst, adjust_joint_list, None

def
keypoint_random_resize
(
image
,
annos
,
mask
=
,
zoom_range
=
(
0.8
,
1.2
)
)
:
height
=
image
.
shape
[
0
]
width
=
image
.
shape
[
1
]
_min
,
_max
=
zoom_range
scalew
=
np
.
random
.
uniform
(
_min
,
_max
)
scaleh
=
np
.
random
.
uniform
(
_min
,
_max
)
neww
=
int
(
width
*
scalew
)
newh
=
int
(
height
*
scaleh
)
dst
=
cv2
.
resize
(
image
,
(
neww
,
newh
)
,
interpolation
=
cv2
.
INTER_AREA
)
if
mask
is
not
:
mask
=
cv2
.
resize
(
mask
,
(
neww
,
newh
)
,
interpolation
=
cv2
.
INTER_AREA
)
# adjust meta data
adjust_joint_list
=
[
]
for
joint
in
annos
:
# TODO : speed up with affine transform
adjust_joint
=
[
]
for
point
in
joint
:
if
point
[
0
]
<
100
or
point
[
1
]
<
100
:
adjust_joint
.
append
(
(
1000
,
1000
)
)
continue
adjust_joint
.
append
(
(
int
(
point
[
0
]
*
scalew
+
0.5
)
,
int
(
point
[
1
]
*
scaleh
+
0.5
)
)
)
adjust_joint_list
.
append
(
adjust_joint
)
if
mask
is
not
:
return
dst
,
adjust_joint_list
,
mask
else
:
return
dst
,
adjust_joint_list
,

Randomly resize an image and corresponding keypoints . The height and width of image will be changed independently so the scale will be changed .


def discount_episode_rewards(rewards=None, gamma=0.99, mode=0):
    """Take 1D float array of rewards and compute discounted rewards for an
    episode. When encount a non-zero value, consider as the end a of an episode.

    Parameters
    ----------
    rewards : list
        List of rewards
    gamma : float
        Discounted factor
    mode : int
        Mode for computing the discount rewards.
            - If mode == 0, reset the discount process when encount a non-zero reward (Ping-pong game).
            - If mode == 1, would not reset the discount process.

    Returns
    --------
    list of float
        The discounted rewards.

    Examples
    ----------
    >>> rewards = np.asarray([0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1])
    >>> gamma = 0.9
    >>> discount_rewards = tl.rein.discount_episode_rewards(rewards, gamma)
    >>> print(discount_rewards)
    [ 0.72899997  0.81        0.89999998  1.          0.72899997  0.81
    0.89999998  1.          0.72899997  0.81        0.89999998  1.        ]
    >>> discount_rewards = tl.rein.discount_episode_rewards(rewards, gamma, mode=1)
    >>> print(discount_rewards)
    [ 1.52110755  1.69011939  1.87791049  2.08656716  1.20729685  1.34144104
    1.49048996  1.65610003  0.72899997  0.81        0.89999998  1.        ]

    """
    if rewards is None:
        raise Exception("rewards should be a list")
    discounted_r = np.zeros_like(rewards, dtype=np.float32)
    running_add = 0
    for t in reversed(xrange(0, rewards.size)):
        if mode == 0:
            if rewards[t] != 0: running_add = 0

        running_add = running_add * gamma + rewards[t]
        discounted_r[t] = running_add
    return discounted_r

def
discount_episode_rewards
(
rewards
=
,
gamma
=
0.99
,
mode
=
0
)
:
if
rewards
is
:
raise
Exception
(
"rewards should be a list"
)
discounted_r
=
np
.
zeros_like
(
rewards
,
dtype
=
np
.
float32
)
running_add
=
0
for
t
in
reversed
(
xrange
(
0
,
rewards
.
size
)
)
:
if
mode
==
0
:
if
rewards
[
t
]
!=
0
:
running_add
=
0
running_add
=
running_add
*
gamma
+
rewards
[
t
]
discounted_r
[
t
]
=
running_add
return
discounted_r

Take 1D float array of rewards and compute discounted rewards for an episode . When encount a non - zero value consider as the end a of an episode .


def cross_entropy_reward_loss(logits, actions, rewards, name=None):
    """Calculate the loss for Policy Gradient Network.

    Parameters
    ----------
    logits : tensor
        The network outputs without softmax. This function implements softmax inside.
    actions : tensor or placeholder
        The agent actions.
    rewards : tensor or placeholder
        The rewards.

    Returns
    --------
    Tensor
        The TensorFlow loss function.

    Examples
    ----------
    >>> states_batch_pl = tf.placeholder(tf.float32, shape=[None, D])
    >>> network = InputLayer(states_batch_pl, name='input')
    >>> network = DenseLayer(network, n_units=H, act=tf.nn.relu, name='relu1')
    >>> network = DenseLayer(network, n_units=3, name='out')
    >>> probs = network.outputs
    >>> sampling_prob = tf.nn.softmax(probs)
    >>> actions_batch_pl = tf.placeholder(tf.int32, shape=[None])
    >>> discount_rewards_batch_pl = tf.placeholder(tf.float32, shape=[None])
    >>> loss = tl.rein.cross_entropy_reward_loss(probs, actions_batch_pl, discount_rewards_batch_pl)
    >>> train_op = tf.train.RMSPropOptimizer(learning_rate, decay_rate).minimize(loss)

    """
    cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(labels=actions, logits=logits, name=name)

    return tf.reduce_sum(tf.multiply(cross_entropy, rewards))

Calculate the loss for Policy Gradient Network .


def log_weight(probs, weights, name='log_weight'):
    """Log weight.

    Parameters
    -----------
    probs : tensor
        If it is a network output, usually we should scale it to [0, 1] via softmax.
    weights : tensor
        The weights.

    Returns
    --------
    Tensor
        The Tensor after appling the log weighted expression.

    """
    with tf.variable_scope(name):
        exp_v = tf.reduce_mean(tf.log(probs) * weights)
        return exp_v

def log_weight ( probs , weights , name = 'log_weight' ) : with tf . variable_scope ( name ) : exp_v = tf . reduce_mean ( tf . log ( probs ) * weights ) return exp_v


def choice_action_by_probs(probs=(0.5, 0.5), action_list=None):
    """Choice and return an an action by given the action probability distribution.

    Parameters
    ------------
    probs : list of float.
        The probability distribution of all actions.
    action_list : None or a list of int or others
        A list of action in integer, string or others. If None, returns an integer range between 0 and len(probs)-1.

    Returns
    --------
    float int or str
        The chosen action.

    Examples
    ----------
    >>> for _ in range(5):
    >>>     a = choice_action_by_probs([0.2, 0.4, 0.4])
    >>>     print(a)
    0
    1
    1
    2
    1
    >>> for _ in range(3):
    >>>     a = choice_action_by_probs([0.5, 0.5], ['a', 'b'])
    >>>     print(a)
    a
    b
    b

    """
    if action_list is None:
        n_action = len(probs)
        action_list = np.arange(n_action)
    else:
        if len(action_list) != len(probs):
            raise Exception("number of actions should equal to number of probabilities.")
    return np.random.choice(action_list, p=probs)

Choice and return an an action by given the action probability distribution .


def cross_entropy(output, target, name=None):
    """Softmax cross-entropy operation, returns the TensorFlow expression of cross-entropy for two distributions,
    it implements softmax internally. See ``tf.nn.sparse_softmax_cross_entropy_with_logits``.

    Parameters
    ----------
    output : Tensor
        A batch of distribution with shape: [batch_size, num of classes].
    target : Tensor
        A batch of index with shape: [batch_size, ].
    name : string
        Name of this loss.

    Examples
    --------
    >>> ce = tl.cost.cross_entropy(y_logits, y_target_logits, 'my_loss')

    References
    -----------
    - About cross-entropy: `<https://en.wikipedia.org/wiki/Cross_entropy>`__.
    - The code is borrowed from: `<https://en.wikipedia.org/wiki/Cross_entropy>`__.

    """
    if name is None:
        raise Exception("Please give a unique name to tl.cost.cross_entropy for TF1.0+")
    return tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(labels=target, logits=output), name=name)


def sigmoid_cross_entropy(output, target, name=None):
    """Sigmoid cross-entropy operation, see ``tf.nn.sigmoid_cross_entropy_with_logits``.

    Parameters
    ----------
    output : Tensor
        A batch of distribution with shape: [batch_size, num of classes].
    target : Tensor
        A batch of index with shape: [batch_size, ].
    name : string
        Name of this loss.

    """
    return tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(labels=target, logits=output), name=name)

def sigmoid_cross_entropy ( output , target , name = None ) : return tf . reduce_mean ( tf . nn . sigmoid_cross_entropy_with_logits ( labels = target , logits = output ) , name = name )

Sigmoid cross - entropy operation see tf . nn . sigmoid_cross_entropy_with_logits .


def binary_cross_entropy(output, target, epsilon=1e-8, name='bce_loss'):
    """Binary cross entropy operation.

    Parameters
    ----------
    output : Tensor
        Tensor with type of `float32` or `float64`.
    target : Tensor
        The target distribution, format the same with `output`.
    epsilon : float
        A small value to avoid output to be zero.
    name : str
        An optional name to attach to this function.

    References
    -----------
    - `ericjang-DRAW <https://github.com/ericjang/draw/blob/master/draw.py#L73>`__

    """
    #     with ops.op_scope([output, target], name, "bce_loss") as name:
    #         output = ops.convert_to_tensor(output, name="preds")
    #         target = ops.convert_to_tensor(targets, name="target")

    # with tf.name_scope(name):
    return tf.reduce_mean(
        tf.reduce_sum(-(target * tf.log(output + epsilon) + (1. - target) * tf.log(1. - output + epsilon)), axis=1),
        name=name
    )


def normalized_mean_square_error(output, target, name="normalized_mean_squared_error_loss"):
    """Return the TensorFlow expression of normalized mean-square-error of two distributions.

    Parameters
    ----------
    output : Tensor
        2D, 3D or 4D tensor i.e. [batch_size, n_feature], [batch_size, height, width] or [batch_size, height, width, channel].
    target : Tensor
        The target distribution, format the same with `output`.
    name : str
        An optional name to attach to this function.

    """
    # with tf.name_scope("normalized_mean_squared_error_loss"):
    if output.get_shape().ndims == 2:  # [batch_size, n_feature]
        nmse_a = tf.sqrt(tf.reduce_sum(tf.squared_difference(output, target), axis=1))
        nmse_b = tf.sqrt(tf.reduce_sum(tf.square(target), axis=1))
    elif output.get_shape().ndims == 3:  # [batch_size, w, h]
        nmse_a = tf.sqrt(tf.reduce_sum(tf.squared_difference(output, target), axis=[1, 2]))
        nmse_b = tf.sqrt(tf.reduce_sum(tf.square(target), axis=[1, 2]))
    elif output.get_shape().ndims == 4:  # [batch_size, w, h, c]
        nmse_a = tf.sqrt(tf.reduce_sum(tf.squared_difference(output, target), axis=[1, 2, 3]))
        nmse_b = tf.sqrt(tf.reduce_sum(tf.square(target), axis=[1, 2, 3]))
    nmse = tf.reduce_mean(nmse_a / nmse_b, name=name)
    return nmse

Return the TensorFlow expression of normalized mean - square - error of two distributions .


def cross_entropy_seq_with_mask(logits, target_seqs, input_mask, return_details=False, name=None):
    """Returns the expression of cross-entropy of two sequences, implement
    softmax internally. Normally be used for Dynamic RNN with Synced sequence input and output.

    Parameters
    -----------
    logits : Tensor
        2D tensor with shape of [batch_size * ?, n_classes], `?` means dynamic IDs for each example.
        - Can be get from `DynamicRNNLayer` by setting ``return_seq_2d`` to `True`.
    target_seqs : Tensor
        int of tensor, like word ID. [batch_size, ?], `?` means dynamic IDs for each example.
    input_mask : Tensor
        The mask to compute loss, it has the same size with `target_seqs`, normally 0 or 1.
    return_details : boolean
        Whether to return detailed losses.
            - If False (default), only returns the loss.
            - If True, returns the loss, losses, weights and targets (see source code).

    Examples
    --------
    >>> batch_size = 64
    >>> vocab_size = 10000
    >>> embedding_size = 256
    >>> input_seqs = tf.placeholder(dtype=tf.int64, shape=[batch_size, None], name="input")
    >>> target_seqs = tf.placeholder(dtype=tf.int64, shape=[batch_size, None], name="target")
    >>> input_mask = tf.placeholder(dtype=tf.int64, shape=[batch_size, None], name="mask")
    >>> net = tl.layers.EmbeddingInputlayer(
    ...         inputs = input_seqs,
    ...         vocabulary_size = vocab_size,
    ...         embedding_size = embedding_size,
    ...         name = 'seq_embedding')
    >>> net = tl.layers.DynamicRNNLayer(net,
    ...         cell_fn = tf.contrib.rnn.BasicLSTMCell,
    ...         n_hidden = embedding_size,
    ...         dropout = (0.7 if is_train else None),
    ...         sequence_length = tl.layers.retrieve_seq_length_op2(input_seqs),
    ...         return_seq_2d = True,
    ...         name = 'dynamicrnn')
    >>> print(net.outputs)
    (?, 256)
    >>> net = tl.layers.DenseLayer(net, n_units=vocab_size, name="output")
    >>> print(net.outputs)
    (?, 10000)
    >>> loss = tl.cost.cross_entropy_seq_with_mask(net.outputs, target_seqs, input_mask)

    """
    targets = tf.reshape(target_seqs, [-1])  # to one vector
    weights = tf.to_float(tf.reshape(input_mask, [-1]))  # to one vector like targets
    losses = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=targets, name=name) * weights
    # losses = tf.reduce_mean(tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=targets, name=name)) # for TF1.0 and others

    loss = tf.divide(
        tf.reduce_sum(losses),  # loss from mask. reduce_sum before element-wise mul with mask !!
        tf.reduce_sum(weights),
        name="seq_loss_with_mask"
    )

    if return_details:
        return loss, losses, weights, targets
    else:
        return loss

Returns the expression of cross - entropy of two sequences implement softmax internally . Normally be used for Dynamic RNN with Synced sequence input and output .


def maxnorm_regularizer(scale=1.0):
    """Max-norm regularization returns a function that can be used to apply max-norm regularization to weights.

    More about max-norm, see `wiki-max norm <https://en.wikipedia.org/wiki/Matrix_norm#Max_norm>`_.
    The implementation follows `TensorFlow contrib <https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/layers/python/layers/regularizers.py>`__.

    Parameters
    ----------
    scale : float
        A scalar multiplier `Tensor`. 0.0 disables the regularizer.

    Returns
    ---------
    A function with signature `mn(weights, name=None)` that apply Lo regularization.

    Raises
    --------
    ValueError : If scale is outside of the range [0.0, 1.0] or if scale is not a float.

    """
    if isinstance(scale, numbers.Integral):
        raise ValueError('scale cannot be an integer: %s' % scale)

    if isinstance(scale, numbers.Real):
        if scale < 0.:
            raise ValueError('Setting a scale less than 0 on a regularizer: %g' % scale)
        # if scale >= 1.:
        #   raise ValueError('Setting a scale greater than 1 on a regularizer: %g' %
        #                    scale)
        if scale == 0.:
            tl.logging.info('Scale of 0 disables regularizer.')
            return lambda _, name=None: None

    def mn(weights, name='max_regularizer'):
        """Applies max-norm regularization to weights."""
        with tf.name_scope(name) as scope:
            my_scale = ops.convert_to_tensor(scale, dtype=weights.dtype.base_dtype, name='scale')
            #   if tf.__version__ <= '0.12':
            #       standard_ops_fn = standard_ops.mul
            #   else:
            standard_ops_fn = standard_ops.multiply
            return standard_ops_fn(my_scale, standard_ops.reduce_max(standard_ops.abs(weights)), name=scope)

    return mn

#       standard_ops_fn = standard_ops.mul

Max - norm regularization returns a function that can be used to apply max - norm regularization to weights .


def ramp(x, v_min=0, v_max=1, name=None):
    """Ramp activation function.

    Parameters
    ----------
    x : Tensor
        input.
    v_min : float
        cap input to v_min as a lower bound.
    v_max : float
        cap input to v_max as a upper bound.
    name : str
        The function name (optional).

    Returns
    -------
    Tensor
        A ``Tensor`` in the same type as ``x``.

    """
    return tf.clip_by_value(x, clip_value_min=v_min, clip_value_max=v_max, name=name)

def ramp ( x , v_min = 0 , v_max = 1 , name = None ) : return tf . clip_by_value ( x , clip_value_min = v_min , clip_value_max = v_max , name = name )


def swish(x, name='swish'):
    """Swish function.

     See `Swish: a Self-Gated Activation Function <https://arxiv.org/abs/1710.05941>`__.

    Parameters
    ----------
    x : Tensor
        input.
    name: str
        function name (optional).

    Returns
    -------
    Tensor
        A ``Tensor`` in the same type as ``x``.

    """
    with tf.name_scope(name):
        x = tf.nn.sigmoid(x) * x
    return x

def swish ( x , name = 'swish' ) : with tf . name_scope ( name ) : x = tf . nn . sigmoid ( x ) * x return x


def pixel_wise_softmax(x, name='pixel_wise_softmax'):
    """Return the softmax outputs of images, every pixels have multiple label, the sum of a pixel is 1.

    Usually be used for image segmentation.

    Parameters
    ----------
    x : Tensor
        input.
            - For 2d image, 4D tensor (batch_size, height, weight, channel), where channel >= 2.
            - For 3d image, 5D tensor (batch_size, depth, height, weight, channel), where channel >= 2.
    name : str
        function name (optional)

    Returns
    -------
    Tensor
        A ``Tensor`` in the same type as ``x``.

    Examples
    --------
    >>> outputs = pixel_wise_softmax(network.outputs)
    >>> dice_loss = 1 - dice_coe(outputs, y_, epsilon=1e-5)

    References
    ----------
    - `tf.reverse <https://www.tensorflow.org/versions/master/api_docs/python/array_ops.html#reverse>`__

    """
    with tf.name_scope(name):
        return tf.nn.softmax(x)

def pixel_wise_softmax ( x , name = 'pixel_wise_softmax' ) : with tf . name_scope ( name ) : return tf . nn . softmax ( x )

Return the softmax outputs of images every pixels have multiple label the sum of a pixel is 1 .


def retrieve_seq_length_op3(data, pad_val=0):  # HangSheng: return tensor for sequence length, if input is tf.string
    """Return tensor for sequence length, if input is ``tf.string``."""
    data_shape_size = data.get_shape().ndims
    if data_shape_size == 3:
        return tf.reduce_sum(tf.cast(tf.reduce_any(tf.not_equal(data, pad_val), axis=2), dtype=tf.int32), 1)
    elif data_shape_size == 2:
        return tf.reduce_sum(tf.cast(tf.not_equal(data, pad_val), dtype=tf.int32), 1)
    elif data_shape_size == 1:
        raise ValueError("retrieve_seq_length_op3: data has wrong shape!")
    else:
        raise ValueError(
            "retrieve_seq_length_op3: handling data_shape_size %s hasn't been implemented!" % (data_shape_size)
        )

Return tensor for sequence length if input is tf . string .


def state_size(self):
        """State size of the LSTMStateTuple."""
        return (LSTMStateTuple(self._num_units, self._num_units) if self._state_is_tuple else 2 * self._num_units)

def state_size ( self ) : return ( LSTMStateTuple ( self . _num_units , self . _num_units ) if self . _state_is_tuple else 2 * self . _num_units )


def _tf_repeat(self, a, repeats):
        """Tensorflow version of np.repeat for 1D"""
        # https://github.com/tensorflow/tensorflow/issues/8521

        if len(a.get_shape()) != 1:
            raise AssertionError("This is not a 1D Tensor")

        a = tf.expand_dims(a, -1)
        a = tf.tile(a, [1, repeats])
        a = self.tf_flatten(a)
        return a

Tensorflow version of np . repeat for 1D


def _tf_batch_map_coordinates(self, inputs, coords):
        """Batch version of tf_map_coordinates

        Only supports 2D feature maps

        Parameters
        ----------
        inputs : ``tf.Tensor``
            shape = (b*c, h, w)
        coords : ``tf.Tensor``
            shape = (b*c, h, w, n, 2)

        Returns
        -------
        ``tf.Tensor``
            A Tensor with the shape as (b*c, h, w, n)

        """
        input_shape = inputs.get_shape()
        coords_shape = coords.get_shape()
        batch_channel = tf.shape(inputs)[0]
        input_h = int(input_shape[1])
        input_w = int(input_shape[2])
        kernel_n = int(coords_shape[3])
        n_coords = input_h * input_w * kernel_n

        coords_lt = tf.cast(tf.floor(coords), 'int32')
        coords_rb = tf.cast(tf.ceil(coords), 'int32')
        coords_lb = tf.stack([coords_lt[:, :, :, :, 0], coords_rb[:, :, :, :, 1]], axis=-1)
        coords_rt = tf.stack([coords_rb[:, :, :, :, 0], coords_lt[:, :, :, :, 1]], axis=-1)

        idx = self._tf_repeat(tf.range(batch_channel), n_coords)

        vals_lt = self._get_vals_by_coords(inputs, coords_lt, idx, (batch_channel, input_h, input_w, kernel_n))
        vals_rb = self._get_vals_by_coords(inputs, coords_rb, idx, (batch_channel, input_h, input_w, kernel_n))
        vals_lb = self._get_vals_by_coords(inputs, coords_lb, idx, (batch_channel, input_h, input_w, kernel_n))
        vals_rt = self._get_vals_by_coords(inputs, coords_rt, idx, (batch_channel, input_h, input_w, kernel_n))

        coords_offset_lt = coords - tf.cast(coords_lt, 'float32')

        vals_t = vals_lt + (vals_rt - vals_lt) * coords_offset_lt[:, :, :, :, 0]
        vals_b = vals_lb + (vals_rb - vals_lb) * coords_offset_lt[:, :, :, :, 0]
        mapped_vals = vals_t + (vals_b - vals_t) * coords_offset_lt[:, :, :, :, 1]

        return mapped_vals

def _tf_batch_map_coordinates ( self , inputs , coords ) : input_shape = inputs . get_shape ( ) coords_shape = coords . get_shape ( ) batch_channel = tf . shape ( inputs ) [ 0 ] input_h = int ( input_shape [ 1 ] ) input_w = int ( input_shape [ 2 ] ) kernel_n = int ( coords_shape [ 3 ] ) n_coords = input_h * input_w * kernel_n coords_lt = tf . cast ( tf . floor ( coords ) , 'int32' ) coords_rb = tf . cast ( tf . ceil ( coords ) , 'int32' ) coords_lb = tf . stack ( [ coords_lt [ : , : , : , : , 0 ] , coords_rb [ : , : , : , : , 1 ] ] , axis = - 1 ) coords_rt = tf . stack ( [ coords_rb [ : , : , : , : , 0 ] , coords_lt [ : , : , : , : , 1 ] ] , axis = - 1 ) idx = self . _tf_repeat ( tf . range ( batch_channel ) , n_coords ) vals_lt = self . _get_vals_by_coords ( inputs , coords_lt , idx , ( batch_channel , input_h , input_w , kernel_n ) ) vals_rb = self . _get_vals_by_coords ( inputs , coords_rb , idx , ( batch_channel , input_h , input_w , kernel_n ) ) vals_lb = self . _get_vals_by_coords ( inputs , coords_lb , idx , ( batch_channel , input_h , input_w , kernel_n ) ) vals_rt = self . _get_vals_by_coords ( inputs , coords_rt , idx , ( batch_channel , input_h , input_w , kernel_n ) ) coords_offset_lt = coords - tf . cast ( coords_lt , 'float32' ) vals_t = vals_lt + ( vals_rt - vals_lt ) * coords_offset_lt [ : , : , : , : , 0 ] vals_b = vals_lb + ( vals_rb - vals_lb ) * coords_offset_lt [ : , : , : , : , 0 ] mapped_vals = vals_t + ( vals_b - vals_t ) * coords_offset_lt [ : , : , : , : , 1 ] return mapped_vals


def _tf_batch_map_offsets(self, inputs, offsets, grid_offset):
        """Batch map offsets into input

        Parameters
        ------------
        inputs : ``tf.Tensor``
            shape = (b, h, w, c)
        offsets: ``tf.Tensor``
            shape = (b, h, w, 2*n)
        grid_offset: `tf.Tensor``
            Offset grids shape = (h, w, n, 2)

        Returns
        -------
        ``tf.Tensor``
            A Tensor with the shape as (b, h, w, c)

        """
        input_shape = inputs.get_shape()
        batch_size = tf.shape(inputs)[0]
        kernel_n = int(int(offsets.get_shape()[3]) / 2)
        input_h = input_shape[1]
        input_w = input_shape[2]
        channel = input_shape[3]

        # inputs (b, h, w, c) --> (b*c, h, w)
        inputs = self._to_bc_h_w(inputs, input_shape)

        # offsets (b, h, w, 2*n) --> (b, h, w, n, 2)
        offsets = tf.reshape(offsets, (batch_size, input_h, input_w, kernel_n, 2))
        # offsets (b, h, w, n, 2) --> (b*c, h, w, n, 2)
        # offsets = tf.tile(offsets, [channel, 1, 1, 1, 1])

        coords = tf.expand_dims(grid_offset, 0)  # grid_offset --> (1, h, w, n, 2)
        coords = tf.tile(coords, [batch_size, 1, 1, 1, 1]) + offsets  # grid_offset --> (b, h, w, n, 2)

        # clip out of bound
        coords = tf.stack(
            [
                tf.clip_by_value(coords[:, :, :, :, 0], 0.0, tf.cast(input_h - 1, 'float32')),
                tf.clip_by_value(coords[:, :, :, :, 1], 0.0, tf.cast(input_w - 1, 'float32'))
            ], axis=-1
        )
        coords = tf.tile(coords, [channel, 1, 1, 1, 1])

        mapped_vals = self._tf_batch_map_coordinates(inputs, coords)
        # (b*c, h, w, n) --> (b, h, w, n, c)
        mapped_vals = self._to_b_h_w_n_c(mapped_vals, [batch_size, input_h, input_w, kernel_n, channel])

        return mapped_vals


def minibatches(inputs=None, targets=None, batch_size=None, allow_dynamic_batch_size=False, shuffle=False):
    """Generate a generator that input a group of example in numpy.array and
    their labels, return the examples and labels by the given batch size.

    Parameters
    ----------
    inputs : numpy.array
        The input features, every row is a example.
    targets : numpy.array
        The labels of inputs, every row is a example.
    batch_size : int
        The batch size.
    allow_dynamic_batch_size: boolean
        Allow the use of the last data batch in case the number of examples is not a multiple of batch_size, this may result in unexpected behaviour if other functions expect a fixed-sized batch-size.
    shuffle : boolean
        Indicating whether to use a shuffling queue, shuffle the dataset before return.

    Examples
    --------
    >>> X = np.asarray([['a','a'], ['b','b'], ['c','c'], ['d','d'], ['e','e'], ['f','f']])
    >>> y = np.asarray([0,1,2,3,4,5])
    >>> for batch in tl.iterate.minibatches(inputs=X, targets=y, batch_size=2, shuffle=False):
    >>>     print(batch)
    (array([['a', 'a'], ['b', 'b']], dtype='<U1'), array([0, 1]))
    (array([['c', 'c'], ['d', 'd']], dtype='<U1'), array([2, 3]))
    (array([['e', 'e'], ['f', 'f']], dtype='<U1'), array([4, 5]))

    Notes
    -----
    If you have two inputs and one label and want to shuffle them together, e.g. X1 (1000, 100), X2 (1000, 80) and Y (1000, 1), you can stack them together (`np.hstack((X1, X2))`)
    into (1000, 180) and feed to ``inputs``. After getting a batch, you can split it back into X1 and X2.

    """
    if len(inputs) != len(targets):
        raise AssertionError("The length of inputs and targets should be equal")

    if shuffle:
        indices = np.arange(len(inputs))
        np.random.shuffle(indices)

    # for start_idx in range(0, len(inputs) - batch_size + 1, batch_size):
    # chulei: handling the case where the number of samples is not a multiple of batch_size, avoiding wasting samples
    for start_idx in range(0, len(inputs), batch_size):
        end_idx = start_idx + batch_size
        if end_idx > len(inputs):
            if allow_dynamic_batch_size:
                end_idx = len(inputs)
            else:
                break
        if shuffle:
            excerpt = indices[start_idx:end_idx]
        else:
            excerpt = slice(start_idx, end_idx)
        if (isinstance(inputs, list) or isinstance(targets, list)) and (shuffle ==True):
            # zsdonghao: for list indexing when shuffle==True
            yield [inputs[i] for i in excerpt], [targets[i] for i in excerpt]
        else:
            yield inputs[excerpt], targets[excerpt]

Generate a generator that input a group of example in numpy . array and their labels return the examples and labels by the given batch size .


def save_model(self, network=None, model_name='model', **kwargs):
        """Save model architecture and parameters into database, timestamp will be added automatically.

        Parameters
        ----------
        network : TensorLayer layer
            TensorLayer layer instance.
        model_name : str
            The name/key of model.
        kwargs : other events
            Other events, such as name, accuracy, loss, step number and etc (optinal).

        Examples
        ---------
        Save model architecture and parameters into database.
        >>> db.save_model(net, accuracy=0.8, loss=2.3, name='second_model')

        Load one model with parameters from database (run this in other script)
        >>> net = db.find_top_model(sess=sess, accuracy=0.8, loss=2.3)

        Find and load the latest model.
        >>> net = db.find_top_model(sess=sess, sort=[("time", pymongo.DESCENDING)])
        >>> net = db.find_top_model(sess=sess, sort=[("time", -1)])

        Find and load the oldest model.
        >>> net = db.find_top_model(sess=sess, sort=[("time", pymongo.ASCENDING)])
        >>> net = db.find_top_model(sess=sess, sort=[("time", 1)])

        Get model information
        >>> net._accuracy
        ... 0.8

        Returns
        ---------
        boolean : True for success, False for fail.
        """
        kwargs.update({'model_name': model_name})
        self._fill_project_info(kwargs)  # put project_name into kwargs

        params = network.get_all_params()

        s = time.time()

        kwargs.update({'architecture': network.all_graphs, 'time': datetime.utcnow()})

        try:
            params_id = self.model_fs.put(self._serialization(params))
            kwargs.update({'params_id': params_id, 'time': datetime.utcnow()})
            self.db.Model.insert_one(kwargs)
            print("[Database] Save model: SUCCESS, took: {}s".format(round(time.time() - s, 2)))
            return True
        except Exception as e:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            logging.info("{}  {}  {}  {}  {}".format(exc_type, exc_obj, fname, exc_tb.tb_lineno, e))
            print("[Database] Save model: FAIL")
            return False

Save model architecture and parameters into database timestamp will be added automatically .


def find_top_model(self, sess, sort=None, model_name='model', **kwargs):
        """Finds and returns a model architecture and its parameters from the database which matches the requirement.

        Parameters
        ----------
        sess : Session
            TensorFlow session.
        sort : List of tuple
            PyMongo sort comment, search "PyMongo find one sorting" and `collection level operations <http://api.mongodb.com/python/current/api/pymongo/collection.html>`__ for more details.
        model_name : str or None
            The name/key of model.
        kwargs : other events
            Other events, such as name, accuracy, loss, step number and etc (optinal).

        Examples
        ---------
        - see ``save_model``.

        Returns
        ---------
        network : TensorLayer layer
            Note that, the returned network contains all information of the document (record), e.g. if you saved accuracy in the document, you can get the accuracy by using ``net._accuracy``.
        """
        # print(kwargs)   # {}
        kwargs.update({'model_name': model_name})
        self._fill_project_info(kwargs)

        s = time.time()

        d = self.db.Model.find_one(filter=kwargs, sort=sort)

        _temp_file_name = '_find_one_model_ztemp_file'
        if d is not None:
            params_id = d['params_id']
            graphs = d['architecture']
            _datetime = d['time']
            exists_or_mkdir(_temp_file_name, False)
            with open(os.path.join(_temp_file_name, 'graph.pkl'), 'wb') as file:
                pickle.dump(graphs, file, protocol=pickle.HIGHEST_PROTOCOL)
        else:
            print("[Database] FAIL! Cannot find model: {}".format(kwargs))
            return False
        try:
            params = self._deserialization(self.model_fs.get(params_id).read())
            np.savez(os.path.join(_temp_file_name, 'params.npz'), params=params)

            network = load_graph_and_params(name=_temp_file_name, sess=sess)
            del_folder(_temp_file_name)

            pc = self.db.Model.find(kwargs)
            print(
                "[Database] Find one model SUCCESS. kwargs:{} sort:{} save time:{} took: {}s".
                format(kwargs, sort, _datetime, round(time.time() - s, 2))
            )

            # put all informations of model into the TL layer
            for key in d:
                network.__dict__.update({"_%s" % key: d[key]})

            # check whether more parameters match the requirement
            params_id_list = pc.distinct('params_id')
            n_params = len(params_id_list)
            if n_params != 1:
                print("     Note that there are {} models match the kwargs".format(n_params))
            return network
        except Exception as e:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            logging.info("{}  {}  {}  {}  {}".format(exc_type, exc_obj, fname, exc_tb.tb_lineno, e))
            return False

Finds and returns a model architecture and its parameters from the database which matches the requirement .


def delete_model(self, **kwargs):
        """Delete model.

        Parameters
        -----------
        kwargs : logging information
            Find items to delete, leave it empty to delete all log.
        """
        self._fill_project_info(kwargs)
        self.db.Model.delete_many(kwargs)
        logging.info("[Database] Delete Model SUCCESS")

def
delete_model
(
self
,
*
*
kwargs
)
:
self
.
_fill_project_info
(
kwargs
)
self
.
db
.
Model
.
delete_many
(
kwargs
)
logging
.
info
(
"[Database] Delete Model SUCCESS"
)


def save_dataset(self, dataset=None, dataset_name=None, **kwargs):
        """Saves one dataset into database, timestamp will be added automatically.

        Parameters
        ----------
        dataset : any type
            The dataset you want to store.
        dataset_name : str
            The name of dataset.
        kwargs : other events
            Other events, such as description, author and etc (optinal).

        Examples
        ----------
        Save dataset
        >>> db.save_dataset([X_train, y_train, X_test, y_test], 'mnist', description='this is a tutorial')

        Get dataset
        >>> dataset = db.find_top_dataset('mnist')

        Returns
        ---------
        boolean : Return True if save success, otherwise, return False.
        """
        self._fill_project_info(kwargs)
        if dataset_name is None:
            raise Exception("dataset_name is None, please give a dataset name")
        kwargs.update({'dataset_name': dataset_name})

        s = time.time()
        try:
            dataset_id = self.dataset_fs.put(self._serialization(dataset))
            kwargs.update({'dataset_id': dataset_id, 'time': datetime.utcnow()})
            self.db.Dataset.insert_one(kwargs)
            # print("[Database] Save params: {} SUCCESS, took: {}s".format(file_name, round(time.time()-s, 2)))
            print("[Database] Save dataset: SUCCESS, took: {}s".format(round(time.time() - s, 2)))
            return True
        except Exception as e:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            logging.info("{}  {}  {}  {}  {}".format(exc_type, exc_obj, fname, exc_tb.tb_lineno, e))
            print("[Database] Save dataset: FAIL")
            return False

Saves one dataset into database timestamp will be added automatically .


def find_top_dataset(self, dataset_name=None, sort=None, **kwargs):
        """Finds and returns a dataset from the database which matches the requirement.

        Parameters
        ----------
        dataset_name : str
            The name of dataset.
        sort : List of tuple
            PyMongo sort comment, search "PyMongo find one sorting" and `collection level operations <http://api.mongodb.com/python/current/api/pymongo/collection.html>`__ for more details.
        kwargs : other events
            Other events, such as description, author and etc (optinal).

        Examples
        ---------
        Save dataset
        >>> db.save_dataset([X_train, y_train, X_test, y_test], 'mnist', description='this is a tutorial')

        Get dataset
        >>> dataset = db.find_top_dataset('mnist')
        >>> datasets = db.find_datasets('mnist')

        Returns
        --------
        dataset : the dataset or False
            Return False if nothing found.

        """

        self._fill_project_info(kwargs)
        if dataset_name is None:
            raise Exception("dataset_name is None, please give a dataset name")
        kwargs.update({'dataset_name': dataset_name})

        s = time.time()

        d = self.db.Dataset.find_one(filter=kwargs, sort=sort)

        if d is not None:
            dataset_id = d['dataset_id']
        else:
            print("[Database] FAIL! Cannot find dataset: {}".format(kwargs))
            return False
        try:
            dataset = self._deserialization(self.dataset_fs.get(dataset_id).read())
            pc = self.db.Dataset.find(kwargs)
            print("[Database] Find one dataset SUCCESS, {} took: {}s".format(kwargs, round(time.time() - s, 2)))

            # check whether more datasets match the requirement
            dataset_id_list = pc.distinct('dataset_id')
            n_dataset = len(dataset_id_list)
            if n_dataset != 1:
                print("     Note that there are {} datasets match the requirement".format(n_dataset))
            return dataset
        except Exception as e:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            logging.info("{}  {}  {}  {}  {}".format(exc_type, exc_obj, fname, exc_tb.tb_lineno, e))
            return False

Finds and returns a dataset from the database which matches the requirement .


def find_datasets(self, dataset_name=None, **kwargs):
        """Finds and returns all datasets from the database which matches the requirement.
        In some case, the data in a dataset can be stored separately for better management.

        Parameters
        ----------
        dataset_name : str
            The name/key of dataset.
        kwargs : other events
            Other events, such as description, author and etc (optional).

        Returns
        --------
        params : the parameters, return False if nothing found.

        """

        self._fill_project_info(kwargs)
        if dataset_name is None:
            raise Exception("dataset_name is None, please give a dataset name")
        kwargs.update({'dataset_name': dataset_name})

        s = time.time()
        pc = self.db.Dataset.find(kwargs)

        if pc is not None:
            dataset_id_list = pc.distinct('dataset_id')
            dataset_list = []
            for dataset_id in dataset_id_list:  # you may have multiple Buckets files
                tmp = self.dataset_fs.get(dataset_id).read()
                dataset_list.append(self._deserialization(tmp))
        else:
            print("[Database] FAIL! Cannot find any dataset: {}".format(kwargs))
            return False

        print("[Database] Find {} datasets SUCCESS, took: {}s".format(len(dataset_list), round(time.time() - s, 2)))
        return dataset_list

Finds and returns all datasets from the database which matches the requirement . In some case the data in a dataset can be stored separately for better management .


def delete_datasets(self, **kwargs):
        """Delete datasets.

        Parameters
        -----------
        kwargs : logging information
            Find items to delete, leave it empty to delete all log.

        """

        self._fill_project_info(kwargs)
        self.db.Dataset.delete_many(kwargs)
        logging.info("[Database] Delete Dataset SUCCESS")

def
delete_datasets
(
self
,
*
*
kwargs
)
:
self
.
_fill_project_info
(
kwargs
)
self
.
db
.
Dataset
.
delete_many
(
kwargs
)
logging
.
info
(
"[Database] Delete Dataset SUCCESS"
)


def save_training_log(self, **kwargs):
        """Saves the training log, timestamp will be added automatically.

        Parameters
        -----------
        kwargs : logging information
            Events, such as accuracy, loss, step number and etc.

        Examples
        ---------
        >>> db.save_training_log(accuracy=0.33, loss=0.98)

        """

        self._fill_project_info(kwargs)
        kwargs.update({'time': datetime.utcnow()})
        _result = self.db.TrainLog.insert_one(kwargs)
        _log = self._print_dict(kwargs)
        logging.info("[Database] train log: " + _log)

def
save_training_log
(
self
,
*
*
kwargs
)
:
self
.
_fill_project_info
(
kwargs
)
kwargs
.
update
(
{
'time'
:
datetime
.
utcnow
(
)
}
)
_result
=
self
.
db
.
TrainLog
.
insert_one
(
kwargs
)
_log
=
self
.
_print_dict
(
kwargs
)
logging
.
info
(
"[Database] train log: "
+
_log
)

Saves the training log timestamp will be added automatically .


def save_validation_log(self, **kwargs):
        """Saves the validation log, timestamp will be added automatically.

        Parameters
        -----------
        kwargs : logging information
            Events, such as accuracy, loss, step number and etc.

        Examples
        ---------
        >>> db.save_validation_log(accuracy=0.33, loss=0.98)

        """

        self._fill_project_info(kwargs)
        kwargs.update({'time': datetime.utcnow()})
        _result = self.db.ValidLog.insert_one(kwargs)
        _log = self._print_dict(kwargs)
        logging.info("[Database] valid log: " + _log)

def
save_validation_log
(
self
,
*
*
kwargs
)
:
self
.
_fill_project_info
(
kwargs
)
kwargs
.
update
(
{
'time'
:
datetime
.
utcnow
(
)
}
)
_result
=
self
.
db
.
ValidLog
.
insert_one
(
kwargs
)
_log
=
self
.
_print_dict
(
kwargs
)
logging
.
info
(
"[Database] valid log: "
+
_log
)

Saves the validation log timestamp will be added automatically .


def delete_training_log(self, **kwargs):
        """Deletes training log.

        Parameters
        -----------
        kwargs : logging information
            Find items to delete, leave it empty to delete all log.

        Examples
        ---------
        Save training log
        >>> db.save_training_log(accuracy=0.33)
        >>> db.save_training_log(accuracy=0.44)

        Delete logs that match the requirement
        >>> db.delete_training_log(accuracy=0.33)

        Delete all logs
        >>> db.delete_training_log()
        """
        self._fill_project_info(kwargs)
        self.db.TrainLog.delete_many(kwargs)
        logging.info("[Database] Delete TrainLog SUCCESS")

def
delete_training_log
(
self
,
*
*
kwargs
)
:
self
.
_fill_project_info
(
kwargs
)
self
.
db
.
TrainLog
.
delete_many
(
kwargs
)
logging
.
info
(
"[Database] Delete TrainLog SUCCESS"
)


def delete_validation_log(self, **kwargs):
        """Deletes validation log.

        Parameters
        -----------
        kwargs : logging information
            Find items to delete, leave it empty to delete all log.

        Examples
        ---------
        - see ``save_training_log``.
        """
        self._fill_project_info(kwargs)
        self.db.ValidLog.delete_many(kwargs)
        logging.info("[Database] Delete ValidLog SUCCESS")

def
delete_validation_log
(
self
,
*
*
kwargs
)
:
self
.
_fill_project_info
(
kwargs
)
self
.
db
.
ValidLog
.
delete_many
(
kwargs
)
logging
.
info
(
"[Database] Delete ValidLog SUCCESS"
)


def create_task(self, task_name=None, script=None, hyper_parameters=None, saved_result_keys=None, **kwargs):
        """Uploads a task to the database, timestamp will be added automatically.

        Parameters
        -----------
        task_name : str
            The task name.
        script : str
            File name of the python script.
        hyper_parameters : dictionary
            The hyper parameters pass into the script.
        saved_result_keys : list of str
            The keys of the task results to keep in the database when the task finishes.
        kwargs : other parameters
            Users customized parameters such as description, version number.

        Examples
        -----------
        Uploads a task
        >>> db.create_task(task_name='mnist', script='example/tutorial_mnist_simple.py', description='simple tutorial')

        Finds and runs the latest task
        >>> db.run_top_task(sess=sess, sort=[("time", pymongo.DESCENDING)])
        >>> db.run_top_task(sess=sess, sort=[("time", -1)])

        Finds and runs the oldest task
        >>> db.run_top_task(sess=sess, sort=[("time", pymongo.ASCENDING)])
        >>> db.run_top_task(sess=sess, sort=[("time", 1)])

        """
        if not isinstance(task_name, str):  # is None:
            raise Exception("task_name should be string")
        if not isinstance(script, str):  # is None:
            raise Exception("script should be string")
        if hyper_parameters is None:
            hyper_parameters = {}
        if saved_result_keys is None:
            saved_result_keys = []

        self._fill_project_info(kwargs)
        kwargs.update({'time': datetime.utcnow()})
        kwargs.update({'hyper_parameters': hyper_parameters})
        kwargs.update({'saved_result_keys': saved_result_keys})

        _script = open(script, 'rb').read()

        kwargs.update({'status': 'pending', 'script': _script, 'result': {}})
        self.db.Task.insert_one(kwargs)
        logging.info("[Database] Saved Task - task_name: {} script: {}".format(task_name, script))

Uploads a task to the database timestamp will be added automatically .


def run_top_task(self, task_name=None, sort=None, **kwargs):
        """Finds and runs a pending task that in the first of the sorting list.

        Parameters
        -----------
        task_name : str
            The task name.
        sort : List of tuple
            PyMongo sort comment, search "PyMongo find one sorting" and `collection level operations <http://api.mongodb.com/python/current/api/pymongo/collection.html>`__ for more details.
        kwargs : other parameters
            Users customized parameters such as description, version number.

        Examples
        ---------
        Monitors the database and pull tasks to run
        >>> while True:
        >>>     print("waiting task from distributor")
        >>>     db.run_top_task(task_name='mnist', sort=[("time", -1)])
        >>>     time.sleep(1)

        Returns
        --------
        boolean : True for success, False for fail.
        """
        if not isinstance(task_name, str):  # is None:
            raise Exception("task_name should be string")
        self._fill_project_info(kwargs)
        kwargs.update({'status': 'pending'})

        # find task and set status to running
        task = self.db.Task.find_one_and_update(kwargs, {'$set': {'status': 'running'}}, sort=sort)

        try:
            # get task info e.g. hyper parameters, python script
            if task is None:
                logging.info("[Database] Find Task FAIL: key: {} sort: {}".format(task_name, sort))
                return False
            else:
                logging.info("[Database] Find Task SUCCESS: key: {} sort: {}".format(task_name, sort))
            _datetime = task['time']
            _script = task['script']
            _id = task['_id']
            _hyper_parameters = task['hyper_parameters']
            _saved_result_keys = task['saved_result_keys']
            logging.info("  hyper parameters:")
            for key in _hyper_parameters:
                globals()[key] = _hyper_parameters[key]
                logging.info("    {}: {}".format(key, _hyper_parameters[key]))
            # run task
            s = time.time()
            logging.info("[Database] Start Task: key: {} sort: {} push time: {}".format(task_name, sort, _datetime))
            _script = _script.decode('utf-8')
            with tf.Graph().as_default():  # as graph: # clear all TF graphs
                exec(_script, globals())

            # set status to finished
            _ = self.db.Task.find_one_and_update({'_id': _id}, {'$set': {'status': 'finished'}})

            # return results
            __result = {}
            for _key in _saved_result_keys:
                logging.info("  result: {}={} {}".format(_key, globals()[_key], type(globals()[_key])))
                __result.update({"%s" % _key: globals()[_key]})
            _ = self.db.Task.find_one_and_update(
                {
                    '_id': _id
                }, {'$set': {
                    'result': __result
                }}, return_document=pymongo.ReturnDocument.AFTER
            )
            logging.info(
                "[Database] Finished Task: task_name - {} sort: {} push time: {} took: {}s".
                format(task_name, sort, _datetime,
                       time.time() - s)
            )
            return True
        except Exception as e:
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            logging.info("{}  {}  {}  {}  {}".format(exc_type, exc_obj, fname, exc_tb.tb_lineno, e))
            logging.info("[Database] Fail to run task")
            # if fail, set status back to pending
            _ = self.db.Task.find_one_and_update({'_id': _id}, {'$set': {'status': 'pending'}})
            return False

Finds and runs a pending task that in the first of the sorting list .


def delete_tasks(self, **kwargs):
        """Delete tasks.

        Parameters
        -----------
        kwargs : logging information
            Find items to delete, leave it empty to delete all log.

        Examples
        ---------
        >>> db.delete_tasks()

        """

        self._fill_project_info(kwargs)
        self.db.Task.delete_many(kwargs)
        logging.info("[Database] Delete Task SUCCESS")

def
delete_tasks
(
self
,
*
*
kwargs
)
:
self
.
_fill_project_info
(
kwargs
)
self
.
db
.
Task
.
delete_many
(
kwargs
)
logging
.
info
(
"[Database] Delete Task SUCCESS"
)


def check_unfinished_task(self, task_name=None, **kwargs):
        """Finds and runs a pending task.

        Parameters
        -----------
        task_name : str
            The task name.
        kwargs : other parameters
            Users customized parameters such as description, version number.

        Examples
        ---------
        Wait until all tasks finish in user's local console

        >>> while not db.check_unfinished_task():
        >>>     time.sleep(1)
        >>> print("all tasks finished")
        >>> sess = tf.InteractiveSession()
        >>> net = db.find_top_model(sess=sess, sort=[("test_accuracy", -1)])
        >>> print("the best accuracy {} is from model {}".format(net._test_accuracy, net._name))

        Returns
        --------
        boolean : True for success, False for fail.

        """

        if not isinstance(task_name, str):  # is None:
            raise Exception("task_name should be string")
        self._fill_project_info(kwargs)

        kwargs.update({'$or': [{'status': 'pending'}, {'status': 'running'}]})

        # ## find task
        # task = self.db.Task.find_one(kwargs)
        task = self.db.Task.find(kwargs)

        task_id_list = task.distinct('_id')
        n_task = len(task_id_list)

        if n_task == 0:
            logging.info("[Database] No unfinished task - task_name: {}".format(task_name))
            return False
        else:

            logging.info("[Database] Find {} unfinished task - task_name: {}".format(n_task, task_name))
            return True


def augment_with_ngrams(unigrams, unigram_vocab_size, n_buckets, n=2):
    """Augment unigram features with hashed n-gram features."""

    def get_ngrams(n):
        return list(zip(*[unigrams[i:] for i in range(n)]))

    def hash_ngram(ngram):
        bytes_ = array.array('L', ngram).tobytes()
        hash_ = int(hashlib.sha256(bytes_).hexdigest(), 16)
        return unigram_vocab_size + hash_ % n_buckets

    return unigrams + [hash_ngram(ngram) for i in range(2, n + 1) for ngram in get_ngrams(i)]

def augment_with_ngrams ( unigrams , unigram_vocab_size , n_buckets , n = 2 ) : def get_ngrams ( n ) : return list ( zip ( * [ unigrams [ i : ] for i in range ( n ) ] ) ) def hash_ngram ( ngram ) : bytes_ = array . array ( 'L' , ngram ) . tobytes ( ) hash_ = int ( hashlib . sha256 ( bytes_ ) . hexdigest ( ) , 16 ) return unigram_vocab_size + hash_ % n_buckets return unigrams + [ hash_ngram ( ngram ) for i in range ( 2 , n + 1 ) for ngram in get_ngrams ( i ) ]

Augment unigram features with hashed n - gram features .


def load_and_preprocess_imdb_data(n_gram=None):
    """Load IMDb data and augment with hashed n-gram features."""
    X_train, y_train, X_test, y_test = tl.files.load_imdb_dataset(nb_words=VOCAB_SIZE)

    if n_gram is not None:
        X_train = np.array([augment_with_ngrams(x, VOCAB_SIZE, N_BUCKETS, n=n_gram) for x in X_train])
        X_test = np.array([augment_with_ngrams(x, VOCAB_SIZE, N_BUCKETS, n=n_gram) for x in X_test])

    return X_train, y_train, X_test, y_test

def load_and_preprocess_imdb_data ( n_gram = None ) : X_train , y_train , X_test , y_test = tl . files . load_imdb_dataset ( nb_words = VOCAB_SIZE ) if n_gram is not None : X_train = np . array ( [ augment_with_ngrams ( x , VOCAB_SIZE , N_BUCKETS , n = n_gram ) for x in X_train ] ) X_test = np . array ( [ augment_with_ngrams ( x , VOCAB_SIZE , N_BUCKETS , n = n_gram ) for x in X_test ] ) return X_train , y_train , X_test , y_test

Load IMDb data and augment with hashed n - gram features .


def read_image(image, path=''):
    """Read one image.

    Parameters
    -----------
    image : str
        The image file name.
    path : str
        The image folder path.

    Returns
    -------
    numpy.array
        The image.

    """
    return imageio.imread(os.path.join(path, image))

def read_image ( image , path = '' ) : return imageio . imread ( os . path . join ( path , image ) )


def read_images(img_list, path='', n_threads=10, printable=True):
    """Returns all images in list by given path and name of each image file.

    Parameters
    -------------
    img_list : list of str
        The image file names.
    path : str
        The image folder path.
    n_threads : int
        The number of threads to read image.
    printable : boolean
        Whether to print information when reading images.

    Returns
    -------
    list of numpy.array
        The images.

    """
    imgs = []
    for idx in range(0, len(img_list), n_threads):
        b_imgs_list = img_list[idx:idx + n_threads]
        b_imgs = tl.prepro.threading_data(b_imgs_list, fn=read_image, path=path)
        # tl.logging.info(b_imgs.shape)
        imgs.extend(b_imgs)
        if printable:
            tl.logging.info('read %d from %s' % (len(imgs), path))
    return imgs

def
read_images
(
img_list
,
path
=
''
,
n_threads
=
10
,
printable
=
True
)
:
imgs
=
[
]
for
idx
in
range
(
0
,
len
(
img_list
)
,
n_threads
)
:
b_imgs_list
=
img_list
[
idx
:
idx
+
n_threads
]
b_imgs
=
tl
.
prepro
.
threading_data
(
b_imgs_list
,
fn
=
read_image
,
path
=
path
)
# tl.logging.info(b_imgs.shape)
imgs
.
extend
(
b_imgs
)
if
printable
:
tl
.
logging
.
info
(
'read %d from %s'
%
(
len
(
imgs
)
,
path
)
)
return
imgs

Returns all images in list by given path and name of each image file .


def save_image(image, image_path='_temp.png'):
    """Save a image.

    Parameters
    -----------
    image : numpy array
        [w, h, c]
    image_path : str
        path

    """
    try:  # RGB
        imageio.imwrite(image_path, image)
    except Exception:  # Greyscale
        imageio.imwrite(image_path, image[:, :, 0])

def
save_image
(
image
,
image_path
=
'_temp.png'
)
:
try
:
# RGB
imageio
.
imwrite
(
image_path
,
image
)
except
Exception
:
# Greyscale
imageio
.
imwrite
(
image_path
,
image
[
:
,
:
,
0
]
)