This repository has been archived by the owner on Jan 25, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
shadow-segmentation.py
149 lines (107 loc) · 4.18 KB
/
shadow-segmentation.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
139
140
141
142
143
144
145
146
147
148
149
import itertools
import os
import sys
import time
import warnings
import numpy as np
import scipy.ndimage as ndi
import matplotlib.pyplot as plt
import skimage.io as io
from sklearn.cluster import MiniBatchKMeans as k_means
from sklearn.metrics import normalized_mutual_info_score
from sklearn.metrics import adjusted_rand_score
from sklearn.metrics import homogeneity_score
from sklearn.metrics import completeness_score
from skimage.feature import local_binary_pattern
from skimage.filter import gabor_filter
from skimage.filter import gaussian_filter
from skimage.filter import threshold_otsu
def zero_pad(string, num_zeroes=5):
zeroes = (num_zeroes - len(string))
if zeroes > 0:
return (zeroes * "0") + string
else:
return string
def _imshow(*images):
fig = plt.figure()
for i in range(0, len(images)):
im = images[i]
if im.shape[0] > im.shape[1]:
ax = fig.add_subplot(1, len(images), i + 1)
else:
ax = fig.add_subplot(len(images), 1, i + 1)
cax = ax.imshow(im, cmap=plt.cm.cubehelix)
fig.colorbar(cax)
def mask_dominant_label(image, labels):
hist, bins = np.histogram(labels, n_clusters, [0, n_clusters])
dominant_label = bins[hist.argmax()]
print("Dominant label: %d" % (dominant_label))
mask = labels == dominant_label
image[mask] = 0
return mask, image
def cluster_metrics(labels_1, labels_2):
print("\n".join(
[
"Normalized Mutual Information: %f" % (normalized_mutual_info_score(labels_1, labels_2)),
"Adjusted Rand Score: %f" % (adjusted_rand_score(labels_1, labels_2)),
"Homogeneity: %f" % (homogeneity_score(labels_1, labels_2)),
"Completeness: %f" % (completeness_score(labels_1, labels_2))
]
))
def lbp(image, n=3, method="uniform"):
return local_binary_pattern(image, P=8*n, R=n, method=method)
def segment_texture(image, n_clusters=15, init=None):
# blur and take local maxima
blur_image = gaussian_filter(image, sigma=8)
blur_image = ndi.maximum_filter(blur_image, size=3)
# get texture features
feats = lbp(blur_image, n=5, method="uniform")
feats_r = feats.reshape(-1, 1)
# cluster the texture features, reusing initialised centres if already calculated
params = {"n_clusters": n_clusters, "batch_size": 500}
if init is not None:
params.update({"init": init})
km = k_means(**params)
clus = km.fit(feats_r)
# copy relevant attributes
labels = clus.labels_
clusters = clus.cluster_centers_
# reshape label arrays
labels = labels.reshape(blur_image.shape[0], blur_image.shape[1])
return (image, blur_image, labels, clusters)
def segment_shadow(image, labels, n_clusters=8):
img = image.ravel()
shadow_seg = img.copy()
for i in range(0, n_clusters):
# set up array of pixel indices matching cluster
mask = np.nonzero((labels.ravel() == i) == True)[0]
if len(mask) > 0:
if img[mask].var() > 0.005:
thresh = threshold_otsu(img[mask])
shadow_seg[mask] = shadow_seg[mask] < thresh
else:
shadow_seg[mask] = 0
shadow_seg = shadow_seg.reshape(*image.shape)
return shadow_seg
if __name__ == "__main__":
# shut up scikit-image and numpy
warnings.simplefilter("ignore")
images = sys.argv[1:-1]
output_dir = os.path.abspath(os.path.join(os.getcwd(), sys.argv[-1]))
times = np.zeros((len(images)))
i = 0
shape = io.imread(images[i], as_grey=True).shape
init = None
for im_path in images:
image = io.imread(im_path, as_grey=True)
s = time.time()
n_clusters = 8
image, blur_image, labels, init = segment_texture(image, n_clusters=n_clusters, init=init)
shadow_seg = segment_shadow(blur_image, labels, n_clusters)
e = time.time()
times[i] = (e - s)
i += 1
fn = os.path.join(output_dir, "output-%s.png" % (zero_pad(str(i))))
io.imsave(fn, shadow_seg)
print("Average time to process a %s image: %f seconds" % (str(shape), np.average(times)))
print("Total time for %d images: %f seconds" % (len(images), np.sum(times)))