-
Notifications
You must be signed in to change notification settings - Fork 0
/
dilate.py
executable file
·109 lines (86 loc) · 4.81 KB
/
dilate.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
'''
Contains functionality for performing dilation on an image.
'''
import numpy as np
import scipy.ndimage
from PIL import Image
def no_error_dilate(input_image, ground_truth_image, output_image, dilation_radius, foreground_label = 255, background_label = 128):
'''
Dilates the foreground and background labels in a label image to a given
radius (which excludes the pixel in question, so a radius of 1 would result
in an extra pixel in each direction being flipped to that label). Avoids
introducing errors by not performing any dilation on a pixel outside of its
'place' (foreground pixels won't be dilated if they're in the background
and vice versa).
input_image: The label image to dilate.
ground_truth_image: The binary ground truth image.
output_image: Where to save the result.
dilation_radius: Radius of dilation to perform.
'''
image = scipy.ndimage.imread(input_image)
output = np.zeros(image.shape, dtype=np.uint8)
ground_truth = np.greater(scipy.ndimage.imread(ground_truth_image), 0)
x, y = np.ogrid[-dilation_radius : dilation_radius + 1, -dilation_radius : dilation_radius + 1]
circle_mask = x**2 + y**2 <= dilation_radius**2
# Iterate over all pixels for dilation
it = np.nditer(image, flags=['multi_index'])
while not it.finished:
pixel = int(it[0])
# Figure out the mask sizes only for the label pixels
if pixel == foreground_label or pixel == background_label:
is_true_foreground = ground_truth[it.multi_index]
image_min_row = max(it.multi_index[0] - dilation_radius, 0)
image_min_col = max(it.multi_index[1] - dilation_radius, 0)
image_max_row = min(it.multi_index[0] + dilation_radius + 1, image.shape[0])
image_max_col = min(it.multi_index[1] + dilation_radius + 1, image.shape[1])
mask_min_row = max(dilation_radius - it.multi_index[0], 0)
mask_min_col = max(dilation_radius - it.multi_index[1], 0)
mask_max_row = min(image.shape[0] - it.multi_index[0] + dilation_radius, circle_mask.shape[0])
mask_max_col = min(image.shape[1] - it.multi_index[1] + dilation_radius, circle_mask.shape[1])
if pixel == foreground_label:
output[it.multi_index] = foreground_label
# We only dilate (and hence apply the mask) if this is a foreground
# pixel on true foreground or a background pixel on true background
if is_true_foreground:
temp_mask = circle_mask[mask_min_row:mask_max_row, mask_min_col:mask_max_col]
output[image_min_row:image_max_row, image_min_col:image_max_col][temp_mask] = foreground_label
elif pixel == background_label:
output[it.multi_index] = background_label
if not is_true_foreground:
temp_mask = circle_mask[mask_min_row:mask_max_row, mask_min_col:mask_max_col]
output[image_min_row:image_max_row, image_min_col:image_max_col][temp_mask] = background_label
it.iternext()
Image.fromarray(output).save(output_image)
def check_no_error_dilate(input_image, ground_truth_image, foreground_label = 255, background_label = 128):
'''
Returns true if no_error_dilate would act differently than textbook_dilation.
input_image: The label image to dilate.
ground_truth_image: The binary ground truth image.
'''
image = scipy.ndimage.imread(input_image)
ground_truth = np.greater(scipy.ndimage.imread(ground_truth_image), 0)
# Iterate over all pixels for dilation
it = np.nditer(image, flags=['multi_index'])
while not it.finished:
pixel = int(it[0])
if pixel == foreground_label and not ground_truth[it.multi_index]:
return True
elif pixel == background_label and ground_truth[it.multi_index]:
return True
it.iternext()
return False
def textbook_dilation(input_image, output_image, dilation_radius):
'''
Dilates all pixels a given radius (which excludes the pixel in question, so
a radius of 1 would result in an extra pixel in each direction being flipped
to that label).
All non-zero labels will be dilated.
input_image: The label image to dilate.
output_image: Where to save the result.
dilation_radius: Radius of dilation to perform.
'''
image = scipy.ndimage.imread(input_image)
x, y = np.ogrid[-dilation_radius : dilation_radius + 1, -dilation_radius : dilation_radius + 1]
circle_mask = x**2 + y**2 <= dilation_radius**2
dilated_image = scipy.ndimage.morphology.grey_dilation(image, footprint=circle_mask)
Image.fromarray(dilated_image).save(output_image)