def buf_to_float(x, n_bytes=2, dtype=np.float32):
    """Convert an integer buffer to floating point values.
    This is primarily useful when loading integer-valued wav data
    into numpy arrays.

    See Also
    --------
    buf_to_float

    Parameters
    ----------
    x : np.ndarray [dtype=int]
        The integer-valued data buffer

    n_bytes : int [1, 2, 4]
        The number of bytes per sample in `x`

    dtype : numeric type
        The target output type (default: 32-bit float)

    Returns
    -------
    x_float : np.ndarray [dtype=float]
        The input data buffer cast to floating point
    """

    # Invert the scale of the data
    scale = 1./float(1 << ((8 * n_bytes) - 1))

    # Construct the format string
    fmt = '<i{:d}'.format(n_bytes)

    # Rescale and format the data buffer
    return scale * np.frombuffer(x, fmt).astype(dtype)

def
buf_to_float
(
x
,
n_bytes
=
2
,
dtype
=
np
.
float32
)
:
# Invert the scale of the data
scale
=
1.
/
float
(
1
<<
(
(
8
*
n_bytes
)
1
)
)
# Construct the format string
fmt
=
'<i{:d}'
.
format
(
n_bytes
)
# Rescale and format the data buffer
return
scale
*
np
.
frombuffer
(
x
,
fmt
)
.
astype
(
dtype
)

Convert an integer buffer to floating point values . This is primarily useful when loading integer - valued wav data into numpy arrays .


def index_to_slice(idx, idx_min=None, idx_max=None, step=None, pad=True):
    '''Generate a slice array from an index array.

    Parameters
    ----------
    idx : list-like
        Array of index boundaries

    idx_min : None or int
    idx_max : None or int
        Minimum and maximum allowed indices

    step : None or int
        Step size for each slice.  If `None`, then the default
        step of 1 is used.

    pad : boolean
        If `True`, pad `idx` to span the range `idx_min:idx_max`.

    Returns
    -------
    slices : list of slice
        ``slices[i] = slice(idx[i], idx[i+1], step)``
        Additional slice objects may be added at the beginning or end,
        depending on whether ``pad==True`` and the supplied values for
        `idx_min` and `idx_max`.

    See Also
    --------
    fix_frames

    Examples
    --------
    >>> # Generate slices from spaced indices
    >>> librosa.util.index_to_slice(np.arange(20, 100, 15))
    [slice(20, 35, None), slice(35, 50, None), slice(50, 65, None), slice(65, 80, None),
     slice(80, 95, None)]
    >>> # Pad to span the range (0, 100)
    >>> librosa.util.index_to_slice(np.arange(20, 100, 15),
    ...                             idx_min=0, idx_max=100)
    [slice(0, 20, None), slice(20, 35, None), slice(35, 50, None), slice(50, 65, None),
     slice(65, 80, None), slice(80, 95, None), slice(95, 100, None)]
    >>> # Use a step of 5 for each slice
    >>> librosa.util.index_to_slice(np.arange(20, 100, 15),
    ...                             idx_min=0, idx_max=100, step=5)
    [slice(0, 20, 5), slice(20, 35, 5), slice(35, 50, 5), slice(50, 65, 5), slice(65, 80, 5),
     slice(80, 95, 5), slice(95, 100, 5)]
    '''

    # First, normalize the index set
    idx_fixed = fix_frames(idx, idx_min, idx_max, pad=pad)

    # Now convert the indices to slices
    return [slice(start, end, step) for (start, end) in zip(idx_fixed, idx_fixed[1:])]

def
index_to_slice
(
idx
,
idx_min
=
,
idx_max
=
,
step
=
,
pad
=
True
)
:
# First, normalize the index set
idx_fixed
=
fix_frames
(
idx
,
idx_min
,
idx_max
,
pad
=
pad
)
# Now convert the indices to slices
return
[
slice
(
start
,
end
,
step
)
for
(
start
,
end
)
in
zip
(
idx_fixed
,
idx_fixed
[
1
:
]
)
]

Generate a slice array from an index array .


def sync(data, idx, aggregate=None, pad=True, axis=-1):
    """Synchronous aggregation of a multi-dimensional array between boundaries

    .. note::
        In order to ensure total coverage, boundary points may be added
        to `idx`.

        If synchronizing a feature matrix against beat tracker output, ensure
        that frame index numbers are properly aligned and use the same hop length.

    Parameters
    ----------
    data      : np.ndarray
        multi-dimensional array of features

    idx : iterable of ints or slices
        Either an ordered array of boundary indices, or
        an iterable collection of slice objects.

    aggregate : function
        aggregation function (default: `np.mean`)

    pad : boolean
        If `True`, `idx` is padded to span the full range `[0, data.shape[axis]]`

    axis : int
        The axis along which to aggregate data

    Returns
    -------
    data_sync : ndarray
        `data_sync` will have the same dimension as `data`, except that the `axis`
        coordinate will be reduced according to `idx`.

        For example, a 2-dimensional `data` with `axis=-1` should satisfy

        `data_sync[:, i] = aggregate(data[:, idx[i-1]:idx[i]], axis=-1)`

    Raises
    ------
    ParameterError
        If the index set is not of consistent type (all slices or all integers)

    Notes
    -----
    This function caches at level 40.

    Examples
    --------
    Beat-synchronous CQT spectra

    >>> y, sr = librosa.load(librosa.util.example_audio_file())
    >>> tempo, beats = librosa.beat.beat_track(y=y, sr=sr, trim=False)
    >>> C = np.abs(librosa.cqt(y=y, sr=sr))
    >>> beats = librosa.util.fix_frames(beats, x_max=C.shape[1])

    By default, use mean aggregation

    >>> C_avg = librosa.util.sync(C, beats)

    Use median-aggregation instead of mean

    >>> C_med = librosa.util.sync(C, beats,
    ...                             aggregate=np.median)

    Or sub-beat synchronization

    >>> sub_beats = librosa.segment.subsegment(C, beats)
    >>> sub_beats = librosa.util.fix_frames(sub_beats, x_max=C.shape[1])
    >>> C_med_sub = librosa.util.sync(C, sub_beats, aggregate=np.median)

    Plot the results

    >>> import matplotlib.pyplot as plt
    >>> beat_t = librosa.frames_to_time(beats, sr=sr)
    >>> subbeat_t = librosa.frames_to_time(sub_beats, sr=sr)
    >>> plt.figure()
    >>> plt.subplot(3, 1, 1)
    >>> librosa.display.specshow(librosa.amplitude_to_db(C,
    ...                                                  ref=np.max),
    ...                          x_axis='time')
    >>> plt.title('CQT power, shape={}'.format(C.shape))
    >>> plt.subplot(3, 1, 2)
    >>> librosa.display.specshow(librosa.amplitude_to_db(C_med,
    ...                                                  ref=np.max),
    ...                          x_coords=beat_t, x_axis='time')
    >>> plt.title('Beat synchronous CQT power, '
    ...           'shape={}'.format(C_med.shape))
    >>> plt.subplot(3, 1, 3)
    >>> librosa.display.specshow(librosa.amplitude_to_db(C_med_sub,
    ...                                                  ref=np.max),
    ...                          x_coords=subbeat_t, x_axis='time')
    >>> plt.title('Sub-beat synchronous CQT power, '
    ...           'shape={}'.format(C_med_sub.shape))
    >>> plt.tight_layout()

    """

    if aggregate is None:
        aggregate = np.mean

    shape = list(data.shape)

    if np.all([isinstance(_, slice) for _ in idx]):
        slices = idx
    elif np.all([np.issubdtype(type(_), np.integer) for _ in idx]):
        slices = index_to_slice(np.asarray(idx), 0, shape[axis], pad=pad)
    else:
        raise ParameterError('Invalid index set: {}'.format(idx))

    agg_shape = list(shape)
    agg_shape[axis] = len(slices)

    data_agg = np.empty(agg_shape, order='F' if np.isfortran(data) else 'C', dtype=data.dtype)

    idx_in = [slice(None)] * data.ndim
    idx_agg = [slice(None)] * data_agg.ndim

    for (i, segment) in enumerate(slices):
        idx_in[axis] = segment
        idx_agg[axis] = i
        data_agg[tuple(idx_agg)] = aggregate(data[tuple(idx_in)], axis=axis)

    return data_agg

def
sync
(
data
,
idx
,
aggregate
=
,
pad
=
True
,
axis
=
1
)
:
if
aggregate
is
:
aggregate
=
np
.
mean
shape
=
list
(
data
.
shape
)
if
np
.
all
(
[
isinstance
(
_
,
slice
)
for
_
in
idx
]
)
:
slices
=
idx
elif
np
.
all
(
[
np
.
issubdtype
(
type
(
_
)
,
np
.
integer
)
for
_
in
idx
]
)
:
slices
=
index_to_slice
(
np
.
asarray
(
idx
)
,
0
,
shape
[
axis
]
,
pad
=
pad
)
else
:
raise
ParameterError
(
'Invalid index set: {}'
.
format
(
idx
)
)
agg_shape
=
list
(
shape
)
agg_shape
[
axis
]
=
len
(
slices
)
data_agg
=
np
.
empty
(
agg_shape
,
order
=
'F'
if
np
.
isfortran
(
data
)
else
'C'
,
dtype
=
data
.
dtype
)
idx_in
=
[
slice
(
)
]
*
data
.
ndim
idx_agg
=
[
slice
(
)
]
*
data_agg
.
ndim
for
(
i
,
segment
)
in
enumerate
(
slices
)
:
idx_in
[
axis
]
=
segment
idx_agg
[
axis
]
=
i
data_agg
[
tuple
(
idx_agg
)
]
=
aggregate
(
data
[
tuple
(
idx_in
)
]
,
axis
=
axis
)
return
data_agg

Synchronous aggregation of a multi - dimensional array between boundaries


def softmask(X, X_ref, power=1, split_zeros=False):
    '''Robustly compute a softmask operation.

        `M = X**power / (X**power + X_ref**power)`

    Parameters
    ----------
    X : np.ndarray
        The (non-negative) input array corresponding to the positive mask elements

    X_ref : np.ndarray
        The (non-negative) array of reference or background elements.
        Must have the same shape as `X`.

    power : number > 0 or np.inf
        If finite, returns the soft mask computed in a numerically stable way

        If infinite, returns a hard (binary) mask equivalent to `X > X_ref`.
        Note: for hard masks, ties are always broken in favor of `X_ref` (`mask=0`).

    split_zeros : bool
        If `True`, entries where `X` and X`_ref` are both small (close to 0)
        will receive mask values of 0.5.

        Otherwise, the mask is set to 0 for these entries.

    Returns
    -------
    mask : np.ndarray, shape=`X.shape`
        The output mask array

    Raises
    ------
    ParameterError
        If `X` and `X_ref` have different shapes.

        If `X` or `X_ref` are negative anywhere

        If `power <= 0`

    Examples
    --------

    >>> X = 2 * np.ones((3, 3))
    >>> X_ref = np.vander(np.arange(3.0))
    >>> X
    array([[ 2.,  2.,  2.],
           [ 2.,  2.,  2.],
           [ 2.,  2.,  2.]])
    >>> X_ref
    array([[ 0.,  0.,  1.],
           [ 1.,  1.,  1.],
           [ 4.,  2.,  1.]])
    >>> librosa.util.softmask(X, X_ref, power=1)
    array([[ 1.   ,  1.   ,  0.667],
           [ 0.667,  0.667,  0.667],
           [ 0.333,  0.5  ,  0.667]])
    >>> librosa.util.softmask(X_ref, X, power=1)
    array([[ 0.   ,  0.   ,  0.333],
           [ 0.333,  0.333,  0.333],
           [ 0.667,  0.5  ,  0.333]])
    >>> librosa.util.softmask(X, X_ref, power=2)
    array([[ 1. ,  1. ,  0.8],
           [ 0.8,  0.8,  0.8],
           [ 0.2,  0.5,  0.8]])
    >>> librosa.util.softmask(X, X_ref, power=4)
    array([[ 1.   ,  1.   ,  0.941],
           [ 0.941,  0.941,  0.941],
           [ 0.059,  0.5  ,  0.941]])
    >>> librosa.util.softmask(X, X_ref, power=100)
    array([[  1.000e+00,   1.000e+00,   1.000e+00],
           [  1.000e+00,   1.000e+00,   1.000e+00],
           [  7.889e-31,   5.000e-01,   1.000e+00]])
    >>> librosa.util.softmask(X, X_ref, power=np.inf)
    array([[ True,  True,  True],
           [ True,  True,  True],
           [False, False,  True]], dtype=bool)
    '''
    if X.shape != X_ref.shape:
        raise ParameterError('Shape mismatch: {}!={}'.format(X.shape,
                                                             X_ref.shape))

    if np.any(X < 0) or np.any(X_ref < 0):
        raise ParameterError('X and X_ref must be non-negative')

    if power <= 0:
        raise ParameterError('power must be strictly positive')

    # We're working with ints, cast to float.
    dtype = X.dtype
    if not np.issubdtype(dtype, np.floating):
        dtype = np.float32

    # Re-scale the input arrays relative to the larger value
    Z = np.maximum(X, X_ref).astype(dtype)
    bad_idx = (Z < np.finfo(dtype).tiny)
    Z[bad_idx] = 1

    # For finite power, compute the softmask
    if np.isfinite(power):
        mask = (X / Z)**power
        ref_mask = (X_ref / Z)**power
        good_idx = ~bad_idx
        mask[good_idx] /= mask[good_idx] + ref_mask[good_idx]
        # Wherever energy is below energy in both inputs, split the mask
        if split_zeros:
            mask[bad_idx] = 0.5
        else:
            mask[bad_idx] = 0.0
    else:
        # Otherwise, compute the hard mask
        mask = X > X_ref

    return mask


def tiny(x):
    '''Compute the tiny-value corresponding to an input's data type.

    This is the smallest "usable" number representable in `x`'s
    data type (e.g., float32).

    This is primarily useful for determining a threshold for
    numerical underflow in division or multiplication operations.

    Parameters
    ----------
    x : number or np.ndarray
        The array to compute the tiny-value for.
        All that matters here is `x.dtype`.

    Returns
    -------
    tiny_value : float
        The smallest positive usable number for the type of `x`.
        If `x` is integer-typed, then the tiny value for `np.float32`
        is returned instead.

    See Also
    --------
    numpy.finfo

    Examples
    --------

    For a standard double-precision floating point number:

    >>> librosa.util.tiny(1.0)
    2.2250738585072014e-308

    Or explicitly as double-precision

    >>> librosa.util.tiny(np.asarray(1e-5, dtype=np.float64))
    2.2250738585072014e-308

    Or complex numbers

    >>> librosa.util.tiny(1j)
    2.2250738585072014e-308

    Single-precision floating point:

    >>> librosa.util.tiny(np.asarray(1e-5, dtype=np.float32))
    1.1754944e-38

    Integer

    >>> librosa.util.tiny(5)
    1.1754944e-38
    '''

    # Make sure we have an array view
    x = np.asarray(x)

    # Only floating types generate a tiny
    if np.issubdtype(x.dtype, np.floating) or np.issubdtype(x.dtype, np.complexfloating):
        dtype = x.dtype
    else:
        dtype = np.float32

    return np.finfo(dtype).tiny

def
tiny
(
x
)
:
# Make sure we have an array view
x
=
np
.
asarray
(
x
)
# Only floating types generate a tiny
if
np
.
issubdtype
(
x
.
dtype
,
np
.
floating
)
or
np
.
issubdtype
(
x
.
dtype
,
np
.
complexfloating
)
:
dtype
=
x
.
dtype
else
:
dtype
=
np
.
float32
return
np
.
finfo
(
dtype
)
.
tiny

Compute the tiny - value corresponding to an input s data type .


def frames2video(frame_dir,
                 video_file,
                 fps=30,
                 fourcc='XVID',
                 filename_tmpl='{:06d}.jpg',
                 start=0,
                 end=0,
                 show_progress=True):
    """Read the frame images from a directory and join them as a video

    Args:
        frame_dir (str): The directory containing video frames.
        video_file (str): Output filename.
        fps (float): FPS of the output video.
        fourcc (str): Fourcc of the output video, this should be compatible
            with the output file type.
        filename_tmpl (str): Filename template with the index as the variable.
        start (int): Starting frame index.
        end (int): Ending frame index.
        show_progress (bool): Whether to show a progress bar.
    """
    if end == 0:
        ext = filename_tmpl.split('.')[-1]
        end = len([name for name in scandir(frame_dir, ext)])
    first_file = osp.join(frame_dir, filename_tmpl.format(start))
    check_file_exist(first_file, 'The start frame not found: ' + first_file)
    img = cv2.imread(first_file)
    height, width = img.shape[:2]
    resolution = (width, height)
    vwriter = cv2.VideoWriter(video_file, VideoWriter_fourcc(*fourcc), fps,
                              resolution)

    def write_frame(file_idx):
        filename = osp.join(frame_dir, filename_tmpl.format(file_idx))
        img = cv2.imread(filename)
        vwriter.write(img)

    if show_progress:
        track_progress(write_frame, range(start, end))
    else:
        for i in range(start, end):
            filename = osp.join(frame_dir, filename_tmpl.format(i))
            img = cv2.imread(filename)
            vwriter.write(img)
    vwriter.release()

def
frames2video
(
frame_dir
,
video_file
,
fps
=
30
,
fourcc
=
'XVID'
,
filename_tmpl
=
'{:06d}.jpg'
,
start
=
0
,
end
=
0
,
show_progress
=
True
)
:
if
end
==
0
:
ext
=
filename_tmpl
.
split
(
'.'
)
[
1
]
end
=
len
(
[
name
for
name
in
scandir
(
frame_dir
,
ext
)
]
)
first_file
=
osp
.
join
(
frame_dir
,
filename_tmpl
.
format
(
start
)
)
check_file_exist
(
first_file
,
'The start frame not found: '
+
first_file
)
img
=
cv2
.
imread
(
first_file
)
height
,
width
=
img
.
shape
[
:
2
]
resolution
=
(
width
,
height
)
vwriter
=
cv2
.
VideoWriter
(
video_file
,
VideoWriter_fourcc
(
*
fourcc
)
,
fps
,
resolution
)
def
write_frame
(
file_idx
)
:
filename
=
osp
.
join
(
frame_dir
,
filename_tmpl
.
format
(
file_idx
)
)
img
=
cv2
.
imread
(
filename
)
vwriter
.
write
(
img
)
if
show_progress
:
track_progress
(
write_frame
,
range
(
start
,
end
)
)
else
:
for
i
in
range
(
start
,
end
)
:
filename
=
osp
.
join
(
frame_dir
,
filename_tmpl
.
format
(
i
)
)
img
=
cv2
.
imread
(
filename
)
vwriter
.
write
(
img
)
vwriter
.
release
(
)


def read(self):
        """Read the next frame.

        If the next frame have been decoded before and in the cache, then
        return it directly, otherwise decode, cache and return it.

        Returns:
            ndarray or None: Return the frame if successful, otherwise None.
        """
        # pos = self._position
        if self._cache:
            img = self._cache.get(self._position)
            if img is not None:
                ret = True
            else:
                if self._position != self._get_real_position():
                    self._set_real_position(self._position)
                ret, img = self._vcap.read()
                if ret:
                    self._cache.put(self._position, img)
        else:
            ret, img = self._vcap.read()
        if ret:
            self._position += 1
        return img

def
read
(
self
)
:
# pos = self._position
if
self
.
_cache
:
img
=
self
.
_cache
.
get
(
self
.
_position
)
if
img
is
not
:
ret
=
True
else
:
if
self
.
_position
!=
self
.
_get_real_position
(
)
:
self
.
_set_real_position
(
self
.
_position
)
ret
,
img
=
self
.
_vcap
.
read
(
)
if
ret
:
self
.
_cache
.
put
(
self
.
_position
,
img
)
else
:
ret
,
img
=
self
.
_vcap
.
read
(
)
if
ret
:
self
.
_position
+=
1
return
img


def get_frame(self, frame_id):
        """Get frame by index.

        Args:
            frame_id (int): Index of the expected frame, 0-based.

        Returns:
            ndarray or None: Return the frame if successful, otherwise None.
        """
        if frame_id < 0 or frame_id >= self._frame_cnt:
            raise IndexError(
                '"frame_id" must be between 0 and {}'.format(self._frame_cnt -
                                                             1))
        if frame_id == self._position:
            return self.read()
        if self._cache:
            img = self._cache.get(frame_id)
            if img is not None:
                self._position = frame_id + 1
                return img
        self._set_real_position(frame_id)
        ret, img = self._vcap.read()
        if ret:
            if self._cache:
                self._cache.put(self._position, img)
            self._position += 1
        return img

def
get_frame
(
self
,
frame_id
)
:
if
frame_id
<
0
or
frame_id
>=
self
.
_frame_cnt
:
raise
IndexError
(
'"frame_id" must be between 0 and {}'
.
format
(
self
.
_frame_cnt
1
)
)
if
frame_id
==
self
.
_position
:
return
self
.
read
(
)
if
self
.
_cache
:
img
=
self
.
_cache
.
get
(
frame_id
)
if
img
is
not
:
self
.
_position
=
frame_id
+
1
return
img
self
.
_set_real_position
(
frame_id
)
ret
,
img
=
self
.
_vcap
.
read
(
)
if
ret
:
if
self
.
_cache
:
self
.
_cache
.
put
(
self
.
_position
,
img
)
self
.
_position
+=
1
return
img


def cvt2frames(self,
                   frame_dir,
                   file_start=0,
                   filename_tmpl='{:06d}.jpg',
                   start=0,
                   max_num=0,
                   show_progress=True):
        """Convert a video to frame images

        Args:
            frame_dir (str): Output directory to store all the frame images.
            file_start (int): Filenames will start from the specified number.
            filename_tmpl (str): Filename template with the index as the
                placeholder.
            start (int): The starting frame index.
            max_num (int): Maximum number of frames to be written.
            show_progress (bool): Whether to show a progress bar.
        """
        mkdir_or_exist(frame_dir)
        if max_num == 0:
            task_num = self.frame_cnt - start
        else:
            task_num = min(self.frame_cnt - start, max_num)
        if task_num <= 0:
            raise ValueError('start must be less than total frame number')
        if start > 0:
            self._set_real_position(start)

        def write_frame(file_idx):
            img = self.read()
            filename = osp.join(frame_dir, filename_tmpl.format(file_idx))
            cv2.imwrite(filename, img)

        if show_progress:
            track_progress(write_frame, range(file_start,
                                              file_start + task_num))
        else:
            for i in range(task_num):
                img = self.read()
                if img is None:
                    break
                filename = osp.join(frame_dir,
                                    filename_tmpl.format(i + file_start))
                cv2.imwrite(filename, img)


def track_progress(func, tasks, bar_width=50, **kwargs):
    """Track the progress of tasks execution with a progress bar.

    Tasks are done with a simple for-loop.

    Args:
        func (callable): The function to be applied to each task.
        tasks (list or tuple[Iterable, int]): A list of tasks or
            (tasks, total num).
        bar_width (int): Width of progress bar.

    Returns:
        list: The task results.
    """
    if isinstance(tasks, tuple):
        assert len(tasks) == 2
        assert isinstance(tasks[0], collections_abc.Iterable)
        assert isinstance(tasks[1], int)
        task_num = tasks[1]
        tasks = tasks[0]
    elif isinstance(tasks, collections_abc.Iterable):
        task_num = len(tasks)
    else:
        raise TypeError(
            '"tasks" must be an iterable object or a (iterator, int) tuple')
    prog_bar = ProgressBar(task_num, bar_width)
    results = []
    for task in tasks:
        results.append(func(task, **kwargs))
        prog_bar.update()
    sys.stdout.write('\n')
    return results

Track the progress of tasks execution with a progress bar .


def track_parallel_progress(func,
                            tasks,
                            nproc,
                            initializer=None,
                            initargs=None,
                            bar_width=50,
                            chunksize=1,
                            skip_first=False,
                            keep_order=True):
    """Track the progress of parallel task execution with a progress bar.

    The built-in :mod:`multiprocessing` module is used for process pools and
    tasks are done with :func:`Pool.map` or :func:`Pool.imap_unordered`.

    Args:
        func (callable): The function to be applied to each task.
        tasks (list or tuple[Iterable, int]): A list of tasks or
            (tasks, total num).
        nproc (int): Process (worker) number.
        initializer (None or callable): Refer to :class:`multiprocessing.Pool`
            for details.
        initargs (None or tuple): Refer to :class:`multiprocessing.Pool` for
            details.
        chunksize (int): Refer to :class:`multiprocessing.Pool` for details.
        bar_width (int): Width of progress bar.
        skip_first (bool): Whether to skip the first sample for each worker
            when estimating fps, since the initialization step may takes
            longer.
        keep_order (bool): If True, :func:`Pool.imap` is used, otherwise
            :func:`Pool.imap_unordered` is used.

    Returns:
        list: The task results.
    """
    if isinstance(tasks, tuple):
        assert len(tasks) == 2
        assert isinstance(tasks[0], collections_abc.Iterable)
        assert isinstance(tasks[1], int)
        task_num = tasks[1]
        tasks = tasks[0]
    elif isinstance(tasks, collections_abc.Iterable):
        task_num = len(tasks)
    else:
        raise TypeError(
            '"tasks" must be an iterable object or a (iterator, int) tuple')
    pool = init_pool(nproc, initializer, initargs)
    start = not skip_first
    task_num -= nproc * chunksize * int(skip_first)
    prog_bar = ProgressBar(task_num, bar_width, start)
    results = []
    if keep_order:
        gen = pool.imap(func, tasks, chunksize)
    else:
        gen = pool.imap_unordered(func, tasks, chunksize)
    for result in gen:
        results.append(result)
        if skip_first:
            if len(results) < nproc * chunksize:
                continue
            elif len(results) == nproc * chunksize:
                prog_bar.start()
                continue
        prog_bar.update()
    sys.stdout.write('\n')
    pool.close()
    pool.join()
    return results

Track the progress of parallel task execution with a progress bar .


def imflip(img, direction='horizontal'):
    """Flip an image horizontally or vertically.

    Args:
        img (ndarray): Image to be flipped.
        direction (str): The flip direction, either "horizontal" or "vertical".

    Returns:
        ndarray: The flipped image.
    """
    assert direction in ['horizontal', 'vertical']
    if direction == 'horizontal':
        return np.flip(img, axis=1)
    else:
        return np.flip(img, axis=0)

def imflip ( img , direction = 'horizontal' ) : assert direction in [ 'horizontal' , 'vertical' ] if direction == 'horizontal' : return np . flip ( img , axis = 1 ) else : return np . flip ( img , axis = 0 )

Flip an image horizontally or vertically .


def imrotate(img,
             angle,
             center=None,
             scale=1.0,
             border_value=0,
             auto_bound=False):
    """Rotate an image.

    Args:
        img (ndarray): Image to be rotated.
        angle (float): Rotation angle in degrees, positive values mean
            clockwise rotation.
        center (tuple): Center of the rotation in the source image, by default
            it is the center of the image.
        scale (float): Isotropic scale factor.
        border_value (int): Border value.
        auto_bound (bool): Whether to adjust the image size to cover the whole
            rotated image.

    Returns:
        ndarray: The rotated image.
    """
    if center is not None and auto_bound:
        raise ValueError('`auto_bound` conflicts with `center`')
    h, w = img.shape[:2]
    if center is None:
        center = ((w - 1) * 0.5, (h - 1) * 0.5)
    assert isinstance(center, tuple)

    matrix = cv2.getRotationMatrix2D(center, -angle, scale)
    if auto_bound:
        cos = np.abs(matrix[0, 0])
        sin = np.abs(matrix[0, 1])
        new_w = h * sin + w * cos
        new_h = h * cos + w * sin
        matrix[0, 2] += (new_w - w) * 0.5
        matrix[1, 2] += (new_h - h) * 0.5
        w = int(np.round(new_w))
        h = int(np.round(new_h))
    rotated = cv2.warpAffine(img, matrix, (w, h), borderValue=border_value)
    return rotated

def
imrotate
(
img
,
angle
,
center
=
,
scale
=
1.0
,
border_value
=
0
,
auto_bound
=
False
)
:
if
center
is
not
and
auto_bound
:
raise
ValueError
(
'`auto_bound` conflicts with `center`'
)
h
,
w
=
img
.
shape
[
:
2
]
if
center
is
:
center
=
(
(
w
1
)
*
0.5
,
(
h
1
)
*
0.5
)
assert
isinstance
(
center
,
tuple
)
matrix
=
cv2
.
getRotationMatrix2D
(
center
,
angle
,
scale
)
if
auto_bound
:
cos
=
np
.
abs
(
matrix
[
0
,
0
]
)
sin
=
np
.
abs
(
matrix
[
0
,
1
]
)
new_w
=
h
*
sin
+
w
*
cos
new_h
=
h
*
cos
+
w
*
sin
matrix
[
0
,
2
]
+=
(
new_w
w
)
*
0.5
matrix
[
1
,
2
]
+=
(
new_h
h
)
*
0.5
w
=
int
(
np
.
round
(
new_w
)
)
h
=
int
(
np
.
round
(
new_h
)
)
rotated
=
cv2
.
warpAffine
(
img
,
matrix
,
(
w
,
h
)
,
borderValue
=
border_value
)
return
rotated


def bbox_clip(bboxes, img_shape):
    """Clip bboxes to fit the image shape.

    Args:
        bboxes (ndarray): Shape (..., 4*k)
        img_shape (tuple): (height, width) of the image.

    Returns:
        ndarray: Clipped bboxes.
    """
    assert bboxes.shape[-1] % 4 == 0
    clipped_bboxes = np.empty_like(bboxes, dtype=bboxes.dtype)
    clipped_bboxes[..., 0::2] = np.maximum(
        np.minimum(bboxes[..., 0::2], img_shape[1] - 1), 0)
    clipped_bboxes[..., 1::2] = np.maximum(
        np.minimum(bboxes[..., 1::2], img_shape[0] - 1), 0)
    return clipped_bboxes

def bbox_clip ( bboxes , img_shape ) : assert bboxes . shape [ - 1 ] % 4 == 0 clipped_bboxes = np . empty_like ( bboxes , dtype = bboxes . dtype ) clipped_bboxes [ ... , 0 : : 2 ] = np . maximum ( np . minimum ( bboxes [ ... , 0 : : 2 ] , img_shape [ 1 ] - 1 ) , 0 ) clipped_bboxes [ ... , 1 : : 2 ] = np . maximum ( np . minimum ( bboxes [ ... , 1 : : 2 ] , img_shape [ 0 ] - 1 ) , 0 ) return clipped_bboxes


def bbox_scaling(bboxes, scale, clip_shape=None):
    """Scaling bboxes w.r.t the box center.

    Args:
        bboxes (ndarray): Shape(..., 4).
        scale (float): Scaling factor.
        clip_shape (tuple, optional): If specified, bboxes that exceed the
            boundary will be clipped according to the given shape (h, w).

    Returns:
        ndarray: Scaled bboxes.
    """
    if float(scale) == 1.0:
        scaled_bboxes = bboxes.copy()
    else:
        w = bboxes[..., 2] - bboxes[..., 0] + 1
        h = bboxes[..., 3] - bboxes[..., 1] + 1
        dw = (w * (scale - 1)) * 0.5
        dh = (h * (scale - 1)) * 0.5
        scaled_bboxes = bboxes + np.stack((-dw, -dh, dw, dh), axis=-1)
    if clip_shape is not None:
        return bbox_clip(scaled_bboxes, clip_shape)
    else:
        return scaled_bboxes

def bbox_scaling ( bboxes , scale , clip_shape = None ) : if float ( scale ) == 1.0 : scaled_bboxes = bboxes . copy ( ) else : w = bboxes [ ... , 2 ] - bboxes [ ... , 0 ] + 1 h = bboxes [ ... , 3 ] - bboxes [ ... , 1 ] + 1 dw = ( w * ( scale - 1 ) ) * 0.5 dh = ( h * ( scale - 1 ) ) * 0.5 scaled_bboxes = bboxes + np . stack ( ( - dw , - dh , dw , dh ) , axis = - 1 ) if clip_shape is not None : return bbox_clip ( scaled_bboxes , clip_shape ) else : return scaled_bboxes

Scaling bboxes w . r . t the box center .


def imcrop(img, bboxes, scale=1.0, pad_fill=None):
    """Crop image patches.

    3 steps: scale the bboxes -> clip bboxes -> crop and pad.

    Args:
        img (ndarray): Image to be cropped.
        bboxes (ndarray): Shape (k, 4) or (4, ), location of cropped bboxes.
        scale (float, optional): Scale ratio of bboxes, the default value
            1.0 means no padding.
        pad_fill (number or list): Value to be filled for padding, None for
            no padding.

    Returns:
        list or ndarray: The cropped image patches.
    """
    chn = 1 if img.ndim == 2 else img.shape[2]
    if pad_fill is not None:
        if isinstance(pad_fill, (int, float)):
            pad_fill = [pad_fill for _ in range(chn)]
        assert len(pad_fill) == chn

    _bboxes = bboxes[None, ...] if bboxes.ndim == 1 else bboxes
    scaled_bboxes = bbox_scaling(_bboxes, scale).astype(np.int32)
    clipped_bbox = bbox_clip(scaled_bboxes, img.shape)

    patches = []
    for i in range(clipped_bbox.shape[0]):
        x1, y1, x2, y2 = tuple(clipped_bbox[i, :])
        if pad_fill is None:
            patch = img[y1:y2 + 1, x1:x2 + 1, ...]
        else:
            _x1, _y1, _x2, _y2 = tuple(scaled_bboxes[i, :])
            if chn == 2:
                patch_shape = (_y2 - _y1 + 1, _x2 - _x1 + 1)
            else:
                patch_shape = (_y2 - _y1 + 1, _x2 - _x1 + 1, chn)
            patch = np.array(
                pad_fill, dtype=img.dtype) * np.ones(
                    patch_shape, dtype=img.dtype)
            x_start = 0 if _x1 >= 0 else -_x1
            y_start = 0 if _y1 >= 0 else -_y1
            w = x2 - x1 + 1
            h = y2 - y1 + 1
            patch[y_start:y_start + h, x_start:x_start +
                  w, ...] = img[y1:y1 + h, x1:x1 + w, ...]
        patches.append(patch)

    if bboxes.ndim == 1:
        return patches[0]
    else:
        return patches

def imcrop ( img , bboxes , scale = 1.0 , pad_fill = None ) : chn = 1 if img . ndim == 2 else img . shape [ 2 ] if pad_fill is not None : if isinstance ( pad_fill , ( int , float ) ) : pad_fill = [ pad_fill for _ in range ( chn ) ] assert len ( pad_fill ) == chn _bboxes = bboxes [ None , ... ] if bboxes . ndim == 1 else bboxes scaled_bboxes = bbox_scaling ( _bboxes , scale ) . astype ( np . int32 ) clipped_bbox = bbox_clip ( scaled_bboxes , img . shape ) patches = [ ] for i in range ( clipped_bbox . shape [ 0 ] ) : x1 , y1 , x2 , y2 = tuple ( clipped_bbox [ i , : ] ) if pad_fill is None : patch = img [ y1 : y2 + 1 , x1 : x2 + 1 , ... ] else : _x1 , _y1 , _x2 , _y2 = tuple ( scaled_bboxes [ i , : ] ) if chn == 2 : patch_shape = ( _y2 - _y1 + 1 , _x2 - _x1 + 1 ) else : patch_shape = ( _y2 - _y1 + 1 , _x2 - _x1 + 1 , chn ) patch = np . array ( pad_fill , dtype = img . dtype ) * np . ones ( patch_shape , dtype = img . dtype ) x_start = 0 if _x1 >= 0 else - _x1 y_start = 0 if _y1 >= 0 else - _y1 w = x2 - x1 + 1 h = y2 - y1 + 1 patch [ y_start : y_start + h , x_start : x_start + w , ... ] = img [ y1 : y1 + h , x1 : x1 + w , ... ] patches . append ( patch ) if bboxes . ndim == 1 : return patches [ 0 ] else : return patches


def impad(img, shape, pad_val=0):
    """Pad an image to a certain shape.

    Args:
        img (ndarray): Image to be padded.
        shape (tuple): Expected padding shape.
        pad_val (number or sequence): Values to be filled in padding areas.

    Returns:
        ndarray: The padded image.
    """
    if not isinstance(pad_val, (int, float)):
        assert len(pad_val) == img.shape[-1]
    if len(shape) < len(img.shape):
        shape = shape + (img.shape[-1], )
    assert len(shape) == len(img.shape)
    for i in range(len(shape) - 1):
        assert shape[i] >= img.shape[i]
    pad = np.empty(shape, dtype=img.dtype)
    pad[...] = pad_val
    pad[:img.shape[0], :img.shape[1], ...] = img
    return pad

def impad ( img , shape , pad_val = 0 ) : if not isinstance ( pad_val , ( int , float ) ) : assert len ( pad_val ) == img . shape [ - 1 ] if len ( shape ) < len ( img . shape ) : shape = shape + ( img . shape [ - 1 ] , ) assert len ( shape ) == len ( img . shape ) for i in range ( len ( shape ) - 1 ) : assert shape [ i ] >= img . shape [ i ] pad = np . empty ( shape , dtype = img . dtype ) pad [ ... ] = pad_val pad [ : img . shape [ 0 ] , : img . shape [ 1 ] , ... ] = img return pad


def impad_to_multiple(img, divisor, pad_val=0):
    """Pad an image to ensure each edge to be multiple to some number.

    Args:
        img (ndarray): Image to be padded.
        divisor (int): Padded image edges will be multiple to divisor.
        pad_val (number or sequence): Same as :func:`impad`.

    Returns:
        ndarray: The padded image.
    """
    pad_h = int(np.ceil(img.shape[0] / divisor)) * divisor
    pad_w = int(np.ceil(img.shape[1] / divisor)) * divisor
    return impad(img, (pad_h, pad_w), pad_val)

def impad_to_multiple ( img , divisor , pad_val = 0 ) : pad_h = int ( np . ceil ( img . shape [ 0 ] / divisor ) ) * divisor pad_w = int ( np . ceil ( img . shape [ 1 ] / divisor ) ) * divisor return impad ( img , ( pad_h , pad_w ) , pad_val )

Pad an image to ensure each edge to be multiple to some number .


def _scale_size(size, scale):
    """Rescale a size by a ratio.

    Args:
        size (tuple): w, h.
        scale (float): Scaling factor.

    Returns:
        tuple[int]: scaled size.
    """
    w, h = size
    return int(w * float(scale) + 0.5), int(h * float(scale) + 0.5)

def _scale_size ( size , scale ) : w , h = size return int ( w * float ( scale ) + 0.5 ) , int ( h * float ( scale ) + 0.5 )


def imresize(img, size, return_scale=False, interpolation='bilinear'):
    """Resize image to a given size.

    Args:
        img (ndarray): The input image.
        size (tuple): Target (w, h).
        return_scale (bool): Whether to return `w_scale` and `h_scale`.
        interpolation (str): Interpolation method, accepted values are
            "nearest", "bilinear", "bicubic", "area", "lanczos".

    Returns:
        tuple or ndarray: (`resized_img`, `w_scale`, `h_scale`) or
            `resized_img`.
    """
    h, w = img.shape[:2]
    resized_img = cv2.resize(
        img, size, interpolation=interp_codes[interpolation])
    if not return_scale:
        return resized_img
    else:
        w_scale = size[0] / w
        h_scale = size[1] / h
        return resized_img, w_scale, h_scale

def imresize ( img , size , return_scale = False , interpolation = 'bilinear' ) : h , w = img . shape [ : 2 ] resized_img = cv2 . resize ( img , size , interpolation = interp_codes [ interpolation ] ) if not return_scale : return resized_img else : w_scale = size [ 0 ] / w h_scale = size [ 1 ] / h return resized_img , w_scale , h_scale


def imresize_like(img, dst_img, return_scale=False, interpolation='bilinear'):
    """Resize image to the same size of a given image.

    Args:
        img (ndarray): The input image.
        dst_img (ndarray): The target image.
        return_scale (bool): Whether to return `w_scale` and `h_scale`.
        interpolation (str): Same as :func:`resize`.

    Returns:
        tuple or ndarray: (`resized_img`, `w_scale`, `h_scale`) or
            `resized_img`.
    """
    h, w = dst_img.shape[:2]
    return imresize(img, (w, h), return_scale, interpolation)

def imresize_like ( img , dst_img , return_scale = False , interpolation = 'bilinear' ) : h , w = dst_img . shape [ : 2 ] return imresize ( img , ( w , h ) , return_scale , interpolation )

Resize image to the same size of a given image .


def imrescale(img, scale, return_scale=False, interpolation='bilinear'):
    """Resize image while keeping the aspect ratio.

    Args:
        img (ndarray): The input image.
        scale (float or tuple[int]): The scaling factor or maximum size.
            If it is a float number, then the image will be rescaled by this
            factor, else if it is a tuple of 2 integers, then the image will
            be rescaled as large as possible within the scale.
        return_scale (bool): Whether to return the scaling factor besides the
            rescaled image.
        interpolation (str): Same as :func:`resize`.

    Returns:
        ndarray: The rescaled image.
    """
    h, w = img.shape[:2]
    if isinstance(scale, (float, int)):
        if scale <= 0:
            raise ValueError(
                'Invalid scale {}, must be positive.'.format(scale))
        scale_factor = scale
    elif isinstance(scale, tuple):
        max_long_edge = max(scale)
        max_short_edge = min(scale)
        scale_factor = min(max_long_edge / max(h, w),
                           max_short_edge / min(h, w))
    else:
        raise TypeError(
            'Scale must be a number or tuple of int, but got {}'.format(
                type(scale)))
    new_size = _scale_size((w, h), scale_factor)
    rescaled_img = imresize(img, new_size, interpolation=interpolation)
    if return_scale:
        return rescaled_img, scale_factor
    else:
        return rescaled_img

Resize image while keeping the aspect ratio .


def _register_handler(handler, file_formats):
    """Register a handler for some file extensions.

    Args:
        handler (:obj:`BaseFileHandler`): Handler to be registered.
        file_formats (str or list[str]): File formats to be handled by this
            handler.
    """
    if not isinstance(handler, BaseFileHandler):
        raise TypeError(
            'handler must be a child of BaseFileHandler, not {}'.format(
                type(handler)))
    if isinstance(file_formats, str):
        file_formats = [file_formats]
    if not is_list_of(file_formats, str):
        raise TypeError('file_formats must be a str or a list of str')
    for ext in file_formats:
        file_handlers[ext] = handler

Register a handler for some file extensions .


def get_priority(priority):
    """Get priority value.

    Args:
        priority (int or str or :obj:`Priority`): Priority.

    Returns:
        int: The priority value.
    """
    if isinstance(priority, int):
        if priority < 0 or priority > 100:
            raise ValueError('priority must be between 0 and 100')
        return priority
    elif isinstance(priority, Priority):
        return priority.value
    elif isinstance(priority, str):
        return Priority[priority.upper()].value
    else:
        raise TypeError('priority must be an integer or Priority enum value')


def dequantize(arr, min_val, max_val, levels, dtype=np.float64):
    """Dequantize an array.

    Args:
        arr (ndarray): Input array.
        min_val (scalar): Minimum value to be clipped.
        max_val (scalar): Maximum value to be clipped.
        levels (int): Quantization levels.
        dtype (np.type): The type of the dequantized array.

    Returns:
        tuple: Dequantized array.
    """
    if not (isinstance(levels, int) and levels > 1):
        raise ValueError(
            'levels must be a positive integer, but got {}'.format(levels))
    if min_val >= max_val:
        raise ValueError(
            'min_val ({}) must be smaller than max_val ({})'.format(
                min_val, max_val))

    dequantized_arr = (arr + 0.5).astype(dtype) * (
        max_val - min_val) / levels + min_val

    return dequantized_arr


def imshow(img, win_name='', wait_time=0):
    """Show an image.

    Args:
        img (str or ndarray): The image to be displayed.
        win_name (str): The window name.
        wait_time (int): Value of waitKey param.
    """
    cv2.imshow(win_name, imread(img))
    cv2.waitKey(wait_time)

def imshow ( img , win_name = '' , wait_time = 0 ) : cv2 . imshow ( win_name , imread ( img ) ) cv2 . waitKey ( wait_time )


def imshow_bboxes(img,
                  bboxes,
                  colors='green',
                  top_k=-1,
                  thickness=1,
                  show=True,
                  win_name='',
                  wait_time=0,
                  out_file=None):
    """Draw bboxes on an image.

    Args:
        img (str or ndarray): The image to be displayed.
        bboxes (list or ndarray): A list of ndarray of shape (k, 4).
        colors (list[str or tuple or Color]): A list of colors.
        top_k (int): Plot the first k bboxes only if set positive.
        thickness (int): Thickness of lines.
        show (bool): Whether to show the image.
        win_name (str): The window name.
        wait_time (int): Value of waitKey param.
        out_file (str, optional): The filename to write the image.
    """
    img = imread(img)

    if isinstance(bboxes, np.ndarray):
        bboxes = [bboxes]
    if not isinstance(colors, list):
        colors = [colors for _ in range(len(bboxes))]
    colors = [color_val(c) for c in colors]
    assert len(bboxes) == len(colors)

    for i, _bboxes in enumerate(bboxes):
        _bboxes = _bboxes.astype(np.int32)
        if top_k <= 0:
            _top_k = _bboxes.shape[0]
        else:
            _top_k = min(top_k, _bboxes.shape[0])
        for j in range(_top_k):
            left_top = (_bboxes[j, 0], _bboxes[j, 1])
            right_bottom = (_bboxes[j, 2], _bboxes[j, 3])
            cv2.rectangle(
                img, left_top, right_bottom, colors[i], thickness=thickness)

    if show:
        imshow(img, win_name, wait_time)
    if out_file is not None:
        imwrite(img, out_file)

def imshow_bboxes ( img , bboxes , colors = 'green' , top_k = - 1 , thickness = 1 , show = True , win_name = '' , wait_time = 0 , out_file = None ) : img = imread ( img ) if isinstance ( bboxes , np . ndarray ) : bboxes = [ bboxes ] if not isinstance ( colors , list ) : colors = [ colors for _ in range ( len ( bboxes ) ) ] colors = [ color_val ( c ) for c in colors ] assert len ( bboxes ) == len ( colors ) for i , _bboxes in enumerate ( bboxes ) : _bboxes = _bboxes . astype ( np . int32 ) if top_k <= 0 : _top_k = _bboxes . shape [ 0 ] else : _top_k = min ( top_k , _bboxes . shape [ 0 ] ) for j in range ( _top_k ) : left_top = ( _bboxes [ j , 0 ] , _bboxes [ j , 1 ] ) right_bottom = ( _bboxes [ j , 2 ] , _bboxes [ j , 3 ] ) cv2 . rectangle ( img , left_top , right_bottom , colors [ i ] , thickness = thickness ) if show : imshow ( img , win_name , wait_time ) if out_file is not None : imwrite ( img , out_file )


def flowread(flow_or_path, quantize=False, concat_axis=0, *args, **kwargs):
    """Read an optical flow map.

    Args:
        flow_or_path (ndarray or str): A flow map or filepath.
        quantize (bool): whether to read quantized pair, if set to True,
            remaining args will be passed to :func:`dequantize_flow`.
        concat_axis (int): The axis that dx and dy are concatenated,
            can be either 0 or 1. Ignored if quantize is False.

    Returns:
        ndarray: Optical flow represented as a (h, w, 2) numpy array
    """
    if isinstance(flow_or_path, np.ndarray):
        if (flow_or_path.ndim != 3) or (flow_or_path.shape[-1] != 2):
            raise ValueError('Invalid flow with shape {}'.format(
                flow_or_path.shape))
        return flow_or_path
    elif not is_str(flow_or_path):
        raise TypeError(
            '"flow_or_path" must be a filename or numpy array, not {}'.format(
                type(flow_or_path)))

    if not quantize:
        with open(flow_or_path, 'rb') as f:
            try:
                header = f.read(4).decode('utf-8')
            except Exception:
                raise IOError('Invalid flow file: {}'.format(flow_or_path))
            else:
                if header != 'PIEH':
                    raise IOError(
                        'Invalid flow file: {}, header does not contain PIEH'.
                        format(flow_or_path))

            w = np.fromfile(f, np.int32, 1).squeeze()
            h = np.fromfile(f, np.int32, 1).squeeze()
            flow = np.fromfile(f, np.float32, w * h * 2).reshape((h, w, 2))
    else:
        assert concat_axis in [0, 1]
        cat_flow = imread(flow_or_path, flag='unchanged')
        if cat_flow.ndim != 2:
            raise IOError(
                '{} is not a valid quantized flow file, its dimension is {}.'.
                format(flow_or_path, cat_flow.ndim))
        assert cat_flow.shape[concat_axis] % 2 == 0
        dx, dy = np.split(cat_flow, 2, axis=concat_axis)
        flow = dequantize_flow(dx, dy, *args, **kwargs)

    return flow.astype(np.float32)


def flowwrite(flow, filename, quantize=False, concat_axis=0, *args, **kwargs):
    """Write optical flow to file.

    If the flow is not quantized, it will be saved as a .flo file losslessly,
    otherwise a jpeg image which is lossy but of much smaller size. (dx and dy
    will be concatenated horizontally into a single image if quantize is True.)

    Args:
        flow (ndarray): (h, w, 2) array of optical flow.
        filename (str): Output filepath.
        quantize (bool): Whether to quantize the flow and save it to 2 jpeg
            images. If set to True, remaining args will be passed to
            :func:`quantize_flow`.
        concat_axis (int): The axis that dx and dy are concatenated,
            can be either 0 or 1. Ignored if quantize is False.
    """
    if not quantize:
        with open(filename, 'wb') as f:
            f.write('PIEH'.encode('utf-8'))
            np.array([flow.shape[1], flow.shape[0]], dtype=np.int32).tofile(f)
            flow = flow.astype(np.float32)
            flow.tofile(f)
            f.flush()
    else:
        assert concat_axis in [0, 1]
        dx, dy = quantize_flow(flow, *args, **kwargs)
        dxdy = np.concatenate((dx, dy), axis=concat_axis)
        imwrite(dxdy, filename)

def flowwrite ( flow , filename , quantize = False , concat_axis = 0 , * args , * * kwargs ) : if not quantize : with open ( filename , 'wb' ) as f : f . write ( 'PIEH' . encode ( 'utf-8' ) ) np . array ( [ flow . shape [ 1 ] , flow . shape [ 0 ] ] , dtype = np . int32 ) . tofile ( f ) flow = flow . astype ( np . float32 ) flow . tofile ( f ) f . flush ( ) else : assert concat_axis in [ 0 , 1 ] dx , dy = quantize_flow ( flow , * args , * * kwargs ) dxdy = np . concatenate ( ( dx , dy ) , axis = concat_axis ) imwrite ( dxdy , filename )


def dequantize_flow(dx, dy, max_val=0.02, denorm=True):
    """Recover from quantized flow.

    Args:
        dx (ndarray): Quantized dx.
        dy (ndarray): Quantized dy.
        max_val (float): Maximum value used when quantizing.
        denorm (bool): Whether to multiply flow values with width/height.

    Returns:
        ndarray: Dequantized flow.
    """
    assert dx.shape == dy.shape
    assert dx.ndim == 2 or (dx.ndim == 3 and dx.shape[-1] == 1)

    dx, dy = [dequantize(d, -max_val, max_val, 255) for d in [dx, dy]]

    if denorm:
        dx *= dx.shape[1]
        dy *= dx.shape[0]
    flow = np.dstack((dx, dy))
    return flow

def dequantize_flow ( dx , dy , max_val = 0.02 , denorm = True ) : assert dx . shape == dy . shape assert dx . ndim == 2 or ( dx . ndim == 3 and dx . shape [ - 1 ] == 1 ) dx , dy = [ dequantize ( d , - max_val , max_val , 255 ) for d in [ dx , dy ] ] if denorm : dx *= dx . shape [ 1 ] dy *= dx . shape [ 0 ] flow = np . dstack ( ( dx , dy ) ) return flow


def load_state_dict(module, state_dict, strict=False, logger=None):
    """Load state_dict to a module.

    This method is modified from :meth:`torch.nn.Module.load_state_dict`.
    Default value for ``strict`` is set to ``False`` and the message for
    param mismatch will be shown even if strict is False.

    Args:
        module (Module): Module that receives the state_dict.
        state_dict (OrderedDict): Weights.
        strict (bool): whether to strictly enforce that the keys
            in :attr:`state_dict` match the keys returned by this module's
            :meth:`~torch.nn.Module.state_dict` function. Default: ``False``.
        logger (:obj:`logging.Logger`, optional): Logger to log the error
            message. If not specified, print function will be used.
    """
    unexpected_keys = []
    own_state = module.state_dict()
    for name, param in state_dict.items():
        if name not in own_state:
            unexpected_keys.append(name)
            continue
        if isinstance(param, torch.nn.Parameter):
            # backwards compatibility for serialized parameters
            param = param.data

        try:
            own_state[name].copy_(param)
        except Exception:
            raise RuntimeError('While copying the parameter named {}, '
                               'whose dimensions in the model are {} and '
                               'whose dimensions in the checkpoint are {}.'
                               .format(name, own_state[name].size(),
                                       param.size()))
    missing_keys = set(own_state.keys()) - set(state_dict.keys())

    err_msg = []
    if unexpected_keys:
        err_msg.append('unexpected key in source state_dict: {}\n'.format(
            ', '.join(unexpected_keys)))
    if missing_keys:
        err_msg.append('missing keys in source state_dict: {}\n'.format(
            ', '.join(missing_keys)))
    err_msg = '\n'.join(err_msg)
    if err_msg:
        if strict:
            raise RuntimeError(err_msg)
        elif logger is not None:
            logger.warn(err_msg)
        else:
            print(err_msg)


def load_checkpoint(model,
                    filename,
                    map_location=None,
                    strict=False,
                    logger=None):
    """Load checkpoint from a file or URI.

    Args:
        model (Module): Module to load checkpoint.
        filename (str): Either a filepath or URL or modelzoo://xxxxxxx.
        map_location (str): Same as :func:`torch.load`.
        strict (bool): Whether to allow different params for the model and
            checkpoint.
        logger (:mod:`logging.Logger` or None): The logger for error message.

    Returns:
        dict or OrderedDict: The loaded checkpoint.
    """
    # load checkpoint from modelzoo or file or url
    if filename.startswith('modelzoo://'):
        import torchvision
        model_urls = dict()
        for _, name, ispkg in pkgutil.walk_packages(
                torchvision.models.__path__):
            if not ispkg:
                _zoo = import_module('torchvision.models.{}'.format(name))
                _urls = getattr(_zoo, 'model_urls')
                model_urls.update(_urls)
        model_name = filename[11:]
        checkpoint = model_zoo.load_url(model_urls[model_name])
    elif filename.startswith('open-mmlab://'):
        model_name = filename[13:]
        checkpoint = model_zoo.load_url(open_mmlab_model_urls[model_name])
    elif filename.startswith(('http://', 'https://')):
        checkpoint = model_zoo.load_url(filename)
    else:
        if not osp.isfile(filename):
            raise IOError('{} is not a checkpoint file'.format(filename))
        checkpoint = torch.load(filename, map_location=map_location)
    # get state_dict from checkpoint
    if isinstance(checkpoint, OrderedDict):
        state_dict = checkpoint
    elif isinstance(checkpoint, dict) and 'state_dict' in checkpoint:
        state_dict = checkpoint['state_dict']
    else:
        raise RuntimeError(
            'No state_dict found in checkpoint file {}'.format(filename))
    # strip prefix of state_dict
    if list(state_dict.keys())[0].startswith('module.'):
        state_dict = {k[7:]: v for k, v in checkpoint['state_dict'].items()}
    # load state_dict
    if hasattr(model, 'module'):
        load_state_dict(model.module, state_dict, strict, logger)
    else:
        load_state_dict(model, state_dict, strict, logger)
    return checkpoint


def weights_to_cpu(state_dict):
    """Copy a model state_dict to cpu.

    Args:
        state_dict (OrderedDict): Model weights on GPU.

    Returns:
        OrderedDict: Model weights on GPU.
    """
    state_dict_cpu = OrderedDict()
    for key, val in state_dict.items():
        state_dict_cpu[key] = val.cpu()
    return state_dict_cpu

def weights_to_cpu ( state_dict ) : state_dict_cpu = OrderedDict ( ) for key , val in state_dict . items ( ) : state_dict_cpu [ key ] = val . cpu ( ) return state_dict_cpu


def save_checkpoint(model, filename, optimizer=None, meta=None):
    """Save checkpoint to file.

    The checkpoint will have 3 fields: ``meta``, ``state_dict`` and
    ``optimizer``. By default ``meta`` will contain version and time info.

    Args:
        model (Module): Module whose params are to be saved.
        filename (str): Checkpoint filename.
        optimizer (:obj:`Optimizer`, optional): Optimizer to be saved.
        meta (dict, optional): Metadata to be saved in checkpoint.
    """
    if meta is None:
        meta = {}
    elif not isinstance(meta, dict):
        raise TypeError('meta must be a dict or None, but got {}'.format(
            type(meta)))
    meta.update(mmcv_version=mmcv.__version__, time=time.asctime())

    mmcv.mkdir_or_exist(osp.dirname(filename))
    if hasattr(model, 'module'):
        model = model.module

    checkpoint = {
        'meta': meta,
        'state_dict': weights_to_cpu(model.state_dict())
    }
    if optimizer is not None:
        checkpoint['optimizer'] = optimizer.state_dict()

    torch.save(checkpoint, filename)


def init_optimizer(self, optimizer):
        """Init the optimizer.

        Args:
            optimizer (dict or :obj:`~torch.optim.Optimizer`): Either an
                optimizer object or a dict used for constructing the optimizer.

        Returns:
            :obj:`~torch.optim.Optimizer`: An optimizer object.

        Examples:
            >>> optimizer = dict(type='SGD', lr=0.01, momentum=0.9)
            >>> type(runner.init_optimizer(optimizer))
            <class 'torch.optim.sgd.SGD'>
        """
        if isinstance(optimizer, dict):
            optimizer = obj_from_dict(
                optimizer, torch.optim, dict(params=self.model.parameters()))
        elif not isinstance(optimizer, torch.optim.Optimizer):
            raise TypeError(
                'optimizer must be either an Optimizer object or a dict, '
                'but got {}'.format(type(optimizer)))
        return optimizer


def init_logger(self, log_dir=None, level=logging.INFO):
        """Init the logger.

        Args:
            log_dir(str, optional): Log file directory. If not specified, no
                log file will be used.
            level (int or str): See the built-in python logging module.

        Returns:
            :obj:`~logging.Logger`: Python logger.
        """
        logging.basicConfig(
            format='%(asctime)s - %(levelname)s - %(message)s', level=level)
        logger = logging.getLogger(__name__)
        if log_dir and self.rank == 0:
            filename = '{}.log'.format(self.timestamp)
            log_file = osp.join(log_dir, filename)
            self._add_file_handler(logger, log_file, level=level)
        return logger


def current_lr(self):
        """Get current learning rates.

        Returns:
            list: Current learning rate of all param groups.
        """
        if self.optimizer is None:
            raise RuntimeError(
                'lr is not applicable because optimizer does not exist.')
        return [group['lr'] for group in self.optimizer.param_groups]


def register_hook(self, hook, priority='NORMAL'):
        """Register a hook into the hook list.

        Args:
            hook (:obj:`Hook`): The hook to be registered.
            priority (int or str or :obj:`Priority`): Hook priority.
                Lower value means higher priority.
        """
        assert isinstance(hook, Hook)
        if hasattr(hook, 'priority'):
            raise ValueError('"priority" is a reserved attribute for hooks')
        priority = get_priority(priority)
        hook.priority = priority
        # insert the hook to a sorted list
        inserted = False
        for i in range(len(self._hooks) - 1, -1, -1):
            if priority >= self._hooks[i].priority:
                self._hooks.insert(i + 1, hook)
                inserted = True
                break
        if not inserted:
            self._hooks.insert(0, hook)


def run(self, data_loaders, workflow, max_epochs, **kwargs):
        """Start running.

        Args:
            data_loaders (list[:obj:`DataLoader`]): Dataloaders for training
                and validation.
            workflow (list[tuple]): A list of (phase, epochs) to specify the
                running order and epochs. E.g, [('train', 2), ('val', 1)] means
                running 2 epochs for training and 1 epoch for validation,
                iteratively.
            max_epochs (int): Total training epochs.
        """
        assert isinstance(data_loaders, list)
        assert mmcv.is_list_of(workflow, tuple)
        assert len(data_loaders) == len(workflow)

        self._max_epochs = max_epochs
        work_dir = self.work_dir if self.work_dir is not None else 'NONE'
        self.logger.info('Start running, host: %s, work_dir: %s',
                         get_host_info(), work_dir)
        self.logger.info('workflow: %s, max: %d epochs', workflow, max_epochs)
        self.call_hook('before_run')

        while self.epoch < max_epochs:
            for i, flow in enumerate(workflow):
                mode, epochs = flow
                if isinstance(mode, str):  # self.train()
                    if not hasattr(self, mode):
                        raise ValueError(
                            'runner has no method named "{}" to run an epoch'.
                            format(mode))
                    epoch_runner = getattr(self, mode)
                elif callable(mode):  # custom train()
                    epoch_runner = mode
                else:
                    raise TypeError('mode in workflow must be a str or '
                                    'callable function, not {}'.format(
                                        type(mode)))
                for _ in range(epochs):
                    if mode == 'train' and self.epoch >= max_epochs:
                        return
                    epoch_runner(data_loaders[i], **kwargs)

        time.sleep(1)  # wait for some hooks like loggers to finish
        self.call_hook('after_run')


def register_training_hooks(self,
                                lr_config,
                                optimizer_config=None,
                                checkpoint_config=None,
                                log_config=None):
        """Register default hooks for training.

        Default hooks include:

        - LrUpdaterHook
        - OptimizerStepperHook
        - CheckpointSaverHook
        - IterTimerHook
        - LoggerHook(s)
        """
        if optimizer_config is None:
            optimizer_config = {}
        if checkpoint_config is None:
            checkpoint_config = {}
        self.register_lr_hooks(lr_config)
        self.register_hook(self.build_hook(optimizer_config, OptimizerHook))
        self.register_hook(self.build_hook(checkpoint_config, CheckpointHook))
        self.register_hook(IterTimerHook())
        if log_config is not None:
            self.register_logger_hooks(log_config)

def register_training_hooks ( self , lr_config , optimizer_config = None , checkpoint_config = None , log_config = None ) : if optimizer_config is None : optimizer_config = { } if checkpoint_config is None : checkpoint_config = { } self . register_lr_hooks ( lr_config ) self . register_hook ( self . build_hook ( optimizer_config , OptimizerHook ) ) self . register_hook ( self . build_hook ( checkpoint_config , CheckpointHook ) ) self . register_hook ( IterTimerHook ( ) ) if log_config is not None : self . register_logger_hooks ( log_config )


def convert_video(in_file, out_file, print_cmd=False, pre_options='',
                  **kwargs):
    """Convert a video with ffmpeg.

    This provides a general api to ffmpeg, the executed command is::

        `ffmpeg -y <pre_options> -i <in_file> <options> <out_file>`

    Options(kwargs) are mapped to ffmpeg commands with the following rules:

    - key=val: "-key val"
    - key=True: "-key"
    - key=False: ""

    Args:
        in_file (str): Input video filename.
        out_file (str): Output video filename.
        pre_options (str): Options appears before "-i <in_file>".
        print_cmd (bool): Whether to print the final ffmpeg command.
    """
    options = []
    for k, v in kwargs.items():
        if isinstance(v, bool):
            if v:
                options.append('-{}'.format(k))
        elif k == 'log_level':
            assert v in [
                'quiet', 'panic', 'fatal', 'error', 'warning', 'info',
                'verbose', 'debug', 'trace'
            ]
            options.append('-loglevel {}'.format(v))
        else:
            options.append('-{} {}'.format(k, v))
    cmd = 'ffmpeg -y {} -i {} {} {}'.format(pre_options, in_file,
                                            ' '.join(options), out_file)
    if print_cmd:
        print(cmd)
    subprocess.call(cmd, shell=True)

def
convert_video
(
in_file
,
out_file
,
print_cmd
=
False
,
pre_options
=
''
,
*
*
kwargs
)
:
options
=
[
]
for
k
,
v
in
kwargs
.
items
(
)
:
if
isinstance
(
v
,
bool
)
:
if
v
:
options
.
append
(
'-{}'
.
format
(
k
)
)
elif
k
==
'log_level'
:
assert
v
in
[
'quiet'
,
'panic'
,
'fatal'
,
'error'
,
'warning'
,
'info'
,
'verbose'
,
'debug'
,
'trace'
]
options
.
append
(
'-loglevel {}'
.
format
(
v
)
)
else
:
options
.
append
(
'-{} {}'
.
format
(
k
,
v
)
)
cmd
=
'ffmpeg -y {} -i {} {} {}'
.
format
(
pre_options
,
in_file
,
' '
.
join
(
options
)
,
out_file
)
if
print_cmd
:
print
(
cmd
)
subprocess
.
call
(
cmd
,
shell
=
True
)


def resize_video(in_file,
                 out_file,
                 size=None,
                 ratio=None,
                 keep_ar=False,
                 log_level='info',
                 print_cmd=False,
                 **kwargs):
    """Resize a video.

    Args:
        in_file (str): Input video filename.
        out_file (str): Output video filename.
        size (tuple): Expected size (w, h), eg, (320, 240) or (320, -1).
        ratio (tuple or float): Expected resize ratio, (2, 0.5) means
            (w*2, h*0.5).
        keep_ar (bool): Whether to keep original aspect ratio.
        log_level (str): Logging level of ffmpeg.
        print_cmd (bool): Whether to print the final ffmpeg command.
    """
    if size is None and ratio is None:
        raise ValueError('expected size or ratio must be specified')
    elif size is not None and ratio is not None:
        raise ValueError('size and ratio cannot be specified at the same time')
    options = {'log_level': log_level}
    if size:
        if not keep_ar:
            options['vf'] = 'scale={}:{}'.format(size[0], size[1])
        else:
            options['vf'] = ('scale=w={}:h={}:force_original_aspect_ratio'
                             '=decrease'.format(size[0], size[1]))
    else:
        if not isinstance(ratio, tuple):
            ratio = (ratio, ratio)
        options['vf'] = 'scale="trunc(iw*{}):trunc(ih*{})"'.format(
            ratio[0], ratio[1])
    convert_video(in_file, out_file, print_cmd, **options)


def cut_video(in_file,
              out_file,
              start=None,
              end=None,
              vcodec=None,
              acodec=None,
              log_level='info',
              print_cmd=False,
              **kwargs):
    """Cut a clip from a video.

    Args:
        in_file (str): Input video filename.
        out_file (str): Output video filename.
        start (None or float): Start time (in seconds).
        end (None or float): End time (in seconds).
        vcodec (None or str): Output video codec, None for unchanged.
        acodec (None or str): Output audio codec, None for unchanged.
        log_level (str): Logging level of ffmpeg.
        print_cmd (bool): Whether to print the final ffmpeg command.
    """
    options = {'log_level': log_level}
    if vcodec is None:
        options['vcodec'] = 'copy'
    if acodec is None:
        options['acodec'] = 'copy'
    if start:
        options['ss'] = start
    else:
        start = 0
    if end:
        options['t'] = end - start
    convert_video(in_file, out_file, print_cmd, **options)

def cut_video ( in_file , out_file , start = None , end = None , vcodec = None , acodec = None , log_level = 'info' , print_cmd = False , * * kwargs ) : options = { 'log_level' : log_level } if vcodec is None : options [ 'vcodec' ] = 'copy' if acodec is None : options [ 'acodec' ] = 'copy' if start : options [ 'ss' ] = start else : start = 0 if end : options [ 't' ] = end - start convert_video ( in_file , out_file , print_cmd , * * options )


def concat_video(video_list,
                 out_file,
                 vcodec=None,
                 acodec=None,
                 log_level='info',
                 print_cmd=False,
                 **kwargs):
    """Concatenate multiple videos into a single one.

    Args:
        video_list (list): A list of video filenames
        out_file (str): Output video filename
        vcodec (None or str): Output video codec, None for unchanged
        acodec (None or str): Output audio codec, None for unchanged
        log_level (str): Logging level of ffmpeg.
        print_cmd (bool): Whether to print the final ffmpeg command.
    """
    _, tmp_filename = tempfile.mkstemp(suffix='.txt', text=True)
    with open(tmp_filename, 'w') as f:
        for filename in video_list:
            f.write('file {}\n'.format(osp.abspath(filename)))
    options = {'log_level': log_level}
    if vcodec is None:
        options['vcodec'] = 'copy'
    if acodec is None:
        options['acodec'] = 'copy'
    convert_video(
        tmp_filename,
        out_file,
        print_cmd,
        pre_options='-f concat -safe 0',
        **options)
    os.remove(tmp_filename)

def
concat_video
(
video_list
,
out_file
,
vcodec
=
,
acodec
=
,
log_level
=
'info'
,
print_cmd
=
False
,
*
*
kwargs
)
:
_
,
tmp_filename
=
tempfile
.
mkstemp
(
suffix
=
'.txt'
,
text
=
True
)
with
open
(
tmp_filename
,
'w'
)
as
f
:
for
filename
in
video_list
:
f
.
write
(
'file {}\n'
.
format
(
osp
.
abspath
(
filename
)
)
)
options
=
{
'log_level'
:
log_level
}
if
vcodec
is
:
options
[
'vcodec'
]
=
'copy'
if
acodec
is
:
options
[
'acodec'
]
=
'copy'
convert_video
(
tmp_filename
,
out_file
,
print_cmd
,
pre_options
=
'-f concat -safe 0'
,
*
*
options
)
os
.
remove
(
tmp_filename
)

Concatenate multiple videos into a single one .


def list_from_file(filename, prefix='', offset=0, max_num=0):
    """Load a text file and parse the content as a list of strings.

    Args:
        filename (str): Filename.
        prefix (str): The prefix to be inserted to the begining of each item.
        offset (int): The offset of lines.
        max_num (int): The maximum number of lines to be read,
            zeros and negatives mean no limitation.

    Returns:
        list[str]: A list of strings.
    """
    cnt = 0
    item_list = []
    with open(filename, 'r') as f:
        for _ in range(offset):
            f.readline()
        for line in f:
            if max_num > 0 and cnt >= max_num:
                break
            item_list.append(prefix + line.rstrip('\n'))
            cnt += 1
    return item_list

def list_from_file ( filename , prefix = '' , offset = 0 , max_num = 0 ) : cnt = 0 item_list = [ ] with open ( filename , 'r' ) as f : for _ in range ( offset ) : f . readline ( ) for line in f : if max_num > 0 and cnt >= max_num : break item_list . append ( prefix + line . rstrip ( '\n' ) ) cnt += 1 return item_list

Load a text file and parse the content as a list of strings .


def dict_from_file(filename, key_type=str):
    """Load a text file and parse the content as a dict.

    Each line of the text file will be two or more columns splited by
    whitespaces or tabs. The first column will be parsed as dict keys, and
    the following columns will be parsed as dict values.

    Args:
        filename(str): Filename.
        key_type(type): Type of the dict's keys. str is user by default and
            type conversion will be performed if specified.

    Returns:
        dict: The parsed contents.
    """
    mapping = {}
    with open(filename, 'r') as f:
        for line in f:
            items = line.rstrip('\n').split()
            assert len(items) >= 2
            key = key_type(items[0])
            val = items[1:] if len(items) > 2 else items[1]
            mapping[key] = val
    return mapping

def dict_from_file ( filename , key_type = str ) : mapping = { } with open ( filename , 'r' ) as f : for line in f : items = line . rstrip ( '\n' ) . split ( ) assert len ( items ) >= 2 key = key_type ( items [ 0 ] ) val = items [ 1 : ] if len ( items ) > 2 else items [ 1 ] mapping [ key ] = val return mapping

Load a text file and parse the content as a dict .


def conv3x3(in_planes, out_planes, dilation=1):
    "3x3 convolution with padding"
    return nn.Conv2d(
        in_planes,
        out_planes,
        kernel_size=3,
        padding=dilation,
        dilation=dilation)

def conv3x3 ( in_planes , out_planes , dilation = 1 ) : return nn . Conv2d ( in_planes , out_planes , kernel_size = 3 , padding = dilation , dilation = dilation )


def obj_from_dict(info, parent=None, default_args=None):
    """Initialize an object from dict.

    The dict must contain the key "type", which indicates the object type, it
    can be either a string or type, such as "list" or ``list``. Remaining
    fields are treated as the arguments for constructing the object.

    Args:
        info (dict): Object types and arguments.
        parent (:class:`module`): Module which may containing expected object
            classes.
        default_args (dict, optional): Default arguments for initializing the
            object.

    Returns:
        any type: Object built from the dict.
    """
    assert isinstance(info, dict) and 'type' in info
    assert isinstance(default_args, dict) or default_args is None
    args = info.copy()
    obj_type = args.pop('type')
    if mmcv.is_str(obj_type):
        if parent is not None:
            obj_type = getattr(parent, obj_type)
        else:
            obj_type = sys.modules[obj_type]
    elif not isinstance(obj_type, type):
        raise TypeError('type must be a str or valid type, but got {}'.format(
            type(obj_type)))
    if default_args is not None:
        for name, value in default_args.items():
            args.setdefault(name, value)
    return obj_type(**args)


def imread(img_or_path, flag='color'):
    """Read an image.

    Args:
        img_or_path (ndarray or str): Either a numpy array or image path.
            If it is a numpy array (loaded image), then it will be returned
            as is.
        flag (str): Flags specifying the color type of a loaded image,
            candidates are `color`, `grayscale` and `unchanged`.

    Returns:
        ndarray: Loaded image array.
    """
    if isinstance(img_or_path, np.ndarray):
        return img_or_path
    elif is_str(img_or_path):
        flag = imread_flags[flag] if is_str(flag) else flag
        check_file_exist(img_or_path,
                         'img file does not exist: {}'.format(img_or_path))
        return cv2.imread(img_or_path, flag)
    else:
        raise TypeError('"img" must be a numpy array or a filename')


def imfrombytes(content, flag='color'):
    """Read an image from bytes.

    Args:
        content (bytes): Image bytes got from files or other streams.
        flag (str): Same as :func:`imread`.

    Returns:
        ndarray: Loaded image array.
    """
    img_np = np.frombuffer(content, np.uint8)
    flag = imread_flags[flag] if is_str(flag) else flag
    img = cv2.imdecode(img_np, flag)
    return img

def imfrombytes ( content , flag = 'color' ) : img_np = np . frombuffer ( content , np . uint8 ) flag = imread_flags [ flag ] if is_str ( flag ) else flag img = cv2 . imdecode ( img_np , flag ) return img


def imwrite(img, file_path, params=None, auto_mkdir=True):
    """Write image to file

    Args:
        img (ndarray): Image array to be written.
        file_path (str): Image file path.
        params (None or list): Same as opencv's :func:`imwrite` interface.
        auto_mkdir (bool): If the parent folder of `file_path` does not exist,
            whether to create it automatically.

    Returns:
        bool: Successful or not.
    """
    if auto_mkdir:
        dir_name = osp.abspath(osp.dirname(file_path))
        mkdir_or_exist(dir_name)
    return cv2.imwrite(file_path, img, params)

def imwrite ( img , file_path , params = None , auto_mkdir = True ) : if auto_mkdir : dir_name = osp . abspath ( osp . dirname ( file_path ) ) mkdir_or_exist ( dir_name ) return cv2 . imwrite ( file_path , img , params )


def bgr2gray(img, keepdim=False):
    """Convert a BGR image to grayscale image.

    Args:
        img (ndarray): The input image.
        keepdim (bool): If False (by default), then return the grayscale image
            with 2 dims, otherwise 3 dims.

    Returns:
        ndarray: The converted grayscale image.
    """
    out_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    if keepdim:
        out_img = out_img[..., None]
    return out_img

def bgr2gray ( img , keepdim = False ) : out_img = cv2 . cvtColor ( img , cv2 . COLOR_BGR2GRAY ) if keepdim : out_img = out_img [ ... , None ] return out_img

Convert a BGR image to grayscale image .


def gray2bgr(img):
    """Convert a grayscale image to BGR image.

    Args:
        img (ndarray or str): The input image.

    Returns:
        ndarray: The converted BGR image.
    """
    img = img[..., None] if img.ndim == 2 else img
    out_img = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
    return out_img

def gray2bgr ( img ) : img = img [ ... , None ] if img . ndim == 2 else img out_img = cv2 . cvtColor ( img , cv2 . COLOR_GRAY2BGR ) return out_img

Convert a grayscale image to BGR image .


def iter_cast(inputs, dst_type, return_type=None):
    """Cast elements of an iterable object into some type.

    Args:
        inputs (Iterable): The input object.
        dst_type (type): Destination type.
        return_type (type, optional): If specified, the output object will be
            converted to this type, otherwise an iterator.

    Returns:
        iterator or specified type: The converted object.
    """
    if not isinstance(inputs, collections_abc.Iterable):
        raise TypeError('inputs must be an iterable object')
    if not isinstance(dst_type, type):
        raise TypeError('"dst_type" must be a valid type')

    out_iterable = six.moves.map(dst_type, inputs)

    if return_type is None:
        return out_iterable
    else:
        return return_type(out_iterable)

def
iter_cast
(
inputs
,
dst_type
,
return_type
=
)
:
if
not
isinstance
(
inputs
,
collections_abc
.
Iterable
)
:
raise
TypeError
(
'inputs must be an iterable object'
)
if
not
isinstance
(
dst_type
,
type
)
:
raise
TypeError
(
'"dst_type" must be a valid type'
)
out_iterable
=
six
.
moves
.
map
(
dst_type
,
inputs
)
if
return_type
is
:
return
out_iterable
else
:
return
return_type
(
out_iterable
)

Cast elements of an iterable object into some type .


def is_seq_of(seq, expected_type, seq_type=None):
    """Check whether it is a sequence of some type.

    Args:
        seq (Sequence): The sequence to be checked.
        expected_type (type): Expected type of sequence items.
        seq_type (type, optional): Expected sequence type.

    Returns:
        bool: Whether the sequence is valid.
    """
    if seq_type is None:
        exp_seq_type = collections_abc.Sequence
    else:
        assert isinstance(seq_type, type)
        exp_seq_type = seq_type
    if not isinstance(seq, exp_seq_type):
        return False
    for item in seq:
        if not isinstance(item, expected_type):
            return False
    return True

def is_seq_of ( seq , expected_type , seq_type = None ) : if seq_type is None : exp_seq_type = collections_abc . Sequence else : assert isinstance ( seq_type , type ) exp_seq_type = seq_type if not isinstance ( seq , exp_seq_type ) : return False for item in seq : if not isinstance ( item , expected_type ) : return False return True

Check whether it is a sequence of some type .


def slice_list(in_list, lens):
    """Slice a list into several sub lists by a list of given length.

    Args:
        in_list (list): The list to be sliced.
        lens(int or list): The expected length of each out list.

    Returns:
        list: A list of sliced list.
    """
    if not isinstance(lens, list):
        raise TypeError('"indices" must be a list of integers')
    elif sum(lens) != len(in_list):
        raise ValueError(
            'sum of lens and list length does not match: {} != {}'.format(
                sum(lens), len(in_list)))
    out_list = []
    idx = 0
    for i in range(len(lens)):
        out_list.append(in_list[idx:idx + lens[i]])
        idx += lens[i]
    return out_list

Slice a list into several sub lists by a list of given length .


def check_prerequisites(
        prerequisites,
        checker,
        msg_tmpl='Prerequisites "{}" are required in method "{}" but not '
        'found, please install them first.'):
    """A decorator factory to check if prerequisites are satisfied.

    Args:
        prerequisites (str of list[str]): Prerequisites to be checked.
        checker (callable): The checker method that returns True if a
            prerequisite is meet, False otherwise.
        msg_tmpl (str): The message template with two variables.

    Returns:
        decorator: A specific decorator.
    """

    def wrap(func):

        @functools.wraps(func)
        def wrapped_func(*args, **kwargs):
            requirements = [prerequisites] if isinstance(
                prerequisites, str) else prerequisites
            missing = []
            for item in requirements:
                if not checker(item):
                    missing.append(item)
            if missing:
                print(msg_tmpl.format(', '.join(missing), func.__name__))
                raise RuntimeError('Prerequisites not meet.')
            else:
                return func(*args, **kwargs)

        return wrapped_func

    return wrap

A decorator factory to check if prerequisites are satisfied .


def average(self, n=0):
        """Average latest n values or all values"""
        assert n >= 0
        for key in self.val_history:
            values = np.array(self.val_history[key][-n:])
            nums = np.array(self.n_history[key][-n:])
            avg = np.sum(values * nums) / np.sum(nums)
            self.output[key] = avg
        self.ready = True

def average ( self , n = 0 ) : assert n >= 0 for key in self . val_history : values = np . array ( self . val_history [ key ] [ - n : ] ) nums = np . array ( self . n_history [ key ] [ - n : ] ) avg = np . sum ( values * nums ) / np . sum ( nums ) self . output [ key ] = avg self . ready = True


def scatter(input, devices, streams=None):
    """Scatters tensor across multiple GPUs.
    """
    if streams is None:
        streams = [None] * len(devices)

    if isinstance(input, list):
        chunk_size = (len(input) - 1) // len(devices) + 1
        outputs = [
            scatter(input[i], [devices[i // chunk_size]],
                    [streams[i // chunk_size]]) for i in range(len(input))
        ]
        return outputs
    elif isinstance(input, torch.Tensor):
        output = input.contiguous()
        # TODO: copy to a pinned buffer first (if copying from CPU)
        stream = streams[0] if output.numel() > 0 else None
        with torch.cuda.device(devices[0]), torch.cuda.stream(stream):
            output = output.cuda(devices[0], non_blocking=True)
        return output
    else:
        raise Exception('Unknown type {}.'.format(type(input)))


def color_val(color):
    """Convert various input to color tuples.

    Args:
        color (:obj:`Color`/str/tuple/int/ndarray): Color inputs

    Returns:
        tuple[int]: A tuple of 3 integers indicating BGR channels.
    """
    if is_str(color):
        return Color[color].value
    elif isinstance(color, Color):
        return color.value
    elif isinstance(color, tuple):
        assert len(color) == 3
        for channel in color:
            assert channel >= 0 and channel <= 255
        return color
    elif isinstance(color, int):
        assert color >= 0 and color <= 255
        return color, color, color
    elif isinstance(color, np.ndarray):
        assert color.ndim == 1 and color.size == 3
        assert np.all((color >= 0) & (color <= 255))
        color = color.astype(np.uint8)
        return tuple(color)
    else:
        raise TypeError('Invalid type for color: {}'.format(type(color)))

def
color_val
(
color
)
:
if
is_str
(
color
)
:
return
Color
[
color
]
.
value
elif
isinstance
(
color
,
Color
)
:
return
color
.
value
elif
isinstance
(
color
,
tuple
)
:
assert
len
(
color
)
==
3
for
channel
in
color
:
assert
channel
>=
0
and
channel
<=
255
return
color
elif
isinstance
(
color
,
int
)
:
assert
color
>=
0
and
color
<=
255
return
color
,
color
,
color
elif
isinstance
(
color
,
np
.
ndarray
)
:
assert
color
.
ndim
==
1
and
color
.
size
==
3
assert
np
.
all
(
(
color
>=
0
)
&
(
color
<=
255
)
)
color
=
color
.
astype
(
np
.
uint8
)
return
tuple
(
color
)
else
:
raise
TypeError
(
'Invalid type for color: {}'
.
format
(
type
(
color
)
)
)


def check_time(timer_id):
    """Add check points in a single line.

    This method is suitable for running a task on a list of items. A timer will
    be registered when the method is called for the first time.

    :Example:

    >>> import time
    >>> import mmcv
    >>> for i in range(1, 6):
    >>>     # simulate a code block
    >>>     time.sleep(i)
    >>>     mmcv.check_time('task1')
    2.000
    3.000
    4.000
    5.000

    Args:
        timer_id (str): Timer identifier.
    """
    if timer_id not in _g_timers:
        _g_timers[timer_id] = Timer()
        return 0
    else:
        return _g_timers[timer_id].since_last_check()

def check_time ( timer_id ) : if timer_id not in _g_timers : _g_timers [ timer_id ] = Timer ( ) return 0 else : return _g_timers [ timer_id ] . since_last_check ( )


def start(self):
        """Start the timer."""
        if not self._is_running:
            self._t_start = time()
            self._is_running = True
        self._t_last = time()

def start ( self ) : if not self . _is_running : self . _t_start = time ( ) self . _is_running = True self . _t_last = time ( )


def since_start(self):
        """Total time since the timer is started.

        Returns (float): Time in seconds.
        """
        if not self._is_running:
            raise TimerError('timer is not running')
        self._t_last = time()
        return self._t_last - self._t_start

def
since_start
(
self
)
:
if
not
self
.
_is_running
:
raise
TimerError
(
'timer is not running'
)
self
.
_t_last
=
time
(
)
return
self
.
_t_last
self
.
_t_start


def since_last_check(self):
        """Time since the last checking.

        Either :func:`since_start` or :func:`since_last_check` is a checking
        operation.

        Returns (float): Time in seconds.
        """
        if not self._is_running:
            raise TimerError('timer is not running')
        dur = time() - self._t_last
        self._t_last = time()
        return dur

def
since_last_check
(
self
)
:
if
not
self
.
_is_running
:
raise
TimerError
(
'timer is not running'
)
dur
=
time
(
)
self
.
_t_last
self
.
_t_last
=
time
(
)
return
dur


def flowshow(flow, win_name='', wait_time=0):
    """Show optical flow.

    Args:
        flow (ndarray or str): The optical flow to be displayed.
        win_name (str): The window name.
        wait_time (int): Value of waitKey param.
    """
    flow = flowread(flow)
    flow_img = flow2rgb(flow)
    imshow(rgb2bgr(flow_img), win_name, wait_time)

def flowshow ( flow , win_name = '' , wait_time = 0 ) : flow = flowread ( flow ) flow_img = flow2rgb ( flow ) imshow ( rgb2bgr ( flow_img ) , win_name , wait_time )


def flow2rgb(flow, color_wheel=None, unknown_thr=1e6):
    """Convert flow map to RGB image.

    Args:
        flow (ndarray): Array of optical flow.
        color_wheel (ndarray or None): Color wheel used to map flow field to
            RGB colorspace. Default color wheel will be used if not specified.
        unknown_thr (str): Values above this threshold will be marked as
            unknown and thus ignored.

    Returns:
        ndarray: RGB image that can be visualized.
    """
    assert flow.ndim == 3 and flow.shape[-1] == 2
    if color_wheel is None:
        color_wheel = make_color_wheel()
    assert color_wheel.ndim == 2 and color_wheel.shape[1] == 3
    num_bins = color_wheel.shape[0]

    dx = flow[:, :, 0].copy()
    dy = flow[:, :, 1].copy()

    ignore_inds = (np.isnan(dx) | np.isnan(dy) | (np.abs(dx) > unknown_thr) |
                   (np.abs(dy) > unknown_thr))
    dx[ignore_inds] = 0
    dy[ignore_inds] = 0

    rad = np.sqrt(dx**2 + dy**2)
    if np.any(rad > np.finfo(float).eps):
        max_rad = np.max(rad)
        dx /= max_rad
        dy /= max_rad

    [h, w] = dx.shape

    rad = np.sqrt(dx**2 + dy**2)
    angle = np.arctan2(-dy, -dx) / np.pi

    bin_real = (angle + 1) / 2 * (num_bins - 1)
    bin_left = np.floor(bin_real).astype(int)
    bin_right = (bin_left + 1) % num_bins
    w = (bin_real - bin_left.astype(np.float32))[..., None]
    flow_img = (
        1 - w) * color_wheel[bin_left, :] + w * color_wheel[bin_right, :]
    small_ind = rad <= 1
    flow_img[small_ind] = 1 - rad[small_ind, None] * (1 - flow_img[small_ind])
    flow_img[np.logical_not(small_ind)] *= 0.75

    flow_img[ignore_inds, :] = 0

    return flow_img

def flow2rgb ( flow , color_wheel = None , unknown_thr = 1e6 ) : assert flow . ndim == 3 and flow . shape [ - 1 ] == 2 if color_wheel is None : color_wheel = make_color_wheel ( ) assert color_wheel . ndim == 2 and color_wheel . shape [ 1 ] == 3 num_bins = color_wheel . shape [ 0 ] dx = flow [ : , : , 0 ] . copy ( ) dy = flow [ : , : , 1 ] . copy ( ) ignore_inds = ( np . isnan ( dx ) | np . isnan ( dy ) | ( np . abs ( dx ) > unknown_thr ) | ( np . abs ( dy ) > unknown_thr ) ) dx [ ignore_inds ] = 0 dy [ ignore_inds ] = 0 rad = np . sqrt ( dx ** 2 + dy ** 2 ) if np . any ( rad > np . finfo ( float ) . eps ) : max_rad = np . max ( rad ) dx /= max_rad dy /= max_rad [ h , w ] = dx . shape rad = np . sqrt ( dx ** 2 + dy ** 2 ) angle = np . arctan2 ( - dy , - dx ) / np . pi bin_real = ( angle + 1 ) / 2 * ( num_bins - 1 ) bin_left = np . floor ( bin_real ) . astype ( int ) bin_right = ( bin_left + 1 ) % num_bins w = ( bin_real - bin_left . astype ( np . float32 ) ) [ ... , None ] flow_img = ( 1 - w ) * color_wheel [ bin_left , : ] + w * color_wheel [ bin_right , : ] small_ind = rad <= 1 flow_img [ small_ind ] = 1 - rad [ small_ind , None ] * ( 1 - flow_img [ small_ind ] ) flow_img [ np . logical_not ( small_ind ) ] *= 0.75 flow_img [ ignore_inds , : ] = 0 return flow_img


def make_color_wheel(bins=None):
    """Build a color wheel.

    Args:
        bins(list or tuple, optional): Specify the number of bins for each
            color range, corresponding to six ranges: red -> yellow,
            yellow -> green, green -> cyan, cyan -> blue, blue -> magenta,
            magenta -> red. [15, 6, 4, 11, 13, 6] is used for default
            (see Middlebury).

    Returns:
        ndarray: Color wheel of shape (total_bins, 3).
    """
    if bins is None:
        bins = [15, 6, 4, 11, 13, 6]
    assert len(bins) == 6

    RY, YG, GC, CB, BM, MR = tuple(bins)

    ry = [1, np.arange(RY) / RY, 0]
    yg = [1 - np.arange(YG) / YG, 1, 0]
    gc = [0, 1, np.arange(GC) / GC]
    cb = [0, 1 - np.arange(CB) / CB, 1]
    bm = [np.arange(BM) / BM, 0, 1]
    mr = [1, 0, 1 - np.arange(MR) / MR]

    num_bins = RY + YG + GC + CB + BM + MR

    color_wheel = np.zeros((3, num_bins), dtype=np.float32)

    col = 0
    for i, color in enumerate([ry, yg, gc, cb, bm, mr]):
        for j in range(3):
            color_wheel[j, col:col + bins[i]] = color[j]
        col += bins[i]

    return color_wheel.T

def make_color_wheel ( bins = None ) : if bins is None : bins = [ 15 , 6 , 4 , 11 , 13 , 6 ] assert len ( bins ) == 6 RY , YG , GC , CB , BM , MR = tuple ( bins ) ry = [ 1 , np . arange ( RY ) / RY , 0 ] yg = [ 1 - np . arange ( YG ) / YG , 1 , 0 ] gc = [ 0 , 1 , np . arange ( GC ) / GC ] cb = [ 0 , 1 - np . arange ( CB ) / CB , 1 ] bm = [ np . arange ( BM ) / BM , 0 , 1 ] mr = [ 1 , 0 , 1 - np . arange ( MR ) / MR ] num_bins = RY + YG + GC + CB + BM + MR color_wheel = np . zeros ( ( 3 , num_bins ) , dtype = np . float32 ) col = 0 for i , color in enumerate ( [ ry , yg , gc , cb , bm , mr ] ) : for j in range ( 3 ) : color_wheel [ j , col : col + bins [ i ] ] = color [ j ] col += bins [ i ] return color_wheel . T


def accuracy(output, target, topk=(1, )):
    """Computes the precision@k for the specified values of k"""
    with torch.no_grad():
        maxk = max(topk)
        batch_size = target.size(0)

        _, pred = output.topk(maxk, 1, True, True)
        pred = pred.t()
        correct = pred.eq(target.view(1, -1).expand_as(pred))

        res = []
        for k in topk:
            correct_k = correct[:k].view(-1).float().sum(0, keepdim=True)
            res.append(correct_k.mul_(100.0 / batch_size))
        return res

def accuracy ( output , target , topk = ( 1 , ) ) : with torch . no_grad ( ) : maxk = max ( topk ) batch_size = target . size ( 0 ) _ , pred = output . topk ( maxk , 1 , True , True ) pred = pred . t ( ) correct = pred . eq ( target . view ( 1 , - 1 ) . expand_as ( pred ) ) res = [ ] for k in topk : correct_k = correct [ : k ] . view ( - 1 ) . float ( ) . sum ( 0 , keepdim = True ) res . append ( correct_k . mul_ ( 100.0 / batch_size ) ) return res


def scatter(inputs, target_gpus, dim=0):
    """Scatter inputs to target gpus.

    The only difference from original :func:`scatter` is to add support for
    :type:`~mmcv.parallel.DataContainer`.
    """

    def scatter_map(obj):
        if isinstance(obj, torch.Tensor):
            return OrigScatter.apply(target_gpus, None, dim, obj)
        if isinstance(obj, DataContainer):
            if obj.cpu_only:
                return obj.data
            else:
                return Scatter.forward(target_gpus, obj.data)
        if isinstance(obj, tuple) and len(obj) > 0:
            return list(zip(*map(scatter_map, obj)))
        if isinstance(obj, list) and len(obj) > 0:
            out = list(map(list, zip(*map(scatter_map, obj))))
            return out
        if isinstance(obj, dict) and len(obj) > 0:
            out = list(map(type(obj), zip(*map(scatter_map, obj.items()))))
            return out
        return [obj for targets in target_gpus]

    # After scatter_map is called, a scatter_map cell will exist. This cell
    # has a reference to the actual function scatter_map, which has references
    # to a closure that has a reference to the scatter_map cell (because the
    # fn is recursive). To avoid this reference cycle, we set the function to
    # None, clearing the cell
    try:
        return scatter_map(inputs)
    finally:
        scatter_map = None


def scatter_kwargs(inputs, kwargs, target_gpus, dim=0):
    """Scatter with support for kwargs dictionary"""
    inputs = scatter(inputs, target_gpus, dim) if inputs else []
    kwargs = scatter(kwargs, target_gpus, dim) if kwargs else []
    if len(inputs) < len(kwargs):
        inputs.extend([() for _ in range(len(kwargs) - len(inputs))])
    elif len(kwargs) < len(inputs):
        kwargs.extend([{} for _ in range(len(inputs) - len(kwargs))])
    inputs = tuple(inputs)
    kwargs = tuple(kwargs)
    return inputs, kwargs

def scatter_kwargs ( inputs , kwargs , target_gpus , dim = 0 ) : inputs = scatter ( inputs , target_gpus , dim ) if inputs else [ ] kwargs = scatter ( kwargs , target_gpus , dim ) if kwargs else [ ] if len ( inputs ) < len ( kwargs ) : inputs . extend ( [ ( ) for _ in range ( len ( kwargs ) - len ( inputs ) ) ] ) elif len ( kwargs ) < len ( inputs ) : kwargs . extend ( [ { } for _ in range ( len ( inputs ) - len ( kwargs ) ) ] ) inputs = tuple ( inputs ) kwargs = tuple ( kwargs ) return inputs , kwargs


async def fetch(self) -> Response:
        """Fetch all the information by using aiohttp"""
        if self.request_config.get('DELAY', 0) > 0:
            await asyncio.sleep(self.request_config['DELAY'])

        timeout = self.request_config.get('TIMEOUT', 10)
        try:
            async with async_timeout.timeout(timeout):
                resp = await self._make_request()
            try:
                resp_data = await resp.text(encoding=self.encoding)
            except UnicodeDecodeError:
                resp_data = await resp.read()

            response = Response(
                url=self.url,
                method=self.method,
                encoding=resp.get_encoding(),
                html=resp_data,
                metadata=self.metadata,
                cookies=resp.cookies,
                headers=resp.headers,
                history=resp.history,
                status=resp.status,
                aws_json=resp.json,
                aws_text=resp.text,
                aws_read=resp.read)
            # Retry middleware
            aws_valid_response = self.request_config.get('VALID')
            if aws_valid_response and iscoroutinefunction(aws_valid_response):
                response = await aws_valid_response(response)
            if response.ok:
                return response
            else:
                return await self._retry(error_msg='request url failed!')
        except asyncio.TimeoutError:
            return await self._retry(error_msg='timeout')
        except Exception as e:
            return await self._retry(error_msg=e)
        finally:
            # Close client session
            await self._close_request_session()

async
def
fetch
(
self
)
->
Response
:
if
self
.
request_config
.
get
(
'DELAY'
,
0
)
>
0
:
await
asyncio
.
sleep
(
self
.
request_config
[
'DELAY'
]
)
timeout
=
self
.
request_config
.
get
(
'TIMEOUT'
,
10
)
try
:
async
with
async_timeout
.
timeout
(
timeout
)
:
resp
=
await
self
.
_make_request
(
)
try
:
resp_data
=
await
resp
.
text
(
encoding
=
self
.
encoding
)
except
UnicodeDecodeError
:
resp_data
=
await
resp
.
read
(
)
response
=
Response
(
url
=
self
.
url
,
method
=
self
.
method
,
encoding
=
resp
.
get_encoding
(
)
,
html
=
resp_data
,
metadata
=
self
.
metadata
,
cookies
=
resp
.
cookies
,
headers
=
resp
.
headers
,
history
=
resp
.
history
,
status
=
resp
.
status
,
aws_json
=
resp
.
json
,
aws_text
=
resp
.
text
,
aws_read
=
resp
.
read
)
# Retry middleware
aws_valid_response
=
self
.
request_config
.
get
(
'VALID'
)
if
aws_valid_response
and
iscoroutinefunction
(
aws_valid_response
)
:
response
=
await
aws_valid_response
(
response
)
if
response
.
ok
:
return
response
else
:
return
await
self
.
_retry
(
error_msg
=
'request url failed!'
)
except
asyncio
.
TimeoutError
:
return
await
self
.
_retry
(
error_msg
=
'timeout'
)
except
Exception
as
e
:
return
await
self
.
_retry
(
error_msg
=
e
)
finally
:
# Close client session
await
self
.
_close_request_session
(
)


async def json(self,
                   *,
                   encoding: str = None,
                   loads: JSONDecoder = DEFAULT_JSON_DECODER,
                   content_type: Optional[str] = 'application/json') -> Any:
        """Read and decodes JSON response."""
        return await self._aws_json(
            encoding=encoding, loads=loads, content_type=content_type)

async def json ( self , * , encoding : str = None , loads : JSONDecoder = DEFAULT_JSON_DECODER , content_type : Optional [ str ] = 'application/json' ) -> Any : return await self . _aws_json ( encoding = encoding , loads = loads , content_type = content_type )


async def text(self,
                   *,
                   encoding: Optional[str] = None,
                   errors: str = 'strict') -> str:
        """Read response payload and decode."""
        return await self._aws_text(encoding=encoding, errors=errors)

async def text ( self , * , encoding : Optional [ str ] = None , errors : str = 'strict' ) -> str : return await self . _aws_text ( encoding = encoding , errors = errors )


async def handle_callback(self, aws_callback: typing.Coroutine, response):
        """Process coroutine callback function"""
        callback_result = None

        try:
            callback_result = await aws_callback
        except NothingMatchedError as e:
            self.logger.error(f'<Item: {str(e).lower()}>')
        except Exception as e:
            self.logger.error(f'<Callback[{aws_callback.__name__}]: {e}')
        return callback_result, response