Blame view

python/classify.py 4.07 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
6b2be991   sberisha   added utility fun...
12
13
  from scipy import misc
  from envi import envi
18368aa9   David Mayerich   added a new set o...
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  
  #generate a 2D color class map using a stack of binary class images
  def classcolor2(C):
      
      #determine the number of classes
      nc = C.shape[-1]
  
      #generate an RGB image
      RGB = numpy.zeros((C.shape[0], C.shape[1], 3), dtype=numpy.ubyte)
      
      #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
          RGB[C[:, :, c], :] = color
      
538df2a2   David Mayerich   added function de...
30
31
32
33
34
35
      return RGB
  
  #create a function that loads a set of class images as a stack of binary masks
  #input: list of class image names
  #output: X x Y x C stack of binary mask images
  #example: image2class(("class_coll.bmp", "class_epith.bmp"))
6b2be991   sberisha   added utility fun...
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  def image2class(*masks):
      #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
  
      #load first mask to get dimensions -- assuming all masks have same dimensions
      mask = misc.imread(masks[0], flatten=True).astype(numpy.bool)
  
      mask_stack = numpy.zeros((mask.shape[0], mask.shape[1], num_masks), dtype=numpy.bool)
      mask_stack[:,:,0] = mask
  
      #load the rest of masks
      for i in range(1, num_masks):
          mask_stack[:,:,i] = misc.imread(masks[i], flatten=True).astype(numpy.bool)
  
      return mask_stack
  
538df2a2   David Mayerich   added function de...
57
58
59
60
61
  
  #create a set of feature/target pairs for classification
  #input: envi file object, stack of class masks, list of class names
  #output: feature matrix (features x pixels), target matrix (1 x pixels)
  #example: generate_training(("class_coll.bmp", "class_epith.bmp"), (1, 2))
6b2be991   sberisha   added utility fun...
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
  def generate_training(filename, mask_stack):
      #create envi file object
      E = envi(filename)
  
      # get number of classes
      C = mask_stack.shape[2]
  
      #get number of annotated pixels
      num_pixels = 0
      for i in range(0,C):
          num_pixels += numpy.count_nonzero(mask_stack[:,:,i])
  
      feature_matrix = numpy.zeros((E.header.bands, num_pixels), dtype=E.header.data_type)
      target_matrix = numpy.zeros((1, num_pixels))
  
      #load masks and append the corresponding pixels to feature matrix and labels to target_matrix
      idx = 0
      for i in range(0,C):
          mask = E.loadmask(mask_stack[:,:,i])
          feature_matrix[:, idx:idx + mask.shape[1]] = mask
          target_matrix[idx:idx+mask.shape[1]] = (i+1)
          idx += mask.shape[1]
  
      return feature_matrix, target_matrix
538df2a2   David Mayerich   added function de...
86
87
88
89
  
  #create a class mask stack from an X x Y x C probability image
  #input: X x Y x C image giving the probability P(c |x,y)
  #output: X x Y x C binary class image
6b2be991   sberisha   added utility fun...
90
91
92
93
  def prob2class(prob_image):
      class_image = numpy.zeros_like(prob_image)
      #get nonzero indices
      nnz_idx = numpy.transpose(numpy.nonzero(numpy.sum(prob_image, axis=0)))
fad1a72c   David Mayerich   merged sebastian ...
94
      
6b2be991   sberisha   added utility fun...
95
96
97
98
99
100
      #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
90c935e3   David Mayerich   updates
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
  #calculate an ROC curve given a probability image and mask of "True" values
  def image2roc(P, t_vals, mask=[]):
      
      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...
122
  
90c935e3   David Mayerich   updates
123
124
125
126
127
128
      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 ...
129
      return sklearn.metrics.roc_curve(labels, scores)