Commit 6b2be99133073dc9ffbdddfc8afd03f3bab61547
1 parent
538df2a2
added utility functions: image2class, generate_traiing, prob2class and example script
Showing
3 changed files
with
91 additions
and
1 deletions
Show diff stats
python/classify.py
@@ -7,6 +7,8 @@ Created on Sun Jul 23 16:04:33 2017 | @@ -7,6 +7,8 @@ Created on Sun Jul 23 16:04:33 2017 | ||
7 | 7 | ||
8 | import numpy | 8 | import numpy |
9 | import colorsys | 9 | import colorsys |
10 | +from scipy import misc | ||
11 | +from envi import envi | ||
10 | 12 | ||
11 | #generate a 2D color class map using a stack of binary class images | 13 | #generate a 2D color class map using a stack of binary class images |
12 | def classcolor2(C): | 14 | def classcolor2(C): |
@@ -29,15 +31,72 @@ def classcolor2(C): | @@ -29,15 +31,72 @@ def classcolor2(C): | ||
29 | #input: list of class image names | 31 | #input: list of class image names |
30 | #output: X x Y x C stack of binary mask images | 32 | #output: X x Y x C stack of binary mask images |
31 | #example: image2class(("class_coll.bmp", "class_epith.bmp")) | 33 | #example: image2class(("class_coll.bmp", "class_epith.bmp")) |
34 | +def image2class(*masks): | ||
35 | + #get num of mask file names | ||
36 | + num_masks = len(masks) | ||
37 | + | ||
38 | + if num_masks == 0: | ||
39 | + print("ERROR: mask filenames not provided") | ||
40 | + print("Usage example: image2class(('class_coll.bmp', 'class_epith.bmp'))") | ||
41 | + return | ||
42 | + | ||
43 | + #load first mask to get dimensions -- assuming all masks have same dimensions | ||
44 | + mask = misc.imread(masks[0], flatten=True).astype(numpy.bool) | ||
45 | + | ||
46 | + mask_stack = numpy.zeros((mask.shape[0], mask.shape[1], num_masks), dtype=numpy.bool) | ||
47 | + mask_stack[:,:,0] = mask | ||
48 | + | ||
49 | + #load the rest of masks | ||
50 | + for i in range(1, num_masks): | ||
51 | + mask_stack[:,:,i] = misc.imread(masks[i], flatten=True).astype(numpy.bool) | ||
52 | + | ||
53 | + return mask_stack | ||
54 | + | ||
32 | 55 | ||
33 | #create a set of feature/target pairs for classification | 56 | #create a set of feature/target pairs for classification |
34 | #input: envi file object, stack of class masks, list of class names | 57 | #input: envi file object, stack of class masks, list of class names |
35 | #output: feature matrix (features x pixels), target matrix (1 x pixels) | 58 | #output: feature matrix (features x pixels), target matrix (1 x pixels) |
36 | #example: generate_training(("class_coll.bmp", "class_epith.bmp"), (1, 2)) | 59 | #example: generate_training(("class_coll.bmp", "class_epith.bmp"), (1, 2)) |
60 | +def generate_training(filename, mask_stack): | ||
61 | + #create envi file object | ||
62 | + E = envi(filename) | ||
63 | + | ||
64 | + # get number of classes | ||
65 | + C = mask_stack.shape[2] | ||
66 | + | ||
67 | + #get number of annotated pixels | ||
68 | + num_pixels = 0 | ||
69 | + for i in range(0,C): | ||
70 | + num_pixels += numpy.count_nonzero(mask_stack[:,:,i]) | ||
71 | + | ||
72 | + feature_matrix = numpy.zeros((E.header.bands, num_pixels), dtype=E.header.data_type) | ||
73 | + target_matrix = numpy.zeros((1, num_pixels)) | ||
74 | + | ||
75 | + #load masks and append the corresponding pixels to feature matrix and labels to target_matrix | ||
76 | + idx = 0 | ||
77 | + for i in range(0,C): | ||
78 | + mask = E.loadmask(mask_stack[:,:,i]) | ||
79 | + feature_matrix[:, idx:idx + mask.shape[1]] = mask | ||
80 | + target_matrix[idx:idx+mask.shape[1]] = (i+1) | ||
81 | + idx += mask.shape[1] | ||
82 | + | ||
83 | + return feature_matrix, target_matrix | ||
37 | 84 | ||
38 | #create a class mask stack from an X x Y x C probability image | 85 | #create a class mask stack from an X x Y x C probability image |
39 | #input: X x Y x C image giving the probability P(c |x,y) | 86 | #input: X x Y x C image giving the probability P(c |x,y) |
40 | #output: X x Y x C binary class image | 87 | #output: X x Y x C binary class image |
88 | +def prob2class(prob_image): | ||
89 | + class_image = numpy.zeros_like(prob_image) | ||
90 | + #get nonzero indices | ||
91 | + nnz_idx = numpy.transpose(numpy.nonzero(numpy.sum(prob_image, axis=0))) | ||
92 | + | ||
93 | + #set pixel corresponding to max probability to 1 | ||
94 | + for idx in nnz_idx: | ||
95 | + idx_max_prob = numpy.argmax(prob_image[:, idx[0], idx[1]]) | ||
96 | + class_image[idx_max_prob, idx[0], idx[1]] = 1 | ||
97 | + | ||
98 | + return class_image | ||
99 | + | ||
41 | 100 | ||
42 | #create an ROC curve calculator | 101 | #create an ROC curve calculator |
43 | #input: X x Y x C image giving the probability P(c | x,y) | 102 | #input: X x Y x C image giving the probability P(c | x,y) |
python/envi.py
@@ -139,9 +139,18 @@ class envi_header: | @@ -139,9 +139,18 @@ class envi_header: | ||
139 | #handle the complicated conditions | 139 | #handle the complicated conditions |
140 | elif l[li].startswith("description"): | 140 | elif l[li].startswith("description"): |
141 | desc = [l[li]] | 141 | desc = [l[li]] |
142 | - while l[li].strip()[-1] != '}': | 142 | + ''' |
143 | + while l[li].strip()[-1] != '}': #will fail if l[li].strip() is empty | ||
144 | + li += 1 | ||
145 | + desc.append(l[li]) | ||
146 | + ''' | ||
147 | + while True: | ||
148 | + if l[li].strip(): | ||
149 | + if l[li].strip()[-1] == '}': | ||
150 | + break | ||
143 | li += 1 | 151 | li += 1 |
144 | desc.append(l[li]) | 152 | desc.append(l[li]) |
153 | + | ||
145 | desc = ''.join(list(map(str.strip, desc))) #strip all white space from the string list | 154 | desc = ''.join(list(map(str.strip, desc))) #strip all white space from the string list |
146 | i0 = desc.rindex('{') | 155 | i0 = desc.rindex('{') |
147 | i1 = desc.rindex('}') | 156 | i1 = desc.rindex('}') |
1 | +import numpy | ||
2 | +import classify | ||
3 | +import matplotlib.pyplot as plt | ||
4 | +from envi import envi | ||
5 | + | ||
6 | +mask_path = '/home/sberisha/data/masks/' | ||
7 | +mask_stack = classify.image2class(mask_path + "class_blood.png", mask_path + "class_coll.png", mask_path + "class_epith.png", | ||
8 | + mask_path + "class_lymph.png", mask_path + "class_necrosis.png") | ||
9 | + | ||
10 | +color_image = classify.classcolor2(mask_stack) | ||
11 | +plt.imshow(color_image) | ||
12 | + | ||
13 | +data_path ='/home/sberisha/data/cnn/brc961-nfp8/envi/' | ||
14 | + | ||
15 | +feature_matrix, target_matrix = classify.generate_training(data_path + 'brc961-nfp8-project-br1003', mask_stack) | ||
16 | + | ||
17 | +prob_path = '/home/sberisha/data/' | ||
18 | +prob_envi= envi(prob_path + "cnn-response") | ||
19 | +prob_image = prob_envi.loadall() | ||
20 | + | ||
21 | +class_image = classify.prob2class(prob_image) | ||
22 | +plt.imshow(class_image[4,:,:]) | ||
0 | \ No newline at end of file | 23 | \ No newline at end of file |