def load_flickr25k_dataset(tag='sky', path="data", n_threads=50, printable=False):
    """Load Flickr25K dataset.

    Returns a list of images by a given tag from Flick25k dataset,
    it will download Flickr25k from `the official website <http://press.liacs.nl/mirflickr/mirdownload.html>`__
    at the first time you use it.

    Parameters
    ------------
    tag : str or None
        What images to return.
            - If you want to get images with tag, use string like 'dog', 'red', see `Flickr Search <https://www.flickr.com/search/>`__.
            - If you want to get all images, set to ``None``.

    path : str
        The path that the data is downloaded to, defaults is ``data/flickr25k/``.
    n_threads : int
        The number of thread to read image.
    printable : boolean
        Whether to print infomation when reading images, default is ``False``.

    Examples
    -----------
    Get images with tag of sky

    >>> images = tl.files.load_flickr25k_dataset(tag='sky')

    Get all images

    >>> images = tl.files.load_flickr25k_dataset(tag=None, n_threads=100, printable=True)

    """
    path = os.path.join(path, 'flickr25k')

    filename = 'mirflickr25k.zip'
    url = 'http://press.liacs.nl/mirflickr/mirflickr25k/'

    # download dataset
    if folder_exists(os.path.join(path, "mirflickr")) is False:
        logging.info("[*] Flickr25k is nonexistent in {}".format(path))
        maybe_download_and_extract(filename, path, url, extract=True)
        del_file(os.path.join(path, filename))

    # return images by the given tag.
    # 1. image path list
    folder_imgs = os.path.join(path, "mirflickr")
    path_imgs = load_file_list(path=folder_imgs, regx='\\.jpg', printable=False)
    path_imgs.sort(key=natural_keys)

    # 2. tag path list
    folder_tags = os.path.join(path, "mirflickr", "meta", "tags")
    path_tags = load_file_list(path=folder_tags, regx='\\.txt', printable=False)
    path_tags.sort(key=natural_keys)

    # 3. select images
    if tag is None:
        logging.info("[Flickr25k] reading all images")
    else:
        logging.info("[Flickr25k] reading images with tag: {}".format(tag))
    images_list = []
    for idx, _v in enumerate(path_tags):
        tags = read_file(os.path.join(folder_tags, path_tags[idx])).split('\n')
        # logging.info(idx+1, tags)
        if tag is None or tag in tags:
            images_list.append(path_imgs[idx])

    images = visualize.read_images(images_list, folder_imgs, n_threads=n_threads, printable=printable)
    return images


def download_file_from_google_drive(ID, destination):
    """Download file from Google Drive.

    See ``tl.files.load_celebA_dataset`` for example.

    Parameters
    --------------
    ID : str
        The driver ID.
    destination : str
        The destination for save file.

    """

    def save_response_content(response, destination, chunk_size=32 * 1024):
        total_size = int(response.headers.get('content-length', 0))
        with open(destination, "wb") as f:
            for chunk in tqdm(response.iter_content(chunk_size), total=total_size, unit='B', unit_scale=True,
                              desc=destination):
                if chunk:  # filter out keep-alive new chunks
                    f.write(chunk)

    def get_confirm_token(response):
        for key, value in response.cookies.items():
            if key.startswith('download_warning'):
                return value
        return None

    URL = "https://docs.google.com/uc?export=download"
    session = requests.Session()

    response = session.get(URL, params={'id': ID}, stream=True)
    token = get_confirm_token(response)

    if token:
        params = {'id': ID, 'confirm': token}
        response = session.get(URL, params=params, stream=True)
    save_response_content(response, destination)


def load_celebA_dataset(path='data'):
    """Load CelebA dataset

    Return a list of image path.

    Parameters
    -----------
    path : str
        The path that the data is downloaded to, defaults is ``data/celebA/``.

    """
    data_dir = 'celebA'
    filename, drive_id = "img_align_celeba.zip", "0B7EVK8r0v71pZjFTYXZWM3FlRnM"
    save_path = os.path.join(path, filename)
    image_path = os.path.join(path, data_dir)
    if os.path.exists(image_path):
        logging.info('[*] {} already exists'.format(save_path))
    else:
        exists_or_mkdir(path)
        download_file_from_google_drive(drive_id, save_path)
        zip_dir = ''
        with zipfile.ZipFile(save_path) as zf:
            zip_dir = zf.namelist()[0]
            zf.extractall(path)
        os.remove(save_path)
        os.rename(os.path.join(path, zip_dir), image_path)

    data_files = load_file_list(path=image_path, regx='\\.jpg', printable=False)
    for i, _v in enumerate(data_files):
        data_files[i] = os.path.join(image_path, data_files[i])
    return data_files

def
load_celebA_dataset
(
path
=
'data'
)
:
data_dir
=
'celebA'
filename
,
drive_id
=
"img_align_celeba.zip"
,
"0B7EVK8r0v71pZjFTYXZWM3FlRnM"
save_path
=
os
.
path
.
join
(
path
,
filename
)
image_path
=
os
.
path
.
join
(
path
,
data_dir
)
if
os
.
path
.
exists
(
image_path
)
:
logging
.
info
(
'[*] {} already exists'
.
format
(
save_path
)
)
else
:
exists_or_mkdir
(
path
)
download_file_from_google_drive
(
drive_id
,
save_path
)
zip_dir
=
''
with
zipfile
.
ZipFile
(
save_path
)
as
zf
:
zip_dir
=
zf
.
namelist
(
)
[
0
]
zf
.
extractall
(
path
)
os
.
remove
(
save_path
)
os
.
rename
(
os
.
path
.
join
(
path
,
zip_dir
)
,
image_path
)
data_files
=
load_file_list
(
path
=
image_path
,
regx
=
'\\.jpg'
,
printable
=
False
)
for
i
,
_v
in
enumerate
(
data_files
)
:
data_files
[
i
]
=
os
.
path
.
join
(
image_path
,
data_files
[
i
]
)
return
data_files


def assign_params(sess, params, network):
    """Assign the given parameters to the TensorLayer network.

    Parameters
    ----------
    sess : Session
        TensorFlow Session.
    params : list of array
        A list of parameters (array) in order.
    network : :class:`Layer`
        The network to be assigned.

    Returns
    --------
    list of operations
        A list of tf ops in order that assign params. Support sess.run(ops) manually.

    Examples
    --------
    - See ``tl.files.save_npz``

    References
    ----------
    - `Assign value to a TensorFlow variable <http://stackoverflow.com/questions/34220532/how-to-assign-value-to-a-tensorflow-variable>`__

    """
    ops = []
    for idx, param in enumerate(params):
        ops.append(network.all_params[idx].assign(param))
    if sess is not None:
        sess.run(ops)
    return ops

def assign_params ( sess , params , network ) : ops = [ ] for idx , param in enumerate ( params ) : ops . append ( network . all_params [ idx ] . assign ( param ) ) if sess is not None : sess . run ( ops ) return ops

Assign the given parameters to the TensorLayer network .


def load_and_assign_npz(sess=None, name=None, network=None):
    """Load model from npz and assign to a network.

    Parameters
    -------------
    sess : Session
        TensorFlow Session.
    name : str
        The name of the `.npz` file.
    network : :class:`Layer`
        The network to be assigned.

    Returns
    --------
    False or network
        Returns False, if the model is not exist.

    Examples
    --------
    - See ``tl.files.save_npz``

    """
    if network is None:
        raise ValueError("network is None.")
    if sess is None:
        raise ValueError("session is None.")
    if not os.path.exists(name):
        logging.error("file {} doesn't exist.".format(name))
        return False
    else:
        params = load_npz(name=name)
        assign_params(sess, params, network)
        logging.info("[*] Load {} SUCCESS!".format(name))
        return network

def
load_and_assign_npz
(
sess
=
,
name
=
,
network
=
)
:
if
network
is
:
raise
ValueError
(
"network is None."
)
if
sess
is
:
raise
ValueError
(
"session is None."
)
if
not
os
.
path
.
exists
(
name
)
:
logging
.
error
(
"file {} doesn't exist."
.
format
(
name
)
)
return
False
else
:
params
=
load_npz
(
name
=
name
)
assign_params
(
sess
,
params
,
network
)
logging
.
info
(
"[*] Load {} SUCCESS!"
.
format
(
name
)
)
return
network

Load model from npz and assign to a network .


def save_npz_dict(save_list=None, name='model.npz', sess=None):
    """Input parameters and the file name, save parameters as a dictionary into .npz file.

    Use ``tl.files.load_and_assign_npz_dict()`` to restore.

    Parameters
    ----------
    save_list : list of parameters
        A list of parameters (tensor) to be saved.
    name : str
        The name of the `.npz` file.
    sess : Session
        TensorFlow Session.

    """
    if sess is None:
        raise ValueError("session is None.")
    if save_list is None:
        save_list = []

    save_list_names = [tensor.name for tensor in save_list]
    save_list_var = sess.run(save_list)
    save_var_dict = {save_list_names[idx]: val for idx, val in enumerate(save_list_var)}
    np.savez(name, **save_var_dict)
    save_list_var = None
    save_var_dict = None
    del save_list_var
    del save_var_dict
    logging.info("[*] Model saved in npz_dict %s" % name)

def
save_npz_dict
(
save_list
=
,
name
=
'model.npz'
,
sess
=
)
:
if
sess
is
:
raise
ValueError
(
"session is None."
)
if
save_list
is
:
save_list
=
[
]
save_list_names
=
[
tensor
.
name
for
tensor
in
save_list
]
save_list_var
=
sess
.
run
(
save_list
)
save_var_dict
=
{
save_list_names
[
idx
]
:
val
for
idx
,
val
in
enumerate
(
save_list_var
)
}
np
.
savez
(
name
,
**
save_var_dict
)
save_list_var
=
save_var_dict
=
del
save_list_var
del
save_var_dict
logging
.
info
(
"[*] Model saved in npz_dict %s"
%
name
)

Input parameters and the file name save parameters as a dictionary into . npz file .


def save_ckpt(
        sess=None, mode_name='model.ckpt', save_dir='checkpoint', var_list=None, global_step=None, printable=False
):
    """Save parameters into `ckpt` file.

    Parameters
    ------------
    sess : Session
        TensorFlow Session.
    mode_name : str
        The name of the model, default is ``model.ckpt``.
    save_dir : str
        The path / file directory to the `ckpt`, default is ``checkpoint``.
    var_list : list of tensor
        The parameters / variables (tensor) to be saved. If empty, save all global variables (default).
    global_step : int or None
        Step number.
    printable : boolean
        Whether to print all parameters information.

    See Also
    --------
    load_ckpt

    """
    if sess is None:
        raise ValueError("session is None.")
    if var_list is None:
        var_list = []

    ckpt_file = os.path.join(save_dir, mode_name)
    if var_list == []:
        var_list = tf.global_variables()

    logging.info("[*] save %s n_params: %d" % (ckpt_file, len(var_list)))

    if printable:
        for idx, v in enumerate(var_list):
            logging.info("  param {:3}: {:15}   {}".format(idx, v.name, str(v.get_shape())))

    saver = tf.train.Saver(var_list)
    saver.save(sess, ckpt_file, global_step=global_step)

def
save_ckpt
(
sess
=
,
mode_name
=
'model.ckpt'
,
save_dir
=
'checkpoint'
,
var_list
=
,
global_step
=
,
printable
=
False
)
:
if
sess
is
:
raise
ValueError
(
"session is None."
)
if
var_list
is
:
var_list
=
[
]
ckpt_file
=
os
.
path
.
join
(
save_dir
,
mode_name
)
if
var_list
==
[
]
:
var_list
=
tf
.
global_variables
(
)
logging
.
info
(
"[*] save %s n_params: %d"
%
(
ckpt_file
,
len
(
var_list
)
)
)
if
printable
:
for
idx
,
v
in
enumerate
(
var_list
)
:
logging
.
info
(
"  param {:3}: {:15}   {}"
.
format
(
idx
,
v
.
name
,
str
(
v
.
get_shape
(
)
)
)
)
saver
=
tf
.
train
.
Saver
(
var_list
)
saver
.
save
(
sess
,
ckpt_file
,
global_step
=
global_step
)


def load_ckpt(sess=None, mode_name='model.ckpt', save_dir='checkpoint', var_list=None, is_latest=True, printable=False):
    """Load parameters from `ckpt` file.

    Parameters
    ------------
    sess : Session
        TensorFlow Session.
    mode_name : str
        The name of the model, default is ``model.ckpt``.
    save_dir : str
        The path / file directory to the `ckpt`, default is ``checkpoint``.
    var_list : list of tensor
        The parameters / variables (tensor) to be saved. If empty, save all global variables (default).
    is_latest : boolean
        Whether to load the latest `ckpt`, if False, load the `ckpt` with the name of ```mode_name``.
    printable : boolean
        Whether to print all parameters information.

    Examples
    ----------
    - Save all global parameters.

    >>> tl.files.save_ckpt(sess=sess, mode_name='model.ckpt', save_dir='model', printable=True)

    - Save specific parameters.

    >>> tl.files.save_ckpt(sess=sess, mode_name='model.ckpt', var_list=net.all_params, save_dir='model', printable=True)

    - Load latest ckpt.

    >>> tl.files.load_ckpt(sess=sess, var_list=net.all_params, save_dir='model', printable=True)

    - Load specific ckpt.

    >>> tl.files.load_ckpt(sess=sess, mode_name='model.ckpt', var_list=net.all_params, save_dir='model', is_latest=False, printable=True)

    """
    if sess is None:
        raise ValueError("session is None.")
    if var_list is None:
        var_list = []

    if is_latest:
        ckpt_file = tf.train.latest_checkpoint(save_dir)
    else:
        ckpt_file = os.path.join(save_dir, mode_name)

    if not var_list:
        var_list = tf.global_variables()

    logging.info("[*] load %s n_params: %d" % (ckpt_file, len(var_list)))

    if printable:
        for idx, v in enumerate(var_list):
            logging.info("  param {:3}: {:15}   {}".format(idx, v.name, str(v.get_shape())))

    try:
        saver = tf.train.Saver(var_list)
        saver.restore(sess, ckpt_file)
    except Exception as e:
        logging.info(e)
        logging.info("[*] load ckpt fail ...")

def
load_ckpt
(
sess
=
,
mode_name
=
'model.ckpt'
,
save_dir
=
'checkpoint'
,
var_list
=
,
is_latest
=
True
,
printable
=
False
)
:
if
sess
is
:
raise
ValueError
(
"session is None."
)
if
var_list
is
:
var_list
=
[
]
if
is_latest
:
ckpt_file
=
tf
.
train
.
latest_checkpoint
(
save_dir
)
else
:
ckpt_file
=
os
.
path
.
join
(
save_dir
,
mode_name
)
if
not
var_list
:
var_list
=
tf
.
global_variables
(
)
logging
.
info
(
"[*] load %s n_params: %d"
%
(
ckpt_file
,
len
(
var_list
)
)
)
if
printable
:
for
idx
,
v
in
enumerate
(
var_list
)
:
logging
.
info
(
"  param {:3}: {:15}   {}"
.
format
(
idx
,
v
.
name
,
str
(
v
.
get_shape
(
)
)
)
)
try
:
saver
=
tf
.
train
.
Saver
(
var_list
)
saver
.
restore
(
sess
,
ckpt_file
)
except
Exception
as
e
:
logging
.
info
(
e
)
logging
.
info
(
"[*] load ckpt fail ..."
)


def load_npy_to_any(path='', name='file.npy'):
    """Load `.npy` file.

    Parameters
    ------------
    path : str
        Path to the file (optional).
    name : str
        File name.

    Examples
    ---------
    - see tl.files.save_any_to_npy()

    """
    file_path = os.path.join(path, name)
    try:
        return np.load(file_path).item()
    except Exception:
        return np.load(file_path)
    raise Exception("[!] Fail to load %s" % file_path)

def
load_npy_to_any
(
path
=
''
,
name
=
'file.npy'
)
:
file_path
=
os
.
path
.
join
(
path
,
name
)
try
:
return
np
.
load
(
file_path
)
.
item
(
)
except
Exception
:
return
np
.
load
(
file_path
)
raise
Exception
(
"[!] Fail to load %s"
%
file_path
)


def load_file_list(path=None, regx='\.jpg', printable=True, keep_prefix=False):
    r"""Return a file list in a folder by given a path and regular expression.

    Parameters
    ----------
    path : str or None
        A folder path, if `None`, use the current directory.
    regx : str
        The regx of file name.
    printable : boolean
        Whether to print the files infomation.
    keep_prefix : boolean
        Whether to keep path in the file name.

    Examples
    ----------
    >>> file_list = tl.files.load_file_list(path=None, regx='w1pre_[0-9]+\.(npz)')

    """
    if path is None:
        path = os.getcwd()
    file_list = os.listdir(path)
    return_list = []
    for _, f in enumerate(file_list):
        if re.search(regx, f):
            return_list.append(f)
    # return_list.sort()
    if keep_prefix:
        for i, f in enumerate(return_list):
            return_list[i] = os.path.join(path, f)

    if printable:
        logging.info('Match file list = %s' % return_list)
        logging.info('Number of files = %d' % len(return_list))
    return return_list

def
load_file_list
(
path
=
,
regx
=
'\.jpg'
,
printable
=
True
,
keep_prefix
=
False
)
:
r
if
path
is
:
path
=
os
.
getcwd
(
)
file_list
=
os
.
listdir
(
path
)
return_list
=
[
]
for
_
,
f
in
enumerate
(
file_list
)
:
if
re
.
search
(
regx
,
f
)
:
return_list
.
append
(
f
)
if
keep_prefix
:
for
i
,
f
in
enumerate
(
return_list
)
:
return_list
[
i
]
=
os
.
path
.
join
(
path
,
f
)
if
printable
:
logging
.
info
(
'Match file list = %s'
%
return_list
)
logging
.
info
(
'Number of files = %d'
%
len
(
return_list
)
)
return
return_list

r Return a file list in a folder by given a path and regular expression .


def load_folder_list(path=""):
    """Return a folder list in a folder by given a folder path.

    Parameters
    ----------
    path : str
        A folder path.

    """
    return [os.path.join(path, o) for o in os.listdir(path) if os.path.isdir(os.path.join(path, o))]

def load_folder_list ( path = "" ) : return [ os . path . join ( path , o ) for o in os . listdir ( path ) if os . path . isdir ( os . path . join ( path , o ) ) ]

Return a folder list in a folder by given a folder path .


def exists_or_mkdir(path, verbose=True):
    """Check a folder by given name, if not exist, create the folder and return False,
    if directory exists, return True.

    Parameters
    ----------
    path : str
        A folder path.
    verbose : boolean
        If True (default), prints results.

    Returns
    --------
    boolean
        True if folder already exist, otherwise, returns False and create the folder.

    Examples
    --------
    >>> tl.files.exists_or_mkdir("checkpoints/train")

    """
    if not os.path.exists(path):
        if verbose:
            logging.info("[*] creates %s ..." % path)
        os.makedirs(path)
        return False
    else:
        if verbose:
            logging.info("[!] %s exists ..." % path)
        return True

def
exists_or_mkdir
(
path
,
verbose
=
True
)
:
if
not
os
.
path
.
exists
(
path
)
:
if
verbose
:
logging
.
info
(
"[*] creates %s ..."
%
path
)
os
.
makedirs
(
path
)
return
False
else
:
if
verbose
:
logging
.
info
(
"[!] %s exists ..."
%
path
)
return
True

Check a folder by given name if not exist create the folder and return False if directory exists return True .


def maybe_download_and_extract(filename, working_directory, url_source, extract=False, expected_bytes=None):
    """Checks if file exists in working_directory otherwise tries to dowload the file,
    and optionally also tries to extract the file if format is ".zip" or ".tar"

    Parameters
    -----------
    filename : str
        The name of the (to be) dowloaded file.
    working_directory : str
        A folder path to search for the file in and dowload the file to
    url : str
        The URL to download the file from
    extract : boolean
        If True, tries to uncompress the dowloaded file is ".tar.gz/.tar.bz2" or ".zip" file, default is False.
    expected_bytes : int or None
        If set tries to verify that the downloaded file is of the specified size, otherwise raises an Exception, defaults is None which corresponds to no check being performed.

    Returns
    ----------
    str
        File path of the dowloaded (uncompressed) file.

    Examples
    --------
    >>> down_file = tl.files.maybe_download_and_extract(filename='train-images-idx3-ubyte.gz',
    ...                                            working_directory='data/',
    ...                                            url_source='http://yann.lecun.com/exdb/mnist/')
    >>> tl.files.maybe_download_and_extract(filename='ADEChallengeData2016.zip',
    ...                                             working_directory='data/',
    ...                                             url_source='http://sceneparsing.csail.mit.edu/data/',
    ...                                             extract=True)

    """

    # We first define a download function, supporting both Python 2 and 3.
    def _download(filename, working_directory, url_source):

        progress_bar = progressbar.ProgressBar()

        def _dlProgress(count, blockSize, totalSize, pbar=progress_bar):
            if (totalSize != 0):

                if not pbar.max_value:
                    totalBlocks = math.ceil(float(totalSize) / float(blockSize))
                    pbar.max_value = int(totalBlocks)

                pbar.update(count, force=True)

        filepath = os.path.join(working_directory, filename)

        logging.info('Downloading %s...\n' % filename)

        urlretrieve(url_source + filename, filepath, reporthook=_dlProgress)

    exists_or_mkdir(working_directory, verbose=False)
    filepath = os.path.join(working_directory, filename)

    if not os.path.exists(filepath):

        _download(filename, working_directory, url_source)
        statinfo = os.stat(filepath)
        logging.info('Succesfully downloaded %s %s bytes.' % (filename, statinfo.st_size))  # , 'bytes.')
        if (not (expected_bytes is None) and (expected_bytes != statinfo.st_size)):
            raise Exception('Failed to verify ' + filename + '. Can you get to it with a browser?')
        if (extract):
            if tarfile.is_tarfile(filepath):
                logging.info('Trying to extract tar file')
                tarfile.open(filepath, 'r').extractall(working_directory)
                logging.info('... Success!')
            elif zipfile.is_zipfile(filepath):
                logging.info('Trying to extract zip file')
                with zipfile.ZipFile(filepath) as zf:
                    zf.extractall(working_directory)
                logging.info('... Success!')
            else:
                logging.info("Unknown compression_format only .tar.gz/.tar.bz2/.tar and .zip supported")
    return filepath

Checks if file exists in working_directory otherwise tries to dowload the file and optionally also tries to extract the file if format is . zip or . tar


def natural_keys(text):
    """Sort list of string with number in human order.

    Examples
    ----------
    >>> l = ['im1.jpg', 'im31.jpg', 'im11.jpg', 'im21.jpg', 'im03.jpg', 'im05.jpg']
    >>> l.sort(key=tl.files.natural_keys)
    ['im1.jpg', 'im03.jpg', 'im05', 'im11.jpg', 'im21.jpg', 'im31.jpg']
    >>> l.sort() # that is what we dont want
    ['im03.jpg', 'im05', 'im1.jpg', 'im11.jpg', 'im21.jpg', 'im31.jpg']

    References
    ----------
    - `link <http://nedbatchelder.com/blog/200712/human_sorting.html>`__

    """

    # - alist.sort(key=natural_keys) sorts in human order
    # http://nedbatchelder.com/blog/200712/human_sorting.html
    # (See Toothy's implementation in the comments)
    def atoi(text):
        return int(text) if text.isdigit() else text

    return [atoi(c) for c in re.split('(\d+)', text)]

def natural_keys ( text ) : def atoi ( text ) : return int ( text ) if text . isdigit ( ) else text return [ atoi ( c ) for c in re . split ( '(\d+)' , text ) ]

Sort list of string with number in human order .


def threading_data(data=None, fn=None, thread_count=None, **kwargs):
    """Process a batch of data by given function by threading.

    Usually be used for data augmentation.

    Parameters
    -----------
    data : numpy.array or others
        The data to be processed.
    thread_count : int
        The number of threads to use.
    fn : function
        The function for data processing.
    more args : the args for `fn`
        Ssee Examples below.

    Examples
    --------
    Process images.

    >>> images, _, _, _ = tl.files.load_cifar10_dataset(shape=(-1, 32, 32, 3))
    >>> images = tl.prepro.threading_data(images[0:32], tl.prepro.zoom, zoom_range=[0.5, 1])

    Customized image preprocessing function.

    >>> def distort_img(x):
    >>>     x = tl.prepro.flip_axis(x, axis=0, is_random=True)
    >>>     x = tl.prepro.flip_axis(x, axis=1, is_random=True)
    >>>     x = tl.prepro.crop(x, 100, 100, is_random=True)
    >>>     return x
    >>> images = tl.prepro.threading_data(images, distort_img)

    Process images and masks together (Usually be used for image segmentation).

    >>> X, Y --> [batch_size, row, col, 1]
    >>> data = tl.prepro.threading_data([_ for _ in zip(X, Y)], tl.prepro.zoom_multi, zoom_range=[0.5, 1], is_random=True)
    data --> [batch_size, 2, row, col, 1]
    >>> X_, Y_ = data.transpose((1,0,2,3,4))
    X_, Y_ --> [batch_size, row, col, 1]
    >>> tl.vis.save_image(X_, 'images.png')
    >>> tl.vis.save_image(Y_, 'masks.png')

    Process images and masks together by using ``thread_count``.

    >>> X, Y --> [batch_size, row, col, 1]
    >>> data = tl.prepro.threading_data(X, tl.prepro.zoom_multi, 8, zoom_range=[0.5, 1], is_random=True)
    data --> [batch_size, 2, row, col, 1]
    >>> X_, Y_ = data.transpose((1,0,2,3,4))
    X_, Y_ --> [batch_size, row, col, 1]
    >>> tl.vis.save_image(X_, 'after.png')
    >>> tl.vis.save_image(Y_, 'before.png')

    Customized function for processing images and masks together.

    >>> def distort_img(data):
    >>>    x, y = data
    >>>    x, y = tl.prepro.flip_axis_multi([x, y], axis=0, is_random=True)
    >>>    x, y = tl.prepro.flip_axis_multi([x, y], axis=1, is_random=True)
    >>>    x, y = tl.prepro.crop_multi([x, y], 100, 100, is_random=True)
    >>>    return x, y

    >>> X, Y --> [batch_size, row, col, channel]
    >>> data = tl.prepro.threading_data([_ for _ in zip(X, Y)], distort_img)
    >>> X_, Y_ = data.transpose((1,0,2,3,4))

    Returns
    -------
    list or numpyarray
        The processed results.

    References
    ----------
    - `python queue <https://pymotw.com/2/Queue/index.html#module-Queue>`__
    - `run with limited queue <http://effbot.org/librarybook/queue.htm>`__

    """

    def apply_fn(results, i, data, kwargs):
        results[i] = fn(data, **kwargs)

    if thread_count is None:
        results = [None] * len(data)
        threads = []
        # for i in range(len(data)):
        #     t = threading.Thread(name='threading_and_return', target=apply_fn, args=(results, i, data[i], kwargs))
        for i, d in enumerate(data):
            t = threading.Thread(name='threading_and_return', target=apply_fn, args=(results, i, d, kwargs))
            t.start()
            threads.append(t)
    else:
        divs = np.linspace(0, len(data), thread_count + 1)
        divs = np.round(divs).astype(int)
        results = [None] * thread_count
        threads = []
        for i in range(thread_count):
            t = threading.Thread(
                name='threading_and_return', target=apply_fn, args=(results, i, data[divs[i]:divs[i + 1]], kwargs)
            )
            t.start()
            threads.append(t)

    for t in threads:
        t.join()

    if thread_count is None:
        try:
            return np.asarray(results)
        except Exception:
            return results
    else:
        return np.concatenate(results)

def threading_data ( data = None , fn = None , thread_count = None , ** kwargs ) : def apply_fn ( results , i , data , kwargs ) : results [ i ] = fn ( data , ** kwargs ) if thread_count is None : results = [ None ] * len ( data ) threads = [ ] for i , d in enumerate ( data ) : t = threading . Thread ( name = 'threading_and_return' , target = apply_fn , args = ( results , i , d , kwargs ) ) t . start ( ) threads . append ( t ) else : divs = np . linspace ( 0 , len ( data ) , thread_count + 1 ) divs = np . round ( divs ) . astype ( int ) results = [ None ] * thread_count threads = [ ] for i in range ( thread_count ) : t = threading . Thread ( name = 'threading_and_return' , target = apply_fn , args = ( results , i , data [ divs [ i ] : divs [ i + 1 ] ] , kwargs ) ) t . start ( ) threads . append ( t ) for t in threads : t . join ( ) if thread_count is None : try : return np . asarray ( results ) except Exception : return results else : return np . concatenate ( results )

Process a batch of data by given function by threading .


def affine_transform_keypoints(coords_list, transform_matrix):
    """Transform keypoint coordinates according to a given affine transform matrix.
    OpenCV format, x is width.

    Note that, for pose estimation task, flipping requires maintaining the left and right body information.
    We should not flip the left and right body, so please use ``tl.prepro.keypoint_random_flip``.

    Parameters
    -----------
    coords_list : list of list of tuple/list
        The coordinates
        e.g., the keypoint coordinates of every person in an image.
    transform_matrix : numpy.array
        Transform matrix, OpenCV format.

    Examples
    ---------
    >>> # 1. get all affine transform matrices
    >>> M_rotate = tl.prepro.affine_rotation_matrix(angle=20)
    >>> M_flip = tl.prepro.affine_horizontal_flip_matrix(prob=1)
    >>> # 2. combine all affine transform matrices to one matrix
    >>> M_combined = dot(M_flip).dot(M_rotate)
    >>> # 3. transfrom the matrix from Cartesian coordinate (the origin in the middle of image)
    >>> # to Image coordinate (the origin on the top-left of image)
    >>> transform_matrix = tl.prepro.transform_matrix_offset_center(M_combined, x=w, y=h)
    >>> # 4. then we can transfrom the image once for all transformations
    >>> result = tl.prepro.affine_transform_cv2(image, transform_matrix)  # 76 times faster
    >>> # 5. transform keypoint coordinates
    >>> coords = [[(50, 100), (100, 100), (100, 50), (200, 200)], [(250, 50), (200, 50), (200, 100)]]
    >>> coords_result = tl.prepro.affine_transform_keypoints(coords, transform_matrix)
    """
    coords_result_list = []
    for coords in coords_list:
        coords = np.asarray(coords)
        coords = coords.transpose([1, 0])
        coords = np.insert(coords, 2, 1, axis=0)
        # print(coords)
        # print(transform_matrix)
        coords_result = np.matmul(transform_matrix, coords)
        coords_result = coords_result[0:2, :].transpose([1, 0])
        coords_result_list.append(coords_result)
    return coords_result_list

def affine_transform_keypoints ( coords_list , transform_matrix ) : coords_result_list = [ ] for coords in coords_list : coords = np . asarray ( coords ) coords = coords . transpose ( [ 1 , 0 ] ) coords = np . insert ( coords , 2 , 1 , axis = 0 ) coords_result = np . matmul ( transform_matrix , coords ) coords_result = coords_result [ 0 : 2 , : ] . transpose ( [ 1 , 0 ] ) coords_result_list . append ( coords_result ) return coords_result_list

Transform keypoint coordinates according to a given affine transform matrix . OpenCV format x is width .


def projective_transform_by_points(
        x, src, dst, map_args=None, output_shape=None, order=1, mode='constant', cval=0.0, clip=True,
        preserve_range=False
):
    """Projective transform by given coordinates, usually 4 coordinates.

    see `scikit-image <http://scikit-image.org/docs/dev/auto_examples/applications/plot_geometric.html>`__.

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    src : list or numpy
        The original coordinates, usually 4 coordinates of (width, height).
    dst : list or numpy
        The coordinates after transformation, the number of coordinates is the same with src.
    map_args : dictionary or None
        Keyword arguments passed to inverse map.
    output_shape : tuple of 2 int
        Shape of the output image generated. By default the shape of the input image is preserved. Note that, even for multi-band images, only rows and columns need to be specified.
    order : int
        The order of interpolation. The order has to be in the range 0-5:
            - 0 Nearest-neighbor
            - 1 Bi-linear (default)
            - 2 Bi-quadratic
            - 3 Bi-cubic
            - 4 Bi-quartic
            - 5 Bi-quintic
    mode : str
        One of `constant` (default), `edge`, `symmetric`, `reflect` or `wrap`.
        Points outside the boundaries of the input are filled according to the given mode. Modes match the behaviour of numpy.pad.
    cval : float
        Used in conjunction with mode `constant`, the value outside the image boundaries.
    clip : boolean
        Whether to clip the output to the range of values of the input image. This is enabled by default, since higher order interpolation may produce values outside the given input range.
    preserve_range : boolean
        Whether to keep the original range of values. Otherwise, the input image is converted according to the conventions of img_as_float.

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

    Examples
    --------
    Assume X is an image from CIFAR-10, i.e. shape == (32, 32, 3)

    >>> src = [[0,0],[0,32],[32,0],[32,32]]     # [w, h]
    >>> dst = [[10,10],[0,32],[32,0],[32,32]]
    >>> x = tl.prepro.projective_transform_by_points(X, src, dst)

    References
    -----------
    - `scikit-image : geometric transformations <http://scikit-image.org/docs/dev/auto_examples/applications/plot_geometric.html>`__
    - `scikit-image : examples <http://scikit-image.org/docs/dev/auto_examples/index.html>`__

    """
    if map_args is None:
        map_args = {}
    # if type(src) is list:
    if isinstance(src, list):  # convert to numpy
        src = np.array(src)
    # if type(dst) is list:
    if isinstance(dst, list):
        dst = np.array(dst)
    if np.max(x) > 1:  # convert to [0, 1]
        x = x / 255

    m = transform.ProjectiveTransform()
    m.estimate(dst, src)
    warped = transform.warp(
        x, m, map_args=map_args, output_shape=output_shape, order=order, mode=mode, cval=cval, clip=clip,
        preserve_range=preserve_range
    )
    return warped

def projective_transform_by_points ( x , src , dst , map_args = None , output_shape = None , order = 1 , mode = 'constant' , cval = 0.0 , clip = True , preserve_range = False ) : if map_args is None : map_args = { } if isinstance ( src , list ) : src = np . array ( src ) if isinstance ( dst , list ) : dst = np . array ( dst ) if np . max ( x ) > 1 : x = x / 255 m = transform . ProjectiveTransform ( ) m . estimate ( dst , src ) warped = transform . warp ( x , m , map_args = map_args , output_shape = output_shape , order = order , mode = mode , cval = cval , clip = clip , preserve_range = preserve_range ) return warped

Projective transform by given coordinates usually 4 coordinates .


def rotation(
        x, rg=20, is_random=False, row_index=0, col_index=1, channel_index=2, fill_mode='nearest', cval=0., order=1
):
    """Rotate an image randomly or non-randomly.

    Parameters
    -----------
    x : numpy.array
        An image with dimension of [row, col, channel] (default).
    rg : int or float
        Degree to rotate, usually 0 ~ 180.
    is_random : boolean
        If True, randomly rotate. 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.

    Examples
    ---------
    >>> x --> [row, col, 1]
    >>> x = tl.prepro.rotation(x, rg=40, is_random=False)
    >>> tl.vis.save_image(x, 'im.png')

    """
    if is_random:
        theta = np.pi / 180 * np.random.uniform(-rg, rg)
    else:
        theta = np.pi / 180 * rg
    rotation_matrix = np.array([[np.cos(theta), -np.sin(theta), 0], [np.sin(theta), np.cos(theta), 0], [0, 0, 1]])

    h, w = x.shape[row_index], x.shape[col_index]
    transform_matrix = transform_matrix_offset_center(rotation_matrix, h, w)
    x = affine_transform(x, transform_matrix, channel_index, fill_mode, cval, order)
    return x

def rotation ( x , rg = 20 , is_random = False , row_index = 0 , col_index = 1 , channel_index = 2 , fill_mode = 'nearest' , cval = 0. , order = 1 ) : if is_random : theta = np . pi / 180 * np . random . uniform ( - rg , rg ) else : theta = np . pi / 180 * rg rotation_matrix = np . array ( [ [ np . cos ( theta ) , - np . sin ( theta ) , 0 ] , [ np . sin ( theta ) , np . cos ( theta ) , 0 ] , [ 0 , 0 , 1 ] ] ) h , w = x . shape [ row_index ] , x . shape [ col_index ] transform_matrix = transform_matrix_offset_center ( rotation_matrix , h , w ) x = affine_transform ( x , transform_matrix , channel_index , fill_mode , cval , order ) return x

Rotate an image randomly or non - randomly .


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 : 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 : 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 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 ) 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 = None , interp = 'bicubic' , mode = None ) : if size is None : size = [ 100 , 100 ] if x . shape [ - 1 ] == 1 : x = scipy . misc . imresize ( x [ : , : , 0 ] , size , interp = interp , mode = mode ) return x [ : , : , np . newaxis ] else : 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
:
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
:
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

def zca_whitening ( x , principal_components ) : flatx = np . reshape ( x , ( x . size ) ) 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
:
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
:
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
:
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
:
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 ) : r 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 remove_pad_sequences ( sequences , pad_id = 0 ) : sequences_out = copy . deepcopy ( sequences ) for i , _ in enumerate ( sequences ) : 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 sequences_get_mask ( sequences , pad_val = 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 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])

def keypoint_random_crop ( image , annos , mask = None , size = ( 368 , 368 ) ) : _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 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 ) : 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_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 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 = 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 ) ) : _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 : 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 = None , 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 None : mask = cv2 . resize ( mask , ( neww , newh ) , interpolation = cv2 . INTER_AREA ) adjust_joint_list = [ ] for joint in annos : 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

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 binary_cross_entropy ( output , target , epsilon = 1e-8 , name = 'bce_loss' ) : 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

def normalized_mean_square_error ( output , target , name = "normalized_mean_squared_error_loss" ) : if output . get_shape ( ) . ndims == 2 : 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 : 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 : 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

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