Skip to content

Commit

Permalink
updated classifier - outputs matclass image
Browse files Browse the repository at this point in the history
  • Loading branch information
andymiller committed Apr 6, 2012
1 parent ffaabbf commit 23792c4
Show file tree
Hide file tree
Showing 4 changed files with 154 additions and 130 deletions.
207 changes: 115 additions & 92 deletions classifier/boxm2_classify.py
@@ -1,6 +1,6 @@
import numpy as np
import pylab as pl
import random
import random, types, pickle
from sklearn import svm, datasets
from optparse import OptionParser
from PIL import Image
Expand All @@ -11,120 +11,65 @@ class RGBIDataset:
""" Load dataset from flat file - has data and target """
def __init__(self, fname):
self.classes = []
self.data = []
self.target =[]
self.classMap = {}
self.numClass = 0
self.load_flat_file(fname)

def load_flat_file(self,fname):
f = open(fname, 'r')
eoPixels = []
irPixels = []
pixels = []
for line in f:
l = line.split()
#if not(l[0] == "noclass" or l[0] == "trees" or l[0]== "water"): continue
if l[0]=="noclass" and random.random() > .5: continue

#initialize class int
datClass = l[0]
if datClass == "noclass": continue
#if l[0]=="noclass" and random.random() > .5: continue

#initialize class-int map (string to int)
if not self.classMap.has_key(datClass):
self.classMap[datClass] = self.numClass
self.numClass += 1
self.classMap[datClass] = len(self.classMap)

#keep track of string names, equivalent int, and float data
self.classes.append( l[0] )
self.target.append( self.classMap[datClass] )
irPixels.append( [float(l[1])] )
eoPixels.append( [float(x) for x in l[2:]] );
pixels.append( [float(x) for x in l[1:]] );

#numpy arrays
self.classes = np.array(self.classes)
self.target = np.array(self.target)
eoPixels = np.array(eoPixels)
irPixels = np.array(irPixels)
self.eoPixels = eoPixels
self.irPixels = irPixels
print "EO File pixels shape: ", eoPixels.shape
self.intToClass = dict((v,k) for k, v in self.classMap.iteritems())

#trasnform IR dataset to just take brightnes (total intensity), and ratios
self.reducer = ti.LDAFeatures()
self.data = self.reducer.features(eoPixels, irPixels, self.target)
self.pixels = np.array(pixels)

#print info
print "Data shape: ", self.data.shape
for c,v in self.classMap.iteritems():
print c, ":", np.sum(self.target==v), "items in training set"
#reverse class map (int to class)
self.intToClass = dict((v,k) for k, v in self.classMap.iteritems())

if __name__ == "__main__":
# handle inputs
parser = OptionParser()
parser.add_option("-d", "--data", action="store", type="string", dest="data", default="/home/acm/Dropbox/cvg/MatClass/samples.txt",help="Specify data file")
(options, args) = parser.parse_args()
print options
print args

# import some data to play with
#iris = datasets.load_iris()
#X = iris.data[:, :2] # we only take the first two features. We could
# avoid this ugly slicing by using a two-dim dataset
#Y = iris.target
imgs = RGBIDataset(options.data)
X = imgs.data
Y = imgs.target

# we create an instance of SVM and fit out data. We do not scale our
# data since we want to plot the support vectors
rbf_svc = svm.SVC(kernel='rbf', gamma=0.7).fit(X, Y)
eoImg = "/home/acm/Dropbox/cvg/MatClass/Annotations/eoImgs/exp_000.png"
irImg = "/home/acm/Dropbox/cvg/MatClass/Annotations/irImgs/exp_000.png"
#data, pixelZ = ci.classify_pixels(eoImg, irImg, imgs.reducer, rbf_svc, imgs);
#print "Pixel xmin, xmax, ", data[:,0].min(), data[:,0].max()
#print " ymin, ymax, ", data[:,1].min(), data[:,1].max()

def plot_classifier(X, Y, models, classMap=None):
""" Plots classifier or classifiers on 2d plot """
#handle single model
if not isinstance(models, types.ListType):
models = [models]
titles = ["classifier"]
else:
titles = []
for model in models:
titles.append("Classifier...")

#DEBUG#####
eo = Image.open(eoImg)
ir = Image.open(irImg)
eoPix = np.float32(eo) / 255.0
irPix = np.float32(ir) / 255.0
eoDat = eoPix.reshape( (eoPix.shape[0]*eoPix.shape[1], eoPix.shape[2]) )
eoDat = eoDat[:,:3]
irDat = irPix.reshape( (irPix.shape[0]*irPix.shape[1], 1) )
#pl.plot(imgs.eoPixels[:,0], imgs.eoPixels[:,1], "o", c="red", label="File")
#pl.plot(eoDat[:,0], eoDat[:,1], "x", c="blue", label="File")
#pl.legend()
#pl.show()

#poly_svc = svm.SVC(kernel='poly', degree=3).fit(X, Y)
lin_svc = svm.LinearSVC().fit(X, Y)
print "SVM Learned"
#colors for different decisions
colors = ["red", "green", "blue", "yellow", "black"]

# create a mesh to plot in
h = 50 # step size in mesh
x_min, x_max = X[:, 0].min() - .002, X[:, 0].max() + .002
y_min, y_max = X[:, 1].min() - .002, X[:, 1].max() + .002

#incorporate pixel data
#x_min = min(x_min, data[:,0].min())
#x_max = max(x_max, data[:,0].max())
#y_min = min(y_min, data[:,1].min())
#y_max = max(y_max, data[:,1].max())
xx, yy = np.meshgrid(np.arange(x_min, x_max, (x_max-x_min)/h),
np.arange(y_min, y_max, (y_max-y_min)/h))
print xx.shape

# title for the plots
models = [ rbf_svc ]
titles = ['SVC with linear kernel',
'SVC with RBF kernel',
'SVC with polynomial (degree 3) kernel',
'LinearSVC (linear kernel)']

#set cmap
pl.set_cmap(pl.cm.Paired)
for i, clf in enumerate( models ):
for mi, clf in enumerate( models ):
# Plot the decision boundary. For that, we will asign a color to each
# point in the mesh [x_min, m_max]x[y_min, y_max].
pl.subplot(1, len(models), i + 1)
pl.subplot(1, len(models), mi + 1)
Z = clf.predict(np.c_[xx.ravel(), yy.ravel()])

# Put the result into a color plot
Expand All @@ -134,18 +79,96 @@ def load_flat_file(self,fname):
#pl.axis('off')

# Plot also the training points
colors = ["red", "green", "blue", "yellow", "black"]
for c,i in imgs.classMap.iteritems():
x = X[Y==i]
pl.plot(x[:,0], x[:,1], "o", c=colors[i], label=c)

#plot image points
#pl.plot(data[:,0], data[:,1], "o", c="orange", label="Pixels")
if classMap:
for c,i in classMap.iteritems():
x = X[Y==i]
pl.plot(x[:,0], x[:,1], "o", c=colors[i], label=c)

#legend and title
pl.legend()
pl.title(titles[i])

pl.title(titles[mi])
pl.show()




###### MAIN ######
if __name__ == "__main__":
# handle inputs
parser = OptionParser()
parser.add_option("-d", "--train", action="store", type="string", dest="data", default="/home/acm/Dropbox/cvg/MatClass/exp_002.txt", help="Specify training data file")
parser.add_option("-t", "--test", action="store", type="string", dest="test", default="", help="Specify testing data file")
parser.add_option("-s", "--save", action="store", type="string", dest="modelOut", default="", help="Specify model output file (e.g. svc_rbf.svm)")
parser.add_option("-m", "--model", action="store", type="string", dest="modelIn", default="", help="Specify input model to plot/test (e.g. svc_rbf.svm)")
(options, args) = parser.parse_args()
print options

# import some data to play with
training = RGBIDataset(options.data)
Y = training.target
pixels = training.pixels
print pixels


#trasnform IR dataset to just take brightnes (total intensity), and ratios
reducer = ti.LDAFeatures()
X = reducer.features(pixels, Y)

#print info
print "Data shape: ", X.shape
for c,v in training.classMap.iteritems():
print c, ":", np.sum(Y==v), "items in training set"

# we create an instance of SVM and fit out data. We do not scale our
# data since we want to plot the support vectors
if options.modelIn != "":
print "Importing model!"
inFile = open(options.modelIn, 'rb')
rbf_svc = pickle.load(inFile)
inFile.close()
else:
print "Learning SVM "
rbf_svc = svm.SVC(kernel='rbf', gamma=0.7, probability=True).fit(X, Y)
print "SVM Learned"

#write model out if specified
if options.modelOut != "":
print "saving model!"
out = open(options.modelOut, 'wb')
pickle.dump(rbf_svc, out)
out.close()

########## TESTING ############
#testing data from second image
if options.test != "":
testing = RGBIDataset(options.test)
Y_test = testing.target
X_test = reducer.features(testing.pixels)
plot_classifier(X_test, Y_test, rbf_svc, testing.classMap)


#plot on training data
plot_classifier(X,Y,rbf_svc,training.classMap)

#outside image stuff
eoImg = "/home/acm/Dropbox/cvg/MatClass/Annotations/eoImgs/exp_000.png"
irImg = "/home/acm/Dropbox/cvg/MatClass/Annotations/irImgs/exp_000.png"
data, pixelZ = ci.classify_pixels(eoImg, irImg, reducer, rbf_svc, training);
#print "Pixel xmin, xmax, ", data[:,0].min(), data[:,0].max()
#print " ymin, ymax, ", data[:,1].min(), data[:,1].max()

#DEBUG#####
#eo = Image.open(eoImg)
#ir = Image.open(irImg)
#eoPix = np.float32(eo) / 255.0
#irPix = np.float32(ir) / 255.0
#eoDat = eoPix.reshape( (eoPix.shape[0]*eoPix.shape[1], eoPix.shape[2]) )
#eoDat = eoDat[:,:3]
#irDat = irPix.reshape( (irPix.shape[0]*irPix.shape[1], 1) )
#pl.plot(imgs.eoPixels[:,0], imgs.eoPixels[:,1], "o", c="red", label="File")
#pl.plot(eoDat[:,0], eoDat[:,1], "x", c="blue", label="File")
#pl.legend()
#pl.show()



28 changes: 20 additions & 8 deletions classifier/classify_image.py
Expand Up @@ -5,32 +5,44 @@
from PIL import Image
import transImage as ti

def classify_pixels(eoName, irName,reducer,model,dataset=None):
def classify_pixels(eoName, irName, reducer, model, dataset=None):

#grab pixel values from images
eo = Image.open(eoName)
ir = Image.open(irName)
eoPix = np.float32(eo) / 255.0
irPix = np.float32(ir) / 255.0

eoDat = eoPix.reshape( (eoPix.shape[0]*eoPix.shape[1], eoPix.shape[2]) )
eoDat = eoDat[:,:3]
irDat = irPix.reshape( (irPix.shape[0]*irPix.shape[1], 1) )

#zip pixels into (IR, R, G, B) intensities
pixels = np.column_stack( (irDat, eoDat) )

#reduce data
data = reducer.features(eoDat, irDat)
Z = np.array(model.predict(data))
print "dim reducing features"
X = reducer.features(pixels)
X = X[:,:100]


#print "classifying image"
#Z = np.array(model.predict(X))
print "Predicting probabilities"
Probs = np.array(model.predict_proba(X))
print "Probs = ", Probs

#print out classes
if dataset:
print "Num pixels classified: "
for name,val in dataset.classMap.iteritems():
print name, np.sum(Z==val)
print val, name, np.sum(Z==val)

#shape
Z = Z.reshape(irPix.shape)
Z = Z.reshape(irPix.shape).astype(np.uint8)
print "Image shape: ", Z.shape

#try saving it out
newImg = Image.fromarray(Z)
newImg.save("test.tiff")
newImg.save("test.png")

return data, Z
return X, Z
44 changes: 14 additions & 30 deletions classifier/transImage.py
Expand Up @@ -9,9 +9,9 @@ class LDAFeatures:
def __init__(self):
self.lda = None

def features(self, eoPixels, irPixels, gt=None):
def features(self, pixels, gt=None):
#grab feature stack
fullFeatures = naive_features(eoPixels, irPixels)
fullFeatures = naive_features(pixels)

#if the LDA from ground truth exists already, transform new features
if gt==None and self.lda != None:
Expand All @@ -23,48 +23,32 @@ def features(self, eoPixels, irPixels, gt=None):
return self.lda.transform(fullFeatures)

class PCAFeatures:
def features(self, eoPixels, irPixels):
fullFeatures = naive_features(eoPixels, irPixels)
def features(self, pixels):
fullFeatures = naive_features(pixels)
self.pca = PCA(n_components=2).fit(fullFeatures)
return self.pca.transform(fullFeatures)


def naive_features(eoPixels, irPixels):

def naive_features(pixels):
"""Stacks a bunch of ratios/differences into a
high dimensional feature vector
"""
#create sqr differences features for each channel
allPix = np.column_stack( (eoPixels, irPixels) )
intensity = np.sum(eoPixels[:,:3]) + irPixels[:,0] #total intensity
intensity = np.sum(pixels[:,0:4],1) #total intensity

diffs = []
for i in range(4):
for j in range(4):
if i==j: continue
diff = (allPix[:,i] - allPix[:,j]) / intensity
diff = (pixels[:,i] - pixels[:,j]) / intensity
diffs.append(diff)

rRatio = pixelRatio(eoPixels, irPixels, "red")
gRatio = pixelRatio(eoPixels, irPixels, "green")
bRatio = pixelRatio(eoPixels, irPixels, "blue")
iRatio = pixelRatio(eoPixels, irPixels, "ir")
return np.column_stack( [rRatio, bRatio, gRatio, iRatio]+diffs )


def pixelRatio(eoPixels, irPixels, pixel_type="red"):
"""Green / (Green + Red + Blue + IR)"""
assert eoPixels.shape[0] == irPixels.shape[0]

if pixel_type=="red":
num = eoPixels[:,0]
if pixel_type=="green":
num = eoPixels[:,1]
if pixel_type=="blue":
num = eoPixels[:,2]
if pixel_type=="ir":
num = irPixels[:,0]

denom = np.sum(eoPixels[:,:3]) + irPixels[:,0]
return num / denom
ratios = []
for i in range(4):
ratio = pixels[:,i] / intensity
ratios.append(ratio)
return np.column_stack( ratios + diffs )



5 changes: 5 additions & 0 deletions render_spiral.py
Expand Up @@ -7,6 +7,11 @@


def pointsFromFile(fname):
""" Point file format:
<num points>
<x> <y> <z>
<x> <y> <z>
"""
f = open(fname, 'r')
numPts = int(f.readline())
print numPts
Expand Down

0 comments on commit 23792c4

Please sign in to comment.