Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add .correct_mask method #27

Open
wants to merge 166 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 154 commits
Commits
Show all changes
166 commits
Select commit Hold shift + click to select a range
66c7e3e
add correct_mask simplest
HaleySchuhl May 14, 2024
0eb7698
Split up "coords" attribute into two classes, normal vs unrecovered
HaleySchuhl May 14, 2024
7978e75
indent fix
HaleySchuhl May 14, 2024
611a0ff
change debug import
HaleySchuhl May 14, 2024
018ec54
swap x.y for floodfill call
HaleySchuhl May 14, 2024
15a7d27
adding test data
HaleySchuhl May 14, 2024
01ed595
Update conftest.py
HaleySchuhl May 14, 2024
2bb3a25
add correct test
HaleySchuhl May 14, 2024
06ac93f
Update test_annotate_points.py
HaleySchuhl May 14, 2024
2c513ed
deepsource issues
HaleySchuhl May 14, 2024
d8d2f54
only add "unrecovered" class to annotations when there are some for t…
HaleySchuhl May 14, 2024
57bb762
another indent and update comments
HaleySchuhl May 14, 2024
531be5a
update print statements
HaleySchuhl May 14, 2024
a7976b1
update the way objects are removed
HaleySchuhl May 14, 2024
3cddb7c
remove unnecessary param
HaleySchuhl May 14, 2024
bdb9607
also remove coords from tests
HaleySchuhl May 14, 2024
20b192f
deepsource fixes
HaleySchuhl May 14, 2024
af0e28b
add coord trying to hit missed lines of coverage
HaleySchuhl May 15, 2024
c92a88d
delete _remove_points
HaleySchuhl May 15, 2024
d0be7f1
add another click to test trying to inc coverage
HaleySchuhl May 15, 2024
88bc4d6
Create points_correct_mask.md
HaleySchuhl May 15, 2024
aaa9886
add more tot point_correct_mask.md
HaleySchuhl May 15, 2024
68ae127
Update Points.md
HaleySchuhl May 15, 2024
6822957
add doc image for mask correction
HaleySchuhl May 15, 2024
448f2e4
include screenshots in points_correct_mask.md
HaleySchuhl May 15, 2024
6ee2fd7
stop casting to 0/1 bin and keep 0/255
HaleySchuhl May 15, 2024
e6f26bf
Update mkdocs.yml
HaleySchuhl May 15, 2024
ebfba74
remove coord trying to hit line 211
HaleySchuhl May 15, 2024
c97669e
update test for last line hit
HaleySchuhl May 16, 2024
65f58de
remove print statement
HaleySchuhl May 16, 2024
7c86118
Merge branch 'main' into correct_mask_method
HaleySchuhl May 16, 2024
b3ae7f7
update test based on changes to main
HaleySchuhl May 16, 2024
15f3b5a
add timer, temp
HaleySchuhl May 16, 2024
9af32ec
add shorter correction method
HaleySchuhl May 22, 2024
bbf2a05
remove extra bin_img from correct_mask
HaleySchuhl May 22, 2024
8d96d84
update inputs for unit test
HaleySchuhl May 22, 2024
ca3b2d3
add class labels to running list and return them
HaleySchuhl May 23, 2024
629276b
update ID numbering for labels and labeled mask
HaleySchuhl May 23, 2024
e18a21f
add logic to check for multiple annotations in one region of the labe…
HaleySchuhl May 23, 2024
b370e68
remove some of the troubleshooting code
HaleySchuhl May 23, 2024
615c0f8
Update classes.py
HaleySchuhl Jun 4, 2024
1e7e890
capture second output in test
HaleySchuhl Jun 26, 2024
1d8d83f
remove timer and capture unused var
HaleySchuhl Jun 26, 2024
0ef5b9f
remove whitespace and unused import
HaleySchuhl Jun 26, 2024
350fe12
remove point annotation trying to hit last line of code w test
HaleySchuhl Jun 27, 2024
9680acd
test coverage attempt, replace coords?
HaleySchuhl Jun 27, 2024
acc18d3
test logic reversed
HaleySchuhl Jun 27, 2024
000504a
correct_mask returns a labeled mask
HaleySchuhl Jul 15, 2024
ccc4f8e
add pixel annotation to labeled mask when unresolved object
HaleySchuhl Jul 15, 2024
54344ce
add pseudocode placeholder that will get removed soon
HaleySchuhl Jul 15, 2024
458f408
deepsource edits but includes pseudo-code for complexity
HaleySchuhl Jul 15, 2024
eff9642
update if statement, only need to check overlap with one mask now
HaleySchuhl Jul 16, 2024
773e6fb
move what can be moved outside the "else" statement
HaleySchuhl Jul 16, 2024
bec7bbb
update ID in labeled for unrecovered annotations
HaleySchuhl Jul 16, 2024
95670c0
sort labels based on annotation ID
HaleySchuhl Jul 16, 2024
2f2ac04
sort command within function, otherwise return is null
HaleySchuhl Jul 16, 2024
cff1cf3
remove print statement for unique IDs
HaleySchuhl Jul 16, 2024
698717e
delete whitespace
HaleySchuhl Jul 17, 2024
fed91c9
NEW APPROACH - only mask filtering
HaleySchuhl Jul 17, 2024
b3876ce
remove whitespace
HaleySchuhl Jul 17, 2024
0668fd2
move correct_mask documentation to Points
HaleySchuhl Jul 18, 2024
c8db7d0
swap out doc images for clearer examples
HaleySchuhl Jul 18, 2024
a5abaf2
replace doc images in Points.md for correct_mask example
HaleySchuhl Jul 18, 2024
8e2fe29
resize doc images and remove the unused old one
HaleySchuhl Jul 18, 2024
0b23264
update Points.md more clarity and fix order
HaleySchuhl Jul 18, 2024
1f8d72b
Delete points_correct_mask.md
HaleySchuhl Jul 18, 2024
e3ad31d
add "num" objects return
HaleySchuhl Jul 18, 2024
4a02b57
add num to function
HaleySchuhl Jul 18, 2024
10b9bd4
catch the additional return in tests
HaleySchuhl Jul 18, 2024
17f6b98
Update annotated_stomata.png
HaleySchuhl Jul 18, 2024
fdeca13
show corrected annotations also
HaleySchuhl Jul 18, 2024
1f68361
remove extra doc from mkdocs
HaleySchuhl Jul 18, 2024
a90adc9
document method returns
HaleySchuhl Jul 18, 2024
26f3571
begin adding debug img
HaleySchuhl Jul 22, 2024
be02d7f
return debug img for now
HaleySchuhl Jul 23, 2024
1a3e80f
add ID labels at the end instead and draw contours onto debug img
HaleySchuhl Jul 23, 2024
d890e3c
rearrange debug steps, add removed shadows pre colorize
HaleySchuhl Jul 23, 2024
e3eec47
Update classes.py
HaleySchuhl Jul 23, 2024
73485fb
i+1 so skipping 0 pixel not plotted
HaleySchuhl Jul 23, 2024
644f343
unresolved debug thickness bug RESOLVED
HaleySchuhl Jul 25, 2024
96ff8a8
quit returning debug image
HaleySchuhl Jul 25, 2024
99d2282
remove "id" part of text label
HaleySchuhl Jul 26, 2024
af86fcc
update docstrings for correct-mask function
HaleySchuhl Jul 29, 2024
a49b9bf
split up context documentation and clarify
HaleySchuhl Jul 29, 2024
dd14d7d
replace doc images with new debug
HaleySchuhl Jul 29, 2024
d2bdce4
remove colorize step from code example
HaleySchuhl Jul 29, 2024
0f3efb2
deepsource fixes and minor comment updates in correct_mask
HaleySchuhl Jul 29, 2024
031de70
update labeled mask datatype to uint32
HaleySchuhl Jul 29, 2024
60eb086
update method of drawing on final mask, add object count logic
HaleySchuhl Jul 31, 2024
bf4f0b5
datatype BUGFIX
HaleySchuhl Jul 31, 2024
f95b5f6
nest warning statement in verbose "if"
HaleySchuhl Jul 31, 2024
b884364
update text ID labels
HaleySchuhl Jul 31, 2024
8cbd373
double annotated obj handling start
HaleySchuhl Jul 31, 2024
962be38
adding label list and combining unique labels
HaleySchuhl Jul 31, 2024
ea81d26
return analysis_labels and append in unresolved case too
HaleySchuhl Jul 31, 2024
a94be11
num -1 since background
HaleySchuhl Jul 31, 2024
8f3324c
update duplication for clumps greater than 2
HaleySchuhl Jul 31, 2024
309840b
change duplicate annotated debug objs
HaleySchuhl Jul 31, 2024
7457c7a
remove duplicated things and replace with coord
HaleySchuhl Aug 1, 2024
4949390
change where ID labels are getting added
HaleySchuhl Aug 1, 2024
5462ce1
almost one to one objects and labels
HaleySchuhl Aug 1, 2024
13a440c
comment out labeled mask plot
HaleySchuhl Aug 2, 2024
6933dde
remove commented code, and check for annotation count
HaleySchuhl Aug 2, 2024
b331517
extract class labels for duplicate annotations
HaleySchuhl Aug 5, 2024
53dfcec
check for duplication in class labels
HaleySchuhl Aug 5, 2024
9f074ee
add logic to check if class labels unique
HaleySchuhl Aug 5, 2024
6ae776a
increment count with each annotation pixel drawn
HaleySchuhl Aug 5, 2024
a628152
concat a flattened list of unique class labels
HaleySchuhl Aug 5, 2024
c3217c3
indent so that dupes "handled" only once
HaleySchuhl Aug 6, 2024
3f44f6f
separate the filtering helper function out
HaleySchuhl Aug 13, 2024
c4de635
separate out _create_pts_mask function
HaleySchuhl Aug 13, 2024
17bb388
filtering helper as function rather than method
HaleySchuhl Aug 13, 2024
c1cf979
reference _create_pts_mask as method
HaleySchuhl Aug 13, 2024
fad6b6e
make labelnames an input for create_pts_mask helper
HaleySchuhl Aug 13, 2024
23e1d13
capture the adtl return to tests
HaleySchuhl Aug 13, 2024
04fc6f7
simplify for loop
HaleySchuhl Aug 13, 2024
5f63324
simplfy for loop and add _draw_unresolved_object
HaleySchuhl Aug 13, 2024
fadf20e
add _draw_resolved
HaleySchuhl Aug 13, 2024
e132146
utilize _draw_resolved and remove some debug duplicates
HaleySchuhl Aug 13, 2024
fbf9fc2
Stop incrementing object ID at the loop and dupe check
HaleySchuhl Aug 13, 2024
daf2e8e
unique class double annotate case, also check for previous handling
HaleySchuhl Aug 13, 2024
a58e67d
new helper _draw_ghost_of_duplicates_removed
HaleySchuhl Aug 15, 2024
2533ac1
always append mask_pixel_value
HaleySchuhl Aug 15, 2024
e2ec3ae
remove print statements and grab entire class labels
HaleySchuhl Aug 15, 2024
7b9bf97
check if object already "handled" in just the upstream place
HaleySchuhl Aug 15, 2024
da974e0
change line_thickness since dilate will err if ksize=1
HaleySchuhl Aug 15, 2024
92f7ebc
added the inc in thickness at the wrong spot
HaleySchuhl Aug 15, 2024
797482d
update logic for the most complex cases and add print statemtnt
HaleySchuhl Aug 15, 2024
7d46a2d
add _add_debug_id and utilize
HaleySchuhl Aug 16, 2024
158a721
add complex case to final mask and labels
HaleySchuhl Aug 16, 2024
ecd777d
Update Points.md
HaleySchuhl Aug 16, 2024
0deafea
minor clarification to docs for Points classes
HaleySchuhl Aug 16, 2024
d655195
add dupes for more code coverage
HaleySchuhl Aug 16, 2024
aa6eec4
remove unused var
HaleySchuhl Aug 16, 2024
3c626e1
using identity comparison with singleton
HaleySchuhl Aug 16, 2024
95d6c95
more deepsource things
HaleySchuhl Aug 16, 2024
cd63506
change the dupe list in tests
HaleySchuhl Aug 19, 2024
b816526
update test coord for more testing coverage
HaleySchuhl Aug 19, 2024
22787ed
x,y, order for import list switch
HaleySchuhl Aug 19, 2024
c8d12be
update coords to handle all if statements?
HaleySchuhl Aug 19, 2024
fe9764c
deepsource things
HaleySchuhl Aug 19, 2024
3b8b41e
add "unresolvable" point for unit test
HaleySchuhl Aug 19, 2024
acb458b
Bad indentation detected PYL-W0311
HaleySchuhl Aug 19, 2024
c48650b
update warning to fstring
HaleySchuhl Aug 19, 2024
3074741
other fstring
HaleySchuhl Aug 19, 2024
3b0fd0f
update correct_mask method to accept labeled mask
HaleySchuhl Aug 20, 2024
07a61ed
add a test for the labeled mask case
HaleySchuhl Aug 20, 2024
d1aea5d
update _remove_unannotated_objects to be the place where bin vs label…
HaleySchuhl Aug 20, 2024
750f8bd
update Points.md with new param name
HaleySchuhl Aug 20, 2024
679061c
deepsource stuff
HaleySchuhl Aug 20, 2024
532c91b
stop specifying dtype in np.concat step because deepsource complaint
HaleySchuhl Aug 20, 2024
f9654ee
remove whitespace
HaleySchuhl Aug 20, 2024
6852187
Merge branch 'main' into correct_mask_method
HaleySchuhl Sep 12, 2024
52f6aa2
x,y order in import_list revert
HaleySchuhl Sep 17, 2024
906367f
Merge branch 'main' into correct_mask_method
HaleySchuhl Sep 17, 2024
c783cff
xy order fix for unit test coverage
HaleySchuhl Sep 17, 2024
91d996a
replace print statements with pcv.warn
HaleySchuhl Sep 18, 2024
5dd79e3
another instance of pcv.warn & import placement
HaleySchuhl Sep 18, 2024
a62ea63
indent fix
HaleySchuhl Sep 18, 2024
34d6ceb
change dictionary iteration logic to avoid nested for loops
HaleySchuhl Sep 18, 2024
a980fe5
different approach to dec complexity?
HaleySchuhl Sep 18, 2024
08e14bc
simplify sum syntax
HaleySchuhl Sep 18, 2024
e757806
refactor looping method in correct_mask
HaleySchuhl Sep 18, 2024
05a6756
fix x & y order given new looping method
HaleySchuhl Sep 18, 2024
70474fc
whitespace and indent fixes
HaleySchuhl Sep 18, 2024
20f968d
Merge branch 'main' into correct_mask_method
HaleySchuhl Sep 20, 2024
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
80 changes: 73 additions & 7 deletions docs/Points.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## Interactive Point Annotation Tool

Using [Jupyter Notebooks](https://plantcv.readthedocs.io/en/stable/jupyter/) it is possible to interactively click to collect coordinates from an image, which can be used in various downstream applications. Left click on the image to collect a point. Right click removes the
Using [Jupyter Notebooks](https://plantcv.readthedocs.io/en/stable/jupyter/) it is possible to interactively click on an image to collect coordinates, which can be used in various downstream applications. Left click on the image to collect a point. Right click removes the
closest collected point.

**plantcv.annotate.Points**(*img, figsize=(12,6), label="dafault"*)
Expand All @@ -13,9 +13,9 @@ closest collected point.
- label - The current label (default = "default")

- **Attributes:**
- coords - dictionary of all coordinates per group label
- coords - dictionary of all coordinates per sample label
- events - includes right and left click events
- count - dictionary that save the counts of different groups (labels)
- count - dictionary that save the counts of different groups (sample_labels)
- label - the current label
- sample_labels - list of all sample labels, one to one with coordinates collected
- view_all - flag indicating whether or not to view all labels
Expand All @@ -25,18 +25,18 @@ closest collected point.

- **Context:**
- Used to define a list of coordinates of interest.
-
- Can be helpful to ground truth counting algorithms, and exported coordinates could be used in other image analysis workflows.
- **Example use:**
- (pcv.roi.multi)
- (pcv.roi.custom)
- [pcv.roi.multi](https://plantcv.readthedocs.io/en/stable/roi_multi/)
- Shown below [pcv.roi.custom](https://plantcv.readthedocs.io/en/stable/roi_custom/)


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

# Create an instance of the Points class
marker = an.Points(img=img, figsize=(12,6))
marker = an.Points(img=img, figsize=(12,6), label='default')

# Click on the plotted image to collect coordinates

Expand All @@ -45,5 +45,71 @@ roi = pcv.roi.custom(img=img, vertices=marker.coords['default'])

```

## Methods
### Correct a Mask using Point Annotations

Using [Jupyter Notebooks](https://plantcv.readthedocs.io/en/stable/jupyter/) it is possible to interactively click to collect coordinates from an image, then use these coordinate to remove and recover objects from a binary mask.

**plantcv.annotate.Points.correct_mask**(*mask*)

**returns** corrected_mask, lbls, num

- **Parameters:**
- mask - binary or labeled mask image, filtered mask image with selected objects, or the output from [`plantcv.watershed`](https://plantcv.readthedocs.io/en/stable/watershed/)

- **Returns:**
- corrected_mask - A labeled mask with non-annotated objects filtered out, and unresolvable annotations marked with a labeled pixel.
- lbls - A list of class labels ordered the same as the corrected mask object IDs
- num - The number of unique objects in the `corrected_mask`.

- **Context:**
- Filters objects from the `bin_mask` if they do not overlap with an annotation in the `Points` class instance.
- Adds a labeled pixel to the corrected mask if an object cannot be resolved for any annotations (false negatives can be counted but cannot have their size measured downstream).
- Returns the number of unique objects in the `corrected_mask` which is useful for downstream analysis.
- Debug image is a colorized representation of the labeled mask. The "unresolved" annotation replicates are plotted with a radius of `pcv.params.line_thickness` (default = 5).
- Hint: set `pcv.params.text_size=0` to skip ID labeling and instead only plot the annotation coordinate.

- **Example use:**
- Remove noise from a microscopy image that is otherwise difficult to filter out with traditional computer vision
techniques, and recover stomata that were filtered out during mask cleaning.

**bin_img**

![Screenshot](img/documentation_images/points_correct_mask/bin_mask.png)

**Original Image with "auto-detected" Annotations**

![Screenshot](img/documentation_images/points_correct_mask/auto_annotated_stomata.png)

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

# Create an instance of the Points class
img, path, name = pcv.readimage("stomata.tif")

# Segmentation & mask clean up, get_centroids steps here

# Create an instance of the Points class & click on stomata
marker = pcvan.Points(img=img, figsize=(12,6))
marker.import_list(coords=centroid_coords, label="stomata")

# Filter the binary mask based on corrected annotations
corrected_mask, lbls, num = marker.correct_mask(mask=bin_mask)

# Analysis steps here
size_img = pcv.analyze.size(img=img, labeled_mask=corrected_mask, n_labels=num, label=lbls)
```
**Annotations After Human Corrections**

![Screenshot](img/documentation_images/points_correct_mask/annotated_stomata.png)

**Corrected & Labeled Mask**

![Screenshot](img/documentation_images/points_correct_mask/colorized_label_img.png)

**[Size](https://plantcv.readthedocs.io/en/stable/analyze_size/) Analysis Image**

![Screenshot](img/documentation_images/points_correct_mask/shape_img.png)

**Source Code:** [Here](https://github.com/danforthcenter/plantcv-annotate/blob/main/plantcv/annoate/classes.py)
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading