Skip to content

Commit

Permalink
Merge branch 'main' into correct_mask_method
Browse files Browse the repository at this point in the history
  • Loading branch information
HaleySchuhl authored Sep 12, 2024
2 parents f9654ee + 888e3db commit 6852187
Show file tree
Hide file tree
Showing 19 changed files with 367 additions and 49 deletions.
2 changes: 1 addition & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,6 @@ See [this page](https://plantcv.readthedocs.io/en/latest/pr_review_process/) for
- [ ] Test coverage remains 100%
- [ ] Documentation tested
- [ ] New documentation pages added to `plantcv/mkdocs.yml`
- [ ] Changes to function input/output signatures added to `updating.md`
- [ ] Changes to function input/output signatures added to `changelog.md`
- [ ] Code reviewed
- [ ] PR approved
32 changes: 32 additions & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,35 @@
## Changelog

All notable changes to this project will be documented below.

#### annotate.get_centroids

* v0.1dev: coords_list = **annotate.get_centroids**(*bin_img*)

#### annotate.napari_classes

* v0.1dev: class_list = **annotate.napari_classes**(*viewer*)

#### annotate.napari_join_labels

* v0.1dev: relabeled_mask, mask_dict = **annotate.napari_join_labels**(*img, viewer*)

#### annotate.napari_label_classes

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

#### annotate.napari_open

* v0.1dev: viewer = **annotate.napari_open**(*img, mode = 'native', show=True*)

#### annotate.napari_read_coor

* v0.1dev: data = **annotate.napari_read_coor**(*coor, dataformat='yx'*)

#### annotate.napari_save_coor

* v0.1dev: datadict = **annotate.napari_save_coor**(*viewer, filepath*)

#### annotate.Points

* v0.1dev: viewer = **annotate.Points**(*img, figsize=(12,6), label="dafault"*)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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
9 changes: 5 additions & 4 deletions docs/napari_open.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
## Open Image with Napari

Open image data (e.g. RGB, gray, hyperspectral) with an interactive Napari viewer. If a gray image is opened, the image will be pseudocolored for better visualization.
Open image data (e.g. RGB, gray, hyperspectral) with an interactive Napari viewer. Labeled masks may be colorized for better visualization.

**plantcv.annotate.napari_open**(*img, show=True*)
**plantcv.annotate.napari_open**(*img, mode='native', 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)
- img - image data (compatible with gray, RGB, and hyperspectral data. If data is hyperspecral it should be the array e.g. `hyperspectral.array_data`)
- mode - 'native' or 'colorize'. If 'colorized' is selected gray images will be colorized.
- show - if show = True, viewer is launched. False setting is useful for test purposes.

- **Context:**
Expand All @@ -24,7 +25,7 @@ import plantcv.annotate as pcvan
# Create an instance of the Points class
img, path, name = pcv.readimage("./grayimg.png")

viewer = pcvan.napari_open(img=img)
viewer = pcvan.napari_open(img=img, mode='colorize')

# Should open interactive napari viewer

Expand Down
30 changes: 30 additions & 0 deletions docs/napari_read_coor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
## Read point data into Napari Format

Save Points Labeled in Napari to a File

**plantcv.napari_read_coor**(*coor, dataformat = 'yx'*)

**returns** dictionary of points labeled by class

- **Parameters:**
- coor - dictionary object of coordinates, or a path to json datafile with dictionary of point coordinates
- dataformat - either 'yx' or 'xy', Napari takes data as y,x format. If data is 'xy' data is converted from x,y to y,x

- **Context:**
- Import previously labeled points, or points from other functions (e.g. [`pcvan.napari_read_coor`](napari_read_coor.md))

- **Example use:**
- Below


```python
import plantcv.plantcv as pcv
import plantcv.annotate as pcvan

# read in data

data = pcvan.napari_read_points(coor ='coor.json', dataformat = 'xy')

```

**Source Code:** [Here](https://github.com/danforthcenter/plantcv-annotate/blob/main/plantcv/annotate/napari_read_coor.py)
39 changes: 39 additions & 0 deletions docs/napari_save_coor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
## Save Napari Labels to File

Save Points Labeled in Napari to a File

**plantcv.annotate.napari_save_coor**(*viewer, filepath*)

**returns** dictionary of points labeled by class

- **Parameters:**
- viewer - Napari Viewer Object
- Filepath - File to save data. If the file exits an extension will be added.

- **Context:**
- Save points labeled in Napari to a file to checkpoint annotation progress or reuse.

- **Example use:**
- Save points labeled to a file


```python
import plantcv.plantcv as pcv
import plantcv.annotate as pcvan

# Create an instance of the Points class
img, path, name = pcv.readimage("./grayimg.png")
# Should open interactive napari viewer
viewer = pcvan.napari_label_classes(img=img, classes=['background', 'wing','seed'])

dictobj = pcvan.napari_save_coor(viewer, 'testdata.txt')

```

![Screenshot](img/documentation_images/napari_label_classes/napari_label_classes.png)

![Screenshot](img/documentation_images/napari_save_coor/napari_save.png)



**Source Code:** [Here](https://github.com/danforthcenter/plantcv-annotate/blob/main/plantcv/annotate/napari_save_coor.py)
2 changes: 2 additions & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ nav:
- Napari Join: napari_join_labels.md
- Napari Label: napari_label_classes.md
- Napari Open: napari_open.md
- Napari Read Coor: napari_read_coor.md
- Napari Save Coor: napari_save_coor.md
- Points: Points.md
- Get Centroids: get_centroids.md
markdown_extensions:
Expand Down
8 changes: 6 additions & 2 deletions plantcv/annotate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
from plantcv.annotate.napari_open import napari_open
from plantcv.annotate.napari_label_classes import napari_label_classes
from plantcv.annotate.napari_join_labels import napari_join_labels
from plantcv.annotate.napari_save_coor import napari_save_coor
from plantcv.annotate.napari_read_coor import napari_read_coor

# Auto versioning
__version__ = version("plantcv-annotate")
Expand All @@ -15,5 +17,7 @@
"napari_classes",
"napari_open",
"napari_label_classes",
"napari_join_labels"
]
"napari_join_labels",
"napari_save_coor",
"napari_read_coor"
]
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
29 changes: 15 additions & 14 deletions plantcv/annotate/napari_open.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,26 @@
import napari


def napari_open(img, show=True):
"""
open img in napari
def napari_open(img, mode='native', show=True):
"""Open an image with a napari interactive viewer
Inputs:
img = img (grayimg, rgbimg, or hyperspectral image array data e.g.
hyperspectraldata.array_data)
show = if show is True the viewer is launched. This option is useful for
Parameters
----------
img : numpy.ndarray
Image to be opened, img can be gray, rgb, or multispectral
mode: str
Viewing mode, either 'native' (default) or 'colorize'
show: bool
if show is True the viewer is launched. This option is useful for
running tests without triggering the viewer.
Returns:
viewer = napari viewer object
:param img: numpy.ndarray
:return viewer: napari viewer object
Returns
-------
napari.viewer.Viewer
Napari viewer object
"""
shape = np.shape(img)
if len(shape) == 2:
if len(shape) == 2 and mode == 'colorize':
colorful = label2rgb(img)
img = (255*colorful).astype(np.uint8)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
Expand Down
Loading

0 comments on commit 6852187

Please sign in to comment.