Blame view

python/classify.py 4.15 KB
18368aa9   David Mayerich   added a new set o...
1
2
3
4
5
6
7
8
9
  # -*- coding: utf-8 -*-
  """
  Created on Sun Jul 23 16:04:33 2017
  
  @author: david
  """
  
  import numpy
  import colorsys
90c935e3   David Mayerich   updates
10
11
  import sklearn
  import sklearn.metrics
f275c01c   David Mayerich   finalized the pre...
12
13
14
  import scipy
  import scipy.misc
  import envi
18368aa9   David Mayerich   added a new set o...
15
16
  
  #generate a 2D color class map using a stack of binary class images
f275c01c   David Mayerich   finalized the pre...
17
18
  #input: C is a C x Y x X binary image
  #output: an RGB color image with a unique color for each class
71ee1c23   David Mayerich   added additional ...
19
  def class2color(C):
18368aa9   David Mayerich   added a new set o...
20
21
      
      #determine the number of classes
f275c01c   David Mayerich   finalized the pre...
22
23
24
25
      nc = C.shape[0]
      
      s = C.shape[1:]
      s = numpy.append(s, 3)
18368aa9   David Mayerich   added a new set o...
26
27
  
      #generate an RGB image
f275c01c   David Mayerich   finalized the pre...
28
      RGB = numpy.zeros(s, dtype=numpy.ubyte)
18368aa9   David Mayerich   added a new set o...
29
30
31
32
33
      
      #for each class
      for c in range(0, nc):
          hsv = (c * 1.0 / nc, 1, 1)
          color = numpy.asarray(colorsys.hsv_to_rgb(hsv[0], hsv[1], hsv[2])) * 255
f275c01c   David Mayerich   finalized the pre...
34
          RGB[C[c, ...], :] = color
18368aa9   David Mayerich   added a new set o...
35
      
538df2a2   David Mayerich   added function de...
36
37
38
39
      return RGB
  
  #create a function that loads a set of class images as a stack of binary masks
  #input: list of class image names
f275c01c   David Mayerich   finalized the pre...
40
  #output: C x Y x X binary image specifying class/pixel membership
538df2a2   David Mayerich   added function de...
41
  #example: image2class(("class_coll.bmp", "class_epith.bmp"))
f275c01c   David Mayerich   finalized the pre...
42
  def image2class(masks):
6b2be991   sberisha   added utility fun...
43
44
45
46
47
48
49
50
      #get num of mask file names
      num_masks = len(masks)
  
      if num_masks == 0:
          print("ERROR: mask filenames not provided")
          print("Usage example: image2class(('class_coll.bmp', 'class_epith.bmp'))")
          return
  
f275c01c   David Mayerich   finalized the pre...
51
52
53
54
      classimages = []
      for m in masks:
          img = scipy.misc.imread(m, flatten=True).astype(numpy.bool)
          classimages.append(img)
538df2a2   David Mayerich   added function de...
55
  
f275c01c   David Mayerich   finalized the pre...
56
57
      result = numpy.stack(classimages)
      sum_images = numpy.sum(result.astype(numpy.uint32), 0)
6b2be991   sberisha   added utility fun...
58
  
f275c01c   David Mayerich   finalized the pre...
59
60
61
      #identify and remove redundant pixels
      bad_idx = sum_images > 1
      result[:, bad_idx] = 0
6b2be991   sberisha   added utility fun...
62
  
f275c01c   David Mayerich   finalized the pre...
63
      return result
6b2be991   sberisha   added utility fun...
64
  
6b2be991   sberisha   added utility fun...
65
  
f275c01c   David Mayerich   finalized the pre...
66
67
68
  #create a class mask stack from an C x Y x X probability image
  #input: C x Y x X image giving the probability P(c |x,y)
  #output: C x Y x X binary class image
6b2be991   sberisha   added utility fun...
69
  def prob2class(prob_image):
f275c01c   David Mayerich   finalized the pre...
70
      class_image = numpy.zeros(prob_image.shape, dtype=numpy.bool)
6b2be991   sberisha   added utility fun...
71
72
      #get nonzero indices
      nnz_idx = numpy.transpose(numpy.nonzero(numpy.sum(prob_image, axis=0)))
fad1a72c   David Mayerich   merged sebastian ...
73
      
6b2be991   sberisha   added utility fun...
74
75
76
77
78
79
      #set pixel corresponding to max probability to 1
      for idx in nnz_idx:
          idx_max_prob = numpy.argmax(prob_image[:, idx[0], idx[1]])
          class_image[idx_max_prob, idx[0], idx[1]] = 1
  
      return class_image
f275c01c   David Mayerich   finalized the pre...
80
  
90c935e3   David Mayerich   updates
81
  #calculate an ROC curve given a probability image and mask of "True" values
f275c01c   David Mayerich   finalized the pre...
82
83
84
85
86
87
88
89
90
91
92
93
  #input:
  #       P is a Y x X probability image specifying P(c | x,y)
  #       t_vals is a Y x X binary image specifying points where x,y = c
  #       mask is a mask specifying all pixels to be considered (positives and negatives)
  #           use this mask to limit analysis to regions of the image that have been classified
  #output: fpr, tpr, thresholds
  #       fpr is the false-positive rate (x-axis of an ROC curve)
  #       tpr is the true-positive rate (y-axis of an ROC curve)
  #       thresholds stores the threshold associated with each point on the ROC curve
  #
  #note: the AUC can be calculated as auc = sklearn.metrics.auc(fpr, tpr)
  def prob2roc(P, t_vals, mask=[]):
90c935e3   David Mayerich   updates
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
      
      if not P.shape == t_vals.shape:
          print("ERROR: the probability and mask images must be the same shape")
          return
      
      #if a mask image isn't provided, create one for the entire image
      if mask == []:
          mask = numpy.ones(t_vals.shape, dtype=numpy.bool)
      
      #create masks for the positive and negative probability scores
      mask_p = t_vals
      mask_n = mask - mask * t_vals
      
      #calculate the indices for the positive and negative scores
      idx_p = numpy.nonzero(mask_p)
      idx_n = numpy.nonzero(mask_n)
      
      Pp = P[idx_p]
      Pn = P[idx_n]
6b2be991   sberisha   added utility fun...
113
  
90c935e3   David Mayerich   updates
114
115
116
117
118
119
      Lp = numpy.ones((Pp.shape), dtype=numpy.bool)
      Ln = numpy.zeros((Pn.shape), dtype=numpy.bool)
      
      scores = numpy.concatenate((Pp, Pn))
      labels = numpy.concatenate((Lp, Ln))
      
fad1a72c   David Mayerich   merged sebastian ...
120
      return sklearn.metrics.roc_curve(labels, scores)
f275c01c   David Mayerich   finalized the pre...
121
  
71ee1c23   David Mayerich   added additional ...
122
123
124
125
126
127
128
129
130
131
132
  #convert a label image to a C x Y x X class image
  def label2class(L):
      unique = numpy.unique(L)
      s = L.shape
      s = numpy.append(numpy.array((len(unique)-1)), s)
      print(s)
      C = numpy.zeros(s, dtype=numpy.bool)
      for i in range(1, len(unique)):
          C[i-1, :, :] = L == unique[i]
      return C
  
f275c01c   David Mayerich   finalized the pre...
133
134
135
  #Function to convert a set of class labels to a matrix of neuron responses for an ANN
  
  #Function CNN extraction function