forked from napari/napari
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathannotate_segmentation_with_text.py
138 lines (108 loc) · 3.36 KB
/
annotate_segmentation_with_text.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
"""
Annotate segmentation with text
===============================
Perform a segmentation and annotate the results with
bounding boxes and text.
This example is fully explained in the following tutorial:
https://napari.org/stable/tutorials/segmentation/annotate_segmentation.html
.. tags:: analysis
"""
import numpy as np
from skimage import data
from skimage.filters import threshold_otsu
from skimage.measure import label, regionprops_table
from skimage.morphology import closing, remove_small_objects, square
from skimage.segmentation import clear_border
import napari
def segment(image):
"""Segment an image using an intensity threshold determined via
Otsu's method.
Parameters
----------
image : np.ndarray
The image to be segmented
Returns
-------
label_image : np.ndarray
The resulting image where each detected object labeled with a unique integer.
"""
# apply threshold
thresh = threshold_otsu(image)
bw = closing(image > thresh, square(4))
# remove artifacts connected to image border
cleared = remove_small_objects(clear_border(bw), 20)
# label image regions
label_image = label(cleared)
return label_image
def make_bbox(bbox_extents):
"""Get the coordinates of the corners of a
bounding box from the extents
Parameters
----------
bbox_extents : list (4xN)
List of the extents of the bounding boxes for each of the N regions.
Should be ordered: [min_row, min_column, max_row, max_column]
Returns
-------
bbox_rect : np.ndarray
The corners of the bounding box. Can be input directly into a
napari Shapes layer.
"""
minr = bbox_extents[0]
minc = bbox_extents[1]
maxr = bbox_extents[2]
maxc = bbox_extents[3]
bbox_rect = np.array(
[[minr, minc], [maxr, minc], [maxr, maxc], [minr, maxc]]
)
bbox_rect = np.moveaxis(bbox_rect, 2, 0)
return bbox_rect
def circularity(perimeter, area):
"""Calculate the circularity of the region
Parameters
----------
perimeter : float
the perimeter of the region
area : float
the area of the region
Returns
-------
circularity : float
The circularity of the region as defined by 4*pi*area / perimeter^2
"""
circularity = 4 * np.pi * area / (perimeter ** 2)
return circularity
# load the image and segment it
image = data.coins()[50:-50, 50:-50]
label_image = segment(image)
# create the features dictionary
features = regionprops_table(
label_image, properties=('label', 'bbox', 'perimeter', 'area')
)
features['circularity'] = circularity(
features['perimeter'], features['area']
)
# create the bounding box rectangles
bbox_rects = make_bbox([features[f'bbox-{i}'] for i in range(4)])
# specify the display parameters for the text
text_parameters = {
'string': 'label: {label}\ncirc: {circularity:.2f}',
'size': 12,
'color': 'green',
'anchor': 'upper_left',
'translation': [-3, 0],
}
# initialise viewer with coins image
viewer = napari.view_image(image, name='coins', rgb=False)
# add the labels
label_layer = viewer.add_labels(label_image, name='segmentation')
shapes_layer = viewer.add_shapes(
bbox_rects,
face_color='transparent',
edge_color='green',
features=features,
text=text_parameters,
name='bounding box',
)
if __name__ == '__main__':
napari.run()