Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 30 additions & 4 deletions lightning/types/images.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from lightning.types.base import Base
from lightning.types.decorators import viztype
from lightning.types.utils import array_to_im
from lightning.types.utils import array_to_im, polygon_to_points, polygon_to_mask


@viztype
Expand All @@ -27,12 +27,38 @@ def clean(imagedata):
outdict = [array_to_im(imagedata)]

return {'images': outdict}

def get_coords(self, return_type='bounds', dims=None):
"""
Get data from polygons drawn on image.

Parameters
----------
return_type : string, optional, default='bounds'
Specification of output data. Options are 'bounds','points', and 'mask'

dims : array-like, optional, default=None
Specify the size of the image containing the polygon.

"""

@property
def coords(self):
user_data = self.get_user_data()['settings']
if 'coords' in user_data.keys():
return user_data['coords']
coords = user_data['coords']

if return_type == 'bounds':
return coords

elif return_type == 'points':
return [polygon_to_points(x) for x in coords]

elif return_type == 'mask':
if not dims:
raise Exception('Must provide image dimensions to return mask')
return [polygon_to_mask(x, dims) for x in coords]

else:
raise Exception('Option %s is not supported' % return_type)
else:
return []

Expand Down
48 changes: 45 additions & 3 deletions lightning/types/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from numpy import asarray, array, ndarray, vstack, newaxis, nonzero, concatenate, transpose, atleast_2d, size, isscalar

from numpy import asarray, array, ndarray, vstack, newaxis, nonzero, concatenate, transpose, atleast_2d, size, isscalar, meshgrid, where
from matplotlib.path import Path

def add_property(d, prop, name):

Expand Down Expand Up @@ -206,4 +206,46 @@ def list_to_regions(reg):
checkthree = all(map(lambda x: len(x) == 3, reg))
if not (checktwo or checkthree):
raise Exception("All region names must be two letters (for US) or three letters (for world)")
return reg
return reg


def polygon_to_mask(coords, dims):
"""
Given a list of pairs of points which define a polygon, return a binary
mask covering the interior of the polygon
"""

bounds = array(coords).astype('int')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Replace array with asarray

path = Path(bounds)

grid = meshgrid(range(dims[1]), range(dims[0]))
grid_flat = zip(grid[0].ravel(), grid[1].ravel())

mask = path.contains_points(grid_flat).reshape(dims[0:2]).astype('int')

return mask


def polygon_to_points(coords):
"""
Given a list of pairs of points which define a polygon,
return a list of points interior to the polygon
"""

bounds = array(coords).astype('int')

bmax = bounds.max(0)
bmin = bounds.min(0)

path = Path(bounds)

grid = meshgrid(range(bmin[0], bmax[0]+1), range(bmin[1], bmax[1]+1))

grid_flat = zip(grid[0].ravel(), grid[1].ravel())

points = path.contains_points(grid_flat).reshape(grid[0].shape).astype('int')
points = where(points)
points = vstack([points[0], points[1]]).T + bmin[-1::-1]
points = points.tolist()

return points