Article Outline
Python matplotlib example 'lasso imshow select'
Functions in program:
def imshow_select(data, selector='lasso', bbox=False):
def path_bbox(p):
Modules used in program:
import numpy as np
import matplotlib.pyplot as plt
python lasso imshow select
Python matplotlib example: lasso imshow select
#!/usr/bin/env python
"""
Function for interactively selecting part of an array displayed as an image with matplotlib.
"""
import matplotlib.pyplot as plt
from matplotlib import is_interactive
from matplotlib.path import Path
from matplotlib.widgets import LassoSelector, RectangleSelector
import numpy as np
def path_bbox(p):
"""
Return rectangular bounding box of given path.
Parameters
----------
p : array_like
Array of vertices with shape Nx2.
Returns
-------
bbox : array_like
Array of bounding box vertices with shape 4x2.
"""
assert p.ndim == 2
assert p.shape[1] == 2
ix_min = p[:, 0].argmin()
ix_max = p[:, 0].argmax()
iy_min = p[:, 1].argmin()
iy_max = p[:, 1].argmax()
return np.array([[p[ix_min, 0], p[iy_min, 1]],
[p[ix_min, 0], p[iy_max, 1]],
[p[ix_max, 0], p[iy_max, 1]],
[p[ix_max, 0], p[iy_min, 1]]])
def imshow_select(data, selector='lasso', bbox=False):
"""
Display array as image with region selector.
Parameters
----------
data : array_like
Array to display.
selector : str
Region selector. For `lasso`, use `LassoSelector`; for `rectangle`,
use `RectangleSelector`.
bbox : bool
If True, only return array within rectangular bounding box of selected region.
Otherwise, return array with same dimensions as `data` such that selected region
contains the corresponding values from `data` and the remainder contains 0.
Returns
-------
region : array_like
Data for selected region.
mask : array_like
Boolean mask with same shape of `data` for selecting the returned region from `data`.
"""
interactive = is_interactive()
if not interactive:
plt.ion()
fig = plt.figure()
ax = fig.gca()
ax.imshow(data)
x, y = np.meshgrid(np.arange(data.shape[1], dtype=int),
np.arange(data.shape[0], dtype=int))
pix = np.vstack((x.flatten(), y.flatten())).T
# Store data in dict value to permit overwriting by nested
# functions in Python 2.7:
selected = {}
selected['data'] = np.zeros_like(data)
selected['mask'] = np.tile(False, data.shape)
def _onselect_lasso(verts):
verts = np.array(verts)
p = Path(verts)
ind = p.contains_points(pix, radius=1)
selected['data'].flat[ind] = data.flat[ind]
selected['mask'].flat[ind] = True
if bbox:
b = path_bbox(verts)
selected['data'] = selected['data'][int(min(b[:, 1])):int(max(b[:, 1])),
int(min(b[:, 0])):int(max(b[:, 0]))]
def _onselect_rectangle(start, end):
verts = np.array([[start.xdata, start.ydata],
[start.xdata, end.ydata],
[end.xdata, end.ydata],
[end.xdata, start.ydata]], int)
p = Path(verts)
ind = p.contains_points(pix, radius=1)
selected['data'].flat[ind] = data.flat[ind]
selected['mask'].flat[ind] = True
if bbox:
b = path_bbox(verts)
selected['data'] = selected['data'][min(b[:, 1]):max(b[:, 1]),
min(b[:, 0]):max(b[:, 0])]
name_to_selector = {'lasso': LassoSelector,
'rectangle': RectangleSelector}
selector = name_to_selector[selector]
onselect_dict = {LassoSelector: _onselect_lasso,
RectangleSelector: _onselect_rectangle}
kwargs_dict = {LassoSelector: {},
RectangleSelector: {'interactive': True}}
lasso = selector(ax, onselect_dict[selector], **kwargs_dict[selector])
raw_input('Press Enter when done')
lasso.disconnect_events()
if not interactive:
plt.ioff()
return selected['data'], selected['mask']
if __name__ == '__main__':
from skimage.data import coins
data = coins()
selected, mask = imshow_select(data, 'lasso', True)
plt.imsave('selected.png', selected)
plt.imsave('mask.png', mask)
Python links
- Learn Python: https://pythonbasics.org/
- Python Tutorial: https://pythonprogramminglanguage.com