Skip to content

Commit

Permalink
Merge pull request #29 from danforthcenter/18-napari-import-coor
Browse files Browse the repository at this point in the history
Updates to napari_label_classes
  • Loading branch information
HaleySchuhl authored Sep 12, 2024
2 parents 4324cdd + 526fb46 commit 888e3db
Show file tree
Hide file tree
Showing 4 changed files with 88 additions and 27 deletions.
2 changes: 1 addition & 1 deletion docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ All notable changes to this project will be documented below.

#### annotate.napari_label_classes

* v0.1dev: viewer = **annotate.napari_label_classes**(*img, classes, show=True*)
* v0.1dev: viewer = **annotate.napari_label_classes**(*img, classes, size=10, shape='square', importdata=False, show=True*)

#### annotate.napari_open

Expand Down
25 changes: 12 additions & 13 deletions docs/napari_label_classes.md
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
## Label Image with Napari

This function opens an image in Napari and then defines a set of classes to label. A random shape label is assigned to each class.
This function opens an image in Napari and then defines a set of Points layers with the user-defined labels called `classes`. A random `shape` of the annotation symbol is assigned to each of the `classes`.
Image can be annotated as long as viewer is open.

**plantcv.annotate.napari_label_classes*(*img, classes, show=True*)
**plantcv.annotate.napari_label_classes*(*img, classes, size=10, shape='square', importdata=False, show=True*)

**returns** napari viewer object

- **Parameters:**
- img - image data (compatible with gray, RGB, and hyperspectral data. If data is hyperspecral it should be the array e.g. hyperspectral.array_data)
- classes - list of classes to label. If no points are selected for a class,
data without labels will default to this class when napari_join_labels
is run. If all classes have points labeled, any clusters not labeled
will default to the last class in the list if napari_join_labels is
run.
- show - if show = True, viewer is launched. False setting is useful for test purposes.
- classes - list of classes to label. This option is not necessary if data is data is imported.
- size - integer pixel size of label (also adjustable from the interactive Napari viewer)
- shape - shape of the annotation symbol. Can be 'o', 'arrow', 'clobber', 'cross', 'diamond', 'disc', 'hbar', 'ring', 'square' (default), 'star', 'tailed_arrow',
'triangle_down', 'triangle_up', 'vbar', or 'x' (also adjustable from the interactive Napari viewer)
- importdata - dictionary of data, data saved from napari_save_coor or data imported from napari_read_coor
- show - if `show=True`, viewer is launched. `False` setting is useful for test purposes.

- **Context:**
- Adding class labels to images. Works best on an image that has objects segmented/classified with contours/clusters labeled with values (e.g. labeled mask, output of kmeans clustering).
- Adding one or more classes of points layer for annotation of the image.

- **Example use:**
- Labeling output of kmeans clustering into classes. Labeling points.
- Ground truth counting, labeling classes of objects of interest.


```python
Expand All @@ -31,9 +31,8 @@ import napari
# Create an instance of the Points class
img, path, name = pcv.readimage("./grayimg.png")

viewer = pcvan.napari_label_classes(img=img, classes=['background', 'wing','seed'])

# Should open interactive napari viewer
# Opens interactive napari viewer
viewer = pcvan.napari_label_classes(img=img, classes=['background', 'wing','seed'], size=30)

```

Expand Down
75 changes: 67 additions & 8 deletions plantcv/annotate/napari_label_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import numpy as np
import random
from plantcv.annotate import napari_open
from plantcv.annotate import napari_classes


def napari_label_classes(img, classes, show=True):
def napari_label_classes(img, classes=False, size=10, shape='square',
importdata=False, show=True):
"""
open img in napari and label classes
Expand All @@ -19,26 +21,83 @@ def napari_label_classes(img, classes, show=True):
is run. If all classes have points labeled, any clusters not labeled
will default to the last class in the list when napari_join_labels is
run.
show = if show is True the viewer is launched. This option is useful for
size = size of marker in pixels
shape = either 'square' or 'circle'
importdata = dictionary of values in Napari format (y,x).
Output of napari_read_coor
show = if show is True the viewer is launched. This opetion is useful for
running tests without triggering the viewer.
Returns:
viewer = Napari viewer object
:param img: numpy.ndarray
:param classes: list
:param size: int
:param shape: str
:param importdata: dict
:param show: str
:return viewer: napari viewer object
"""
showcall = show
viewer = napari_open(img, show=showcall)

symbols = ['arrow', 'clobber', 'cross', 'diamond', 'disc', 'hbar', 'ring',
'square', 'star', 'tailed_arrow', 'triangle_down',
'triangle_up', 'vbar']
color = ["aliceblue", "antiquewhite", "aqua", "aquamarine", "azure",
"beige", "bisque", "black", "blanchedalmond", "blue",
"blueviolet", "brown", "burlywood", "cadetblue",
"chartreuse", "chocolate", "coral", "cornflowerblue",
"cornsilk", "crimson", "cyan", "darkblue", "darkcyan",
"darkgoldenrod", "darkgray", "darkgreen", "darkkhaki",
"darkmagenta", "darkolivegreen", "darkorange", "darkorchid",
"darkred", "darksalmon", "darkseagreen", "darkslateblue",
"darkslategray", "darkturquoise", "darkviolet", "deeppink",
"deepskyblue", "dimgray", "dodgerblue", "firebrick",
"floralwhite", "forestgreen", "fuchsia", "gainsboro",
"ghostwhite", "gold", "goldenrod", "gray", "green",
"greenyellow", "honeydew", "hotpink", "indianred",
"indigo", "ivory", "khaki", "lavender", "lavenderblush",
"lawngreen", "lemonchiffon", "lightblue", "lightcoral",
"lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen",
"lightpink", "lightsalmon", "lightseagreen", "lightskyblue",
"lightslategray", "lightsteelblue", "lightyellow", "lime",
"limegreen", "linen", "magenta", "maroon", "mediumaquamarine",
"mediumblue", "mediumorchid", "mediumpurple", "mediumseagreen",
"mediumslateblue", "mediumspringgreen", "mediumturquoise",
"mediumvioletred", "midnightblue", "mintcream", "mistyrose",
"moccasin", "navajowhite", "navy", "oldlace", "olive",
"olivedrab", "orange", "orangered", "orchid", "palegoldenrod",
"palegreen", "paleturquoise", "palevioletred", "papayawhip",
"peachpuff", "peru", "pink", "plum", "powderblue", "purple",
"red", "rosybrown", "royalblue", "saddlebrown",
"salmon", "sandybrown", "seagreen", "seashell", "sienna",
"silver", "skyblue", "slateblue", "slategray", "snow",
"springgreen", "steelblue", "tan", "teal", "thistle", "tomato",
"turquoise", "violet", "wheat", "white", "whitesmoke",
"yellow", "yellowgreen"]

keys = napari_classes(viewer)

if classes is not False:
for x in classes:
if x not in keys:
viewer.add_points(np.array([]), name=x, symbol=shape,
edge_color=random.choice(color),
face_color=random.choice(color), size=size)
keys = napari_classes(viewer)

for x in classes:
viewer.add_points(np.array([]), name=x, symbol=random.choice(symbols),
face_color='white', size=10)
if importdata is not False:
importkeys = list(importdata.keys())
for key in importkeys:
if len(importdata[key]) != 0:
if key in keys:
viewer.layers[key].add(importdata[key])
else:
viewer.add_points(importdata[key], name=key, symbol=shape,
edge_color=random.choice(color),
face_color=random.choice(color),
size=size)

return viewer
13 changes: 8 additions & 5 deletions tests/test_napari_label_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ def test_napari_label_classes_gray(test_data):
"""Test for PlantCV.Annotate"""
# Read in test data
img, _, _ = readimage(test_data.kmeans_seed_gray_img)
viewer = napari_label_classes(img, ['seed'], show=False)
coor = [(25, 25)]
viewer.add_points(np.array(coor), symbol="o", name='background',
face_color="red", size=1)
data = {'total': [(25, 25)], 'background': [(50, 50)]}
viewer = napari_label_classes(img, ['total'], size=5, importdata=data,
show=False)
coor = [(50, 25)]
viewer.add_points(np.array(coor), symbol="o", name='coor',
face_color="red", size=5)

assert len(viewer.layers['total'].data) == 1

assert len(viewer.layers['background'].data) == 1
viewer.close()

0 comments on commit 888e3db

Please sign in to comment.