Skip to content

Commit 449e025

Browse files
Merge pull request #97 from computational-cell-analytics/clean-gui
Add gui element to clear annotations
2 parents c307ccf + d8116c0 commit 449e025

File tree

4 files changed

+58
-59
lines changed

4 files changed

+58
-59
lines changed

micro_sam/sam_annotator/annotator_2d.py

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -11,27 +11,23 @@
1111
from .. import util
1212
from .. import instance_segmentation
1313
from ..visualization import project_embeddings_for_visualization
14+
from . import util as vutil
1415
from .gui_utils import show_wrong_file_warning
15-
from .util import (
16-
clear_all_prompts, commit_segmentation_widget, create_prompt_menu,
17-
prompt_layer_to_boxes, prompt_layer_to_points, prompt_segmentation, toggle_label, LABEL_COLOR_CYCLE,
18-
_initialize_parser,
19-
)
2016

2117

2218
@magicgui(call_button="Segment Object [S]")
2319
def segment_wigdet(v: Viewer):
2420
# get the current box and point prompts
25-
boxes = prompt_layer_to_boxes(v.layers["box_prompts"])
26-
points, labels = prompt_layer_to_points(v.layers["prompts"])
21+
boxes = vutil.prompt_layer_to_boxes(v.layers["box_prompts"])
22+
points, labels = vutil.prompt_layer_to_points(v.layers["prompts"])
2723

2824
shape = v.layers["current_object"].data.shape
2925
if IMAGE_EMBEDDINGS["original_size"] is None: # tiled prediction
30-
seg = prompt_segmentation(
26+
seg = vutil.prompt_segmentation(
3127
PREDICTOR, points, labels, boxes, shape, image_embeddings=IMAGE_EMBEDDINGS, multiple_box_prompts=True
3228
)
3329
else: # normal prediction and we have set the precomputed embeddings already
34-
seg = prompt_segmentation(PREDICTOR, points, labels, boxes, shape, multiple_box_prompts=True)
30+
seg = vutil.prompt_segmentation(PREDICTOR, points, labels, boxes, shape, multiple_box_prompts=True)
3531

3632
# no prompts were given or prompts were invalid, skip segmentation
3733
if seg is None:
@@ -141,7 +137,7 @@ def _initialize_viewer(raw, segmentation_result, tile_shape, show_embeddings):
141137
name="prompts",
142138
properties={"label": labels},
143139
edge_color="label",
144-
edge_color_cycle=LABEL_COLOR_CYCLE,
140+
edge_color_cycle=vutil.LABEL_COLOR_CYCLE,
145141
symbol="o",
146142
face_color="transparent",
147143
edge_width=0.5,
@@ -158,14 +154,15 @@ def _initialize_viewer(raw, segmentation_result, tile_shape, show_embeddings):
158154
# add the widgets
159155
#
160156

161-
prompt_widget = create_prompt_menu(prompts, labels)
157+
prompt_widget = vutil.create_prompt_menu(prompts, labels)
162158
v.window.add_dock_widget(prompt_widget)
163159

164160
# (optional) auto-segmentation functionality
165161
v.window.add_dock_widget(autosegment_widget)
166162

167163
v.window.add_dock_widget(segment_wigdet)
168-
v.window.add_dock_widget(commit_segmentation_widget)
164+
v.window.add_dock_widget(vutil.commit_segmentation_widget)
165+
v.window.add_dock_widget(vutil.clear_widget)
169166

170167
#
171168
# key bindings
@@ -177,15 +174,15 @@ def _segmet(v):
177174

178175
@v.bind_key("c")
179176
def _commit(v):
180-
commit_segmentation_widget(v)
177+
vutil.commit_segmentation_widget(v)
181178

182179
@v.bind_key("t")
183180
def _toggle_label(event=None):
184-
toggle_label(prompts)
181+
vutil.toggle_label(prompts)
185182

186183
@v.bind_key("Shift-C")
187184
def clear_prompts(v):
188-
clear_all_prompts(v)
185+
vutil.clear_annotations(v)
189186

190187
return v
191188

@@ -246,7 +243,7 @@ def annotator_2d(
246243
#
247244
# start the viewer
248245
#
249-
clear_all_prompts(v)
246+
vutil.clear_annotations(v, clear_segmentations=False)
250247

251248
if return_viewer:
252249
return v
@@ -255,7 +252,7 @@ def annotator_2d(
255252

256253

257254
def main():
258-
parser = _initialize_parser(description="Run interactive segmentation for an image.")
255+
parser = vutil._initialize_parser(description="Run interactive segmentation for an image.")
259256
args = parser.parse_args()
260257
raw = util.load_image_data(args.input, key=args.key)
261258

micro_sam/sam_annotator/annotator_3d.py

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,8 @@
1111
from .. import util
1212
from ..prompt_based_segmentation import segment_from_mask
1313
from ..visualization import project_embeddings_for_visualization
14+
from . import util as vutil
1415
from .gui_utils import show_wrong_file_warning
15-
from .util import (
16-
clear_all_prompts, commit_segmentation_widget, create_prompt_menu,
17-
prompt_layer_to_boxes, prompt_layer_to_points, prompt_segmentation,
18-
segment_slices_with_prompts, toggle_label, LABEL_COLOR_CYCLE,
19-
_initialize_parser
20-
)
2116

2217

2318
#
@@ -133,16 +128,16 @@ def segment_slice_wigdet(v: Viewer):
133128
position = v.cursor.position
134129
z = int(position[0])
135130

136-
point_prompts = prompt_layer_to_points(v.layers["prompts"], z)
131+
point_prompts = vutil.prompt_layer_to_points(v.layers["prompts"], z)
137132
# this is a stop prompt, we do nothing
138133
if not point_prompts:
139134
return
140135

141-
boxes = prompt_layer_to_boxes(v.layers["box_prompts"], z)
136+
boxes = vutil.prompt_layer_to_boxes(v.layers["box_prompts"], z)
142137
points, labels = point_prompts
143138

144139
shape = v.layers["current_object"].data.shape[1:]
145-
seg = prompt_segmentation(
140+
seg = vutil.prompt_segmentation(
146141
PREDICTOR, points, labels, boxes, shape, multiple_box_prompts=False,
147142
image_embeddings=IMAGE_EMBEDDINGS, i=z
148143
)
@@ -175,7 +170,7 @@ def segment_volume_widget(
175170

176171
with progress(total=shape[0]) as progress_bar:
177172

178-
seg, slices, stop_lower, stop_upper = segment_slices_with_prompts(
173+
seg, slices, stop_lower, stop_upper = vutil.segment_slices_with_prompts(
179174
PREDICTOR, v.layers["prompts"], v.layers["box_prompts"], IMAGE_EMBEDDINGS, shape, progress_bar=progress_bar,
180175
)
181176

@@ -235,7 +230,7 @@ def annotator_3d(
235230
name="prompts",
236231
properties={"label": labels},
237232
edge_color="label",
238-
edge_color_cycle=LABEL_COLOR_CYCLE,
233+
edge_color_cycle=vutil.LABEL_COLOR_CYCLE,
239234
symbol="o",
240235
face_color="transparent",
241236
edge_width=0.5,
@@ -254,13 +249,14 @@ def annotator_3d(
254249

255250
# TODO add (optional) auto-segmentation functionality
256251

257-
prompt_widget = create_prompt_menu(prompts, labels)
252+
prompt_widget = vutil.create_prompt_menu(prompts, labels)
258253
v.window.add_dock_widget(prompt_widget)
259254

260255
v.window.add_dock_widget(segment_slice_wigdet)
261256

262257
v.window.add_dock_widget(segment_volume_widget)
263-
v.window.add_dock_widget(commit_segmentation_widget)
258+
v.window.add_dock_widget(vutil.commit_segmentation_widget)
259+
v.window.add_dock_widget(vutil.clear_widget)
264260

265261
#
266262
# key bindings
@@ -276,30 +272,30 @@ def _seg_volume(v):
276272

277273
@v.bind_key("c")
278274
def _commit(v):
279-
commit_segmentation_widget(v)
275+
vutil.commit_segmentation_widget(v)
280276

281277
@v.bind_key("t")
282278
def _toggle_label(event=None):
283-
toggle_label(prompts)
279+
vutil.toggle_label(prompts)
284280

285281
@v.bind_key("Shift-C")
286282
def clear_prompts(v):
287-
clear_all_prompts(v)
283+
vutil.clear_annotations(v)
288284

289285
#
290286
# start the viewer
291287
#
292288

293289
# clear the initial points needed for workaround
294-
clear_prompts(v)
290+
vutil.clear_annotations(v, clear_segmentations=False)
295291

296292
if return_viewer:
297293
return v
298294
napari.run()
299295

300296

301297
def main():
302-
parser = _initialize_parser(description="Run interactive segmentation for an image volume.")
298+
parser = vutil._initialize_parser(description="Run interactive segmentation for an image volume.")
303299
args = parser.parse_args()
304300
raw = util.load_image_data(args.input, key=args.key)
305301

micro_sam/sam_annotator/annotator_tracking.py

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,9 @@
1515

1616
from .. import util
1717
from ..prompt_based_segmentation import segment_from_mask
18-
from .gui_utils import show_wrong_file_warning
19-
from .util import (
20-
create_prompt_menu, clear_all_prompts,
21-
prompt_layer_to_boxes, prompt_layer_to_points,
22-
prompt_layer_to_state, prompt_segmentation,
23-
segment_slices_with_prompts, toggle_label, LABEL_COLOR_CYCLE,
24-
_initialize_parser
25-
)
2618
from ..visualization import project_embeddings_for_visualization
19+
from . import util as vutil
20+
from .gui_utils import show_wrong_file_warning
2721

2822
# Cyan (track) and Magenta (division)
2923
STATE_COLOR_CYCLE = ["#00FFFF", "#FF00FF", ]
@@ -108,7 +102,7 @@ def _update_motion_model(seg, t, t0, motion_model):
108102
seg_t = seg[t]
109103
# currently using the box layer doesn't work for keeping track of the track state
110104
# track_state = prompt_layers_to_state(point_prompts, box_prompts, t)
111-
track_state = prompt_layer_to_state(point_prompts, t)
105+
track_state = vutil.prompt_layer_to_state(point_prompts, t)
112106

113107
# otherwise project the mask (under the motion model) and segment the next slice from the mask
114108
else:
@@ -189,16 +183,16 @@ def segment_frame_wigdet(v: Viewer):
189183
position = v.cursor.position
190184
t = int(position[0])
191185

192-
point_prompts = prompt_layer_to_points(v.layers["prompts"], t, track_id=CURRENT_TRACK_ID)
186+
point_prompts = vutil.prompt_layer_to_points(v.layers["prompts"], t, track_id=CURRENT_TRACK_ID)
193187
# this is a stop prompt, we do nothing
194188
if not point_prompts:
195189
return
196190

197-
boxes = prompt_layer_to_boxes(v.layers["box_prompts"], t, track_id=CURRENT_TRACK_ID)
191+
boxes = vutil.prompt_layer_to_boxes(v.layers["box_prompts"], t, track_id=CURRENT_TRACK_ID)
198192
points, labels = point_prompts
199193

200194
shape = v.layers["current_track"].data.shape[1:]
201-
seg = prompt_segmentation(
195+
seg = vutil.prompt_segmentation(
202196
PREDICTOR, points, labels, boxes, shape, multiple_box_prompts=False,
203197
image_embeddings=IMAGE_EMBEDDINGS, i=t
204198
)
@@ -230,7 +224,7 @@ def track_objet_widget(
230224

231225
with progress(total=shape[0]) as progress_bar:
232226
# step 1: segment all slices with prompts
233-
seg, slices, _, stop_upper = segment_slices_with_prompts(
227+
seg, slices, _, stop_upper = vutil.segment_slices_with_prompts(
234228
PREDICTOR, v.layers["prompts"], v.layers["box_prompts"], IMAGE_EMBEDDINGS, shape,
235229
progress_bar=progress_bar, track_id=CURRENT_TRACK_ID
236230
)
@@ -349,7 +343,7 @@ def commit_tracking_widget(v: Viewer, layer: str = "current_track"):
349343
v.layers[layer].data = np.zeros(shape, dtype="uint32")
350344
v.layers[layer].refresh()
351345

352-
clear_all_prompts(v)
346+
vutil.clear_annotations(v, clear_segmentations=False)
353347

354348

355349
def annotator_tracking(
@@ -409,7 +403,7 @@ def annotator_tracking(
409403
"track_id": ["1", "1"], # NOTE we use string to avoid pandas warnings...
410404
},
411405
edge_color="label",
412-
edge_color_cycle=LABEL_COLOR_CYCLE,
406+
edge_color_cycle=vutil.LABEL_COLOR_CYCLE,
413407
symbol="o",
414408
face_color="state",
415409
face_color_cycle=STATE_COLOR_CYCLE,
@@ -444,7 +438,7 @@ def annotator_tracking(
444438

445439
# TODO add (optional) auto-segmentation and tracking functionality
446440

447-
prompt_widget = create_prompt_menu(prompts, labels)
441+
prompt_widget = vutil.create_prompt_menu(prompts, labels)
448442
v.window.add_dock_widget(prompt_widget)
449443

450444
TRACKING_WIDGET = create_tracking_menu(prompts, box_prompts, state_labels, list(LINEAGE.keys()))
@@ -453,6 +447,7 @@ def annotator_tracking(
453447
v.window.add_dock_widget(segment_frame_wigdet)
454448
v.window.add_dock_widget(track_objet_widget)
455449
v.window.add_dock_widget(commit_tracking_widget)
450+
v.window.add_dock_widget(vutil.clear_widget)
456451

457452
#
458453
# key bindings
@@ -468,15 +463,15 @@ def _track_object(v):
468463

469464
@v.bind_key("t")
470465
def _toggle_label(event=None):
471-
toggle_label(prompts)
466+
vutil.toggle_label(prompts)
472467

473468
@v.bind_key("c")
474469
def _commit(v):
475470
commit_tracking_widget(v)
476471

477472
@v.bind_key("Shift-C")
478473
def clear_prompts(v):
479-
clear_all_prompts(v)
474+
vutil.clear_annotations(v)
480475

481476
#
482477
# start the viewer
@@ -486,15 +481,15 @@ def clear_prompts(v):
486481
v.dims.current_step = (0,) + tuple(sh // 2 for sh in raw.shape[1:])
487482

488483
# clear the initial points needed for workaround
489-
clear_prompts(v)
484+
vutil.clear_annotations(v, clear_segmentations=False)
490485

491486
if return_viewer:
492487
return v
493488
napari.run()
494489

495490

496491
def main():
497-
parser = _initialize_parser(
492+
parser = vutil._initialize_parser(
498493
description="Run interactive segmentation for an image volume.",
499494
with_segmentation_result=False,
500495
)

micro_sam/sam_annotator/util.py

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,25 @@
1212
LABEL_COLOR_CYCLE = ["#00FF00", "#FF0000"]
1313

1414

15-
# TODO: also clear the current segmentation or tracking
16-
# TODO: also add menu for it in the annotator
17-
def clear_all_prompts(v: Viewer) -> None:
15+
def clear_annotations(v: Viewer, clear_segmentations=True) -> None:
1816
v.layers["prompts"].data = []
1917
v.layers["prompts"].refresh()
2018
if "box_prompts" in v.layers:
2119
v.layers["box_prompts"].data = []
2220
v.layers["box_prompts"].refresh()
21+
if not clear_segmentations:
22+
return
23+
if "current_object" in v.layers:
24+
v.layers["current_object"].data = np.zeros(v.layers["current_object"].data.shape, dtype="uint32")
25+
v.layers["current_object"].refresh()
26+
if "current_track" in v.layers:
27+
v.layers["current_track"].data = np.zeros(v.layers["current_track"].data.shape, dtype="uint32")
28+
v.layers["current_track"].refresh()
29+
30+
31+
@magicgui(call_button="Clear Annotations [Shfit + C]")
32+
def clear_widget(v: Viewer) -> None:
33+
clear_annotations(v)
2334

2435

2536
@magicgui(call_button="Commit [C]", layer={"choices": ["current_object", "auto_segmentation"]})
@@ -37,7 +48,7 @@ def commit_segmentation_widget(v: Viewer, layer: str = "current_object") -> None
3748
v.layers[layer].refresh()
3849

3950
if layer == "current_object":
40-
clear_all_prompts(v)
51+
clear_annotations(v)
4152

4253

4354
def create_prompt_menu(points_layer, labels, menu_name="prompt", label_name="label"):

0 commit comments

Comments
 (0)