Point selection with shapes layer + Shapely

Greetings #napari users/developers.

I put together a simple annotation function that might be of use to the community. We’re using functionality like this to hand annotate data embeddings, but you might find use for it elsewhere.

import napari
import numpy as np
from shapely.ops import cascaded_union
from sklearn.datasets import make_blobs
from shapely.geometry import Point, Polygon, MultiPolygon

%gui qt5

v = napari.Viewer()

@v.bind_key('f')
def get_selected_points(v):
    union_data = cascaded_union([Polygon(i) for i in v.layers['annotation'].data])
    if isinstance(union_data, type(MultiPolygon())):
        polys = [Polygon(np.array(poly.exterior.coords)) for poly in union_data]
    else:
        polys = [Polygon(np.array(union_data.exterior.coords))]
    
    all_pts    = [Point(i) for i in X]
    mask       = np.any([[p.within(poly) for p in all_pts] for poly in polys], axis=0)
    sel_pts    = v.add_points(X[mask],face_color='red',size=0.1,name='selected')
    
centers = [[1, 1], [-1, -1], [1, -1]]
X, y = make_blobs(n_samples=1000, centers=centers, cluster_std=0.6)
all_points = v.add_points(X, size=0.05)

v.add_shapes(name='annotation', edge_width=0, opacity=0.1)

A simple video demo: https://www.loom.com/share/5319704a03c949438686c9d3449cb353

7 Likes

That’s super-cool, @burlinge! Thank you for sharing!

2 Likes

Awesome, once we have our plugin infrastructure up this would make a great plugin!!

1 Like

I have a advice, Napari should support shapely directly, or convert through geojson. With shapely, we can edit vector easily, such as union, clip, pick.

2 Likes