a b/10x/batch.py
1
import os
2
import sys
3
import pickle
4
5
import numpy as np
6
import matplotlib
7
8
import skimage as ski
9
from skimage import io, filter, color, exposure, morphology, feature, draw, measure, transform
10
11
from scipy.spatial import distance
12
from scipy import ndimage
13
14
15
16
17
18
19
20
# Things to measure for each image
21
in_count = []
22
out_count = []
23
in_size = []
24
out_size = []
25
in_area_density = []
26
out_area_density = []
27
in_point_density = []
28
out_point_density = []
29
var_point_density = []
30
cov_point_density = []
31
var_area_density = []
32
cov_area_density = []
33
fs_area = []
34
pairwise = []
35
name = []
36
imageid = []
37
38
39
40
41
42
43
44
F = open("filelist%i.p" % int(sys.argv[1]), "r")
45
files = pickle.load(F)
46
F.close()
47
48
49
50
51
52
53
54
55
for f in files :
56
57
    print "Thread %s, image %s" % (sys.argv[1], f)
58
59
    ## ID
60
    name.append(int(f.split("data/Sheep")[1].split("-")[0].split(".jpg")[0]))
61
    imageid.append(int(f.split("data/Sheep")[1].split("-")[2].split(".jpg")[0]))
62
63
64
65
66
67
68
69
    # Process for nuclei
70
71
    A = io.imread(f)
72
    print "Loaded image."
73
    
74
    binary = filter.threshold_adaptive(exposure.adjust_sigmoid(A[:, :, 0], cutoff=0.4, gain = 30), 301).astype(bool)
75
    print "Binarised."
76
77
    clean = morphology.binary_closing(binary, morphology.disk(3)).astype(bool)
78
    clean = morphology.remove_small_objects(clean, 200)
79
    clean = morphology.remove_small_objects( (1-clean).astype(bool), 200)
80
    print "Cleaned."
81
82
83
84
85
86
87
88
89
90
    # Find contour of inflammatory zone
91
92
    local_density = filter.gaussian_filter(clean, 61)
93
    local_density -= local_density.min()
94
    local_density /= local_density.max()
95
96
    ent = filter.gaussian_filter(filter.rank.entropy(local_density, morphology.disk(3)), 75)
97
    ent -= ent.min()
98
    ent /= ent.max()
99
100
    info = ent * (1 + local_density)
101
102
    bw = (info) > filter.threshold_otsu(info)
103
104
    C = measure.find_contours(bw, 0.5)
105
    centroid = []
106
    vals = []
107
108
    for c in C :
109
        centroid.append(np.linalg.norm([c[:, 1].mean() - bw.shape[1] / 2, c[:, 0].mean() - bw.shape[0] / 2]))
110
        vals.append(local_density.T[c.astype(int)].sum())
111
112
    cent = C[np.argmin(centroid / np.array(vals))]
113
    contour = matplotlib.path.Path(cent)
114
115
    print "Contour of inflammatory zone found."
116
117
118
119
120
121
122
123
124
    # Segmentation
125
126
    dist = ndimage.distance_transform_edt(clean)
127
    peaks = feature.peak_local_max(dist, indices=False, labels = clean)
128
    markers = ndimage.label(peaks)[0]
129
    labels = morphology.watershed(-dist, markers, mask=clean)
130
    print "Image segmented."
131
132
133
134
135
136
137
138
139
140
141
142
    # Properties of each nucleus
143
    nuclei = measure.regionprops(labels)
144
    contour = matplotlib.path.Path(cent, closed=True)
145
146
    incount = 0
147
    outcount = 0
148
    insize = []
149
    outsize = []
150
    outer_nuclei = []
151
152
    # Number of nuclei, and their sizes, inside and outside the focus
153
    for n in nuclei :
154
        if contour.contains_point(n.centroid) :
155
            incount += 1
156
            insize.append((labels == n.label).sum())
157
        else :
158
            outcount += 1
159
            outsize.append((labels == n.label).sum())
160
            outer_nuclei.append(n)
161
162
    in_count.append(incount)
163
    out_count.append(outcount)
164
    in_size.append(np.mean(insize))
165
    out_size.append(np.mean(outsize))
166
    print "Nuclei identified."
167
168
169
170
171
172
173
174
175
176
177
178
179
    # Using the shoelace algorithm, compute the area of the focus
180
    x = contour.vertices[:, 0]
181
    y = contour.vertices[:, 1]
182
    x = np.append(x, contour.vertices[0, 0])
183
    y = np.append(y, contour.vertices[0, 1])
184
    fsarea = np.abs(np.sum(x[:-1] * y[1:] - x[1:] * y[:-1])) / (2. * 3456 * 5184)
185
    fs_area.append(fsarea)
186
187
188
189
190
191
192
193
194
195
196
197
198
199
    # Area densities inside and outside the focus
200
    in_area_density.append(incount * np.mean(insize) / fsarea)
201
    out_area_density.append(outcount * np.mean(outsize) / (1. - fsarea))
202
                            
203
    # Point densities inside and outside the focus
204
    in_point_density.append(incount / fsarea)
205
    out_point_density.append(outcount / (1. - fsarea))
206
    print "Densities calculated."
207
208
209
210
211
212
213
214
215
216
217
218
219
220
    # Variance and CoV of outside the focus
221
    mask = np.zeros_like(clean)
222
    for c in cent :
223
        mask[int(np.round(c[0])), int(np.round(c[1]))] = 1
224
    mask = ndimage.binary_fill_holes(ndimage.maximum_filter(mask, 35))
225
226
    areadensity = filter.gaussian_filter(clean, 51)
227
    var_area_density.append(np.var(areadensity[mask == 0]))
228
    cov_area_density.append(np.std(areadensity[mask == 0] / np.mean(areadensity[mask == 0])))
229
230
    pointdensity = np.zeros_like(clean)
231
    for n in nuclei :
232
        pointdensity[int(np.round(n.centroid[0])), int(np.round(n.centroid[1]))] = 1
233
    pointdensity = filter.gaussian_filter(pointdensity, 51)
234
235
    var_point_density.append(np.var(pointdensity[mask == 0]))
236
    cov_point_density.append(np.std(pointdensity[mask == 0] / np.mean(pointdensity[mask == 0])))
237
    print "Variances calculated. "
238
239
240
241
242
243
244
245
246
247
248
    # Pairwise distances between nuclei outside the focal area 
249
    distances = distance.squareform(distance.pdist([n.centroid for n in outer_nuclei]))
250
251
    for i in range(len(distances)) :
252
        distances[i, i] = np.inf
253
        
254
    pairwise.append(np.min(distances, axis=0).mean())
255
    print "Pairwise distances calculated."
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
in_count = []
273
out_count = []
274
in_size = []
275
out_size = []
276
in_area_density = []
277
out_area_density = []
278
in_point_density = []
279
out_point_density = []
280
var_point_density = []
281
cov_point_density = []
282
var_area_density = []
283
cov_area_density = []
284
fs_area = []
285
pairwise = []
286
287
results = {}
288
results["in_count"] = in_count
289
results["out_count"] = out_count
290
results["in_size"] = in_size
291
results["out_size"] = out_size
292
results["in_area_density"] = in_area_density
293
results["out_area_density"] = out_area_density
294
results["in_point_density"] = in_point_density
295
results["out_point_density"] = out_point_density
296
results["name"] = name
297
results["ID"] = imageid
298
results["var_point_density"] = var_point_density
299
results["cov_point_density"] = cov_point_density
300
results["var_area_density"] = var_area_density
301
results["cov_area_density"] = cov_area_density
302
results["fs_area"] = fs_area
303
results["pairwise"] = pairwise
304
305
F = open("results/thread_%s" % sys.argv[1], "w")
306
pickle.dump(results, F)
307
F.close()
308
print "Thread %s finished." % sys.argv[1]
309