Kevin L
Initial commit
5fd3fc6
Raw History Blame Contribute Delete
6.27 kB
from __future__ import absolute_import, division
import numpy as np
from .operations import bezier_curve
from .operations import bresenham as bresenham_function
def scribbles2mask(scribbles,
output_resolution,
bezier_curve_sampling=False,
nb_points=1000,
bresenham=True,
default_value=-1,
single_object=False):
""" Convert the scribbles data into a mask.
# Arguments
scribbles: Dictionary. Scribbles in the default format.
output_resolution: Tuple. Output resolution (H, W).
bezier_curve_sampling: Boolean. Weather to sample first the returned
scribbles using bezier curve or not.
nb_points: Integer. If `bezier_curve_sampling` is `True` set the number
of points to sample from the bezier curve.
bresenham: Boolean. Whether to compute bresenham algorithm for the
scribbles lines.
default_value: Integer. Default value for the pixels which do not belong
to any scribble.
# Returns
ndarray: Array with the mask of the scribbles with the index of the
object ids. The shape of the returned array is (B x H x W) by
default or (H x W) if `only_annotated_frame==True`.
"""
if len(output_resolution) != 2:
raise ValueError(
'Invalid output resolution: {}'.format(output_resolution))
for r in output_resolution:
if r < 1:
raise ValueError(
'Invalid output resolution: {}'.format(output_resolution))
nb_frames = len(scribbles['scribbles'])
masks = np.full(
(nb_frames,) + output_resolution, default_value, dtype=np.int)
size_array = np.asarray(output_resolution[::-1], dtype=np.float) - 1
for f in range(nb_frames):
sp = scribbles['scribbles'][f]
for p in sp:
path = p['path']
if single_object:
# Simulate having only one object
obj_id = 1
else:
obj_id = p['object_id']
path = np.asarray(path, dtype=np.float)
if bezier_curve_sampling:
path = bezier_curve(path, nb_points=nb_points)
path *= size_array
path = path.astype(np.int)
if bresenham:
path = bresenham_function(path)
m = masks[f]
m[path[:, 1], path[:, 0]] = obj_id
masks[f] = m
return masks
def scribbles2points(scribbles_data, output_resolution=None):
""" Convert the given scribbles into a list of points and object ids.
# Arguments
scribbles_data: Dictionary. Scribbles in the default format
output_resolution: Tuple. Output resolution (H, W) to scale the
points.
If None given, the points will be floats as a fraction of height
and width.
# Returns
(ndarray, ndarray): Returns (X, Y) where X is a list of points from the
scribbles represented in the output_resolution with shape (N x 3)
with N being the total number of points on all the scribbles. The three
coordinates given correspond the the frame number, height and width,
respectively.
Y is the object id for each given point with shape (N,).
"""
scribbles = scribbles_data['scribbles']
paths, object_ids = [], []
for frame, s in enumerate(scribbles):
for l in s:
# p = l['path']
coordinates = [[frame] + point for point in l['path']]
paths += coordinates
object_ids += [l['object_id']] * len(l['path'])
paths = np.asarray(paths, dtype=np.float)
object_ids = np.asarray(object_ids, dtype=np.int)
if output_resolution:
h, w = output_resolution
img_size = np.asarray([1, h - 1, w - 1], dtype=np.float)
paths *= img_size
paths = paths.astype(np.int)
return paths, object_ids
def fuse_scribbles(scribbles_a, scribbles_b):
""" Fuse two scribbles in the default format.
# Arguments
scribbles_a: Dictionary. Default representation of scribbles A.
scribbles_b: Dictionary. Default representation of scribbles B.
# Returns
dict: Returns a dictionary with scribbles A and B fused.
"""
if scribbles_a['sequence'] != scribbles_b['sequence']:
raise ValueError('Scribbles to fuse are not from the same sequence')
if len(scribbles_a['scribbles']) != len(scribbles_b['scribbles']):
raise ValueError('Scribbles does not have the same number of frames')
scribbles = dict(scribbles_a)
nb_frames = len(scribbles['scribbles'])
for i in range(nb_frames):
scribbles['scribbles'][i] += scribbles_b['scribbles'][i]
return scribbles
def is_empty(scribbles_data):
""" Checks whether the given scribble has any non-empty line.
# Arguments
scribbles_data (dict): Scribble in the default format
# Returns
bool: Whether the scribble is empty or not.
"""
scribbles = scribbles_data['scribbles']
has_lines = [len(s) > 0 for s in scribbles]
return not any(has_lines)
def annotated_frames(scribbles_data):
""" Finds which frames have a scribble.
# Arguments
scribbles_data (dict): Scribble in the default format.
# Returns
list: Number of the frames that contain at least one scribble.
"""
scribbles = scribbles_data['scribbles']
frames_list = [i for i, s in enumerate(scribbles) if s]
return frames_list
def annotated_frames_object(scribbles_data, object_id):
""" Computes which frames have a scribble for a certain object.
# Arguments
scribbles_data (dict): Scribble in the default format.
object_id (int): Id of the object of interest.
# Returns
dict: Number of the frames that contain at least one scribble.
"""
frames_list = []
scribbles = scribbles_data['scribbles']
for ii, scribble_frame in enumerate(scribbles):
for scribble in scribble_frame:
if scribble['object_id'] == object_id:
frames_list.append(ii)
break
return frames_list