Commit e2507c65 authored by Taddeüs Kroes's avatar Taddeüs Kroes

Implemented SVM classifier and added test file to test it.

parent cce4f7e3
...@@ -7,3 +7,14 @@ ...@@ -7,3 +7,14 @@
*.synctex.gz *.synctex.gz
*.toc *.toc
*.out *.out
*.jpg
images/BBB
images/Images
images/Infos
images/licenseplates
chars
learning_set
test_set
classifier
classifier-model
classifier-characters
# TODO cleanup the getElements stuff from LocalBinaryPatternizer import LocalBinaryPatternizer
class Character: class Character:
def __init__(self, value, corners, image): def __init__(self, value, corners, image):
self.value = value self.value = value
...@@ -12,4 +13,6 @@ class Character: ...@@ -12,4 +13,6 @@ class Character:
show() show()
def get_feature_vector(self): def get_feature_vector(self):
pass pattern = LocalBinaryPatternizer(self.image)
return pattern.create_features_vector()
from svmutil import svm_model, svm_problem, svm_parameter, svm_predict, LINEAR from svmutil import svm_train, svm_problem, svm_parameter, svm_predict, \
from cPicle import dump, load LINEAR, svm_save_model, svm_load_model
from cPickle import dump, load
class Classifier: class Classifier:
def __init__(self, c=None, filename=None): def __init__(self, c=None, filename=None):
if filename: if filename:
# If a filename is given, load a modl from the fiven filename # If a filename is given, load a modl from the fiven filename
f = file(filename, 'r') self.model = svm_load_model(filename + '-model')
self.model, self.param, self.character_map = load(f) f = file(filename + '-characters', 'r')
self.character_map = load(f)
f.close() f.close()
else: else:
self.param = svm_parameter() self.param = svm_parameter()
...@@ -18,8 +20,9 @@ class Classifier: ...@@ -18,8 +20,9 @@ class Classifier:
def save(self, filename): def save(self, filename):
"""Save the SVM model in the given filename.""" """Save the SVM model in the given filename."""
f = file(filename, 'w+') svm_save_model(filename + '-model', self.model)
dump((self.model, self.param, self.character_map), f) f = file(filename + '-characters', 'w+')
dump(self.character_map, f)
f.close() f.close()
def train(self, learning_set): def train(self, learning_set):
...@@ -27,8 +30,11 @@ class Classifier: ...@@ -27,8 +30,11 @@ class Classifier:
known values.""" known values."""
classes = [] classes = []
features = [] features = []
l = len(learning_set)
for char in learning_set: for i, char in enumerate(learning_set):
print 'Training "%s" -- %d of %d (%d%% done)' \
% (char.value, i + 1, l, int(100 * (i + 1) / l))
# Map the character to an integer for use in the SVM model # Map the character to an integer for use in the SVM model
if char.value not in self.character_map: if char.value not in self.character_map:
self.character_map[char.value] = len(self.character_map) self.character_map[char.value] = len(self.character_map)
...@@ -36,15 +42,13 @@ class Classifier: ...@@ -36,15 +42,13 @@ class Classifier:
classes.append(self.character_map[char.value]) classes.append(self.character_map[char.value])
features.append(char.get_feature_vector()) features.append(char.get_feature_vector())
problem = svm_problem(self.c, features) problem = svm_problem(classes, features)
self.model = svm_model(problem, self.param) self.model = svm_train(problem, self.param)
# Add prediction function that returns a numeric class prediction
self.model.predict = lambda self, x: svm_predict([0], [x], self)[0][0]
def classify(self, character): def classify(self, character):
"""Classify a character object and assign its value.""" """Classify a character object and assign its value."""
prediction = self.model.predict(character.get_feature_vector()) predict = lambda x: svm_predict([0], [x], self.model)[0][0]
prediction = predict(character.get_feature_vector())
for value, svm_class in self.character_map.iteritems(): for value, svm_class in self.character_map.iteritems():
if svm_class == prediction: if svm_class == prediction:
......
#!/usr/bin/python
from LicensePlate import LicensePlate
from Classifier import Classifier
from cPickle import dump, load
#chars = []
#
#for i in range(9):
# for j in range(100):
# try:
# filename = '%04d/00991_%04d%02d.info' % (i, i, j)
# print 'loading file "%s"' % filename
# plate = LicensePlate(i, j)
#
# if hasattr(plate, 'characters'):
# chars.extend(plate.characters)
# except:
# print 'epic fail'
#
#print 'loaded %d chars' % len(chars)
#
#dump(chars, file('chars', 'w+'))
#----------------------------------------------------------------
#chars = load(file('chars', 'r'))
#learned = []
#learning_set = []
#test_set = []
#
#for char in chars:
# if learned.count(char.value) > 80:
# test_set.append(char)
# else:
# learning_set.append(char)
# learned.append(char.value)
#
#dump(learning_set, file('learning_set', 'w+'))
#dump(test_set, file('test_set', 'w+'))
#----------------------------------------------------------------
learning_set = load(file('learning_set', 'r'))
# Train the classifier with the learning set
classifier = Classifier(c=3)
classifier.train(learning_set)
#classifier.save('classifier')
#----------------------------------------------------------------
#classifier = Classifier(filename='classifier')
#test_set = load(file('test_set', 'r'))
#l = len(test_set)
#matches = 0
#
#for i, char in enumerate(test_set):
# prediction = classifier.classify(char)
#
# if char.value == prediction:
# print ':) ------> Successfully recognized "%s"' % char.value
# matches += 1
# else:
# print ':( Expected character "%s", got "%s"' \
# % (char.value, prediction),
#
# print ' -- %d of %d (%d%% done)' % (i + 1, l, int(100 * (i + 1) / l))
#
#print '\n%d matches (%d%%), %d fails' % (matches, \
# int(100 * matches / len(test_set)), \
# len(test_set) - matches)
...@@ -4,6 +4,7 @@ from Error import Error ...@@ -4,6 +4,7 @@ from Error import Error
from Point import Point from Point import Point
from Character import Character from Character import Character
from GrayscaleImage import GrayscaleImage from GrayscaleImage import GrayscaleImage
from NormalizedCharacterImage import NormalizedCharacterImage
''' '''
Creates a license plate object based on an XML file. The image should be Creates a license plate object based on an XML file. The image should be
...@@ -13,15 +14,13 @@ from GrayscaleImage import GrayscaleImage ...@@ -13,15 +14,13 @@ from GrayscaleImage import GrayscaleImage
''' '''
class LicensePlate: class LicensePlate:
def __init__(self, xml_title): def __init__(self, folder_nr, file_nr):
try: filename = '%04d/00991_%04d%02d' % (folder_nr, folder_nr, file_nr)
self.dom = parse('../XML/' + str(xml_title))
except IOError: self.dom = parse('../images/Infos/%s.info' % filename)
Error("Incorrect file name given.")
else:
properties = self.get_properties() properties = self.get_properties()
self.image = GrayscaleImage('../images/' + str(properties['uii']) + '.' + str(properties['type'])) self.image = GrayscaleImage('../images/Images/%s.jpg' % filename)
self.width = int(properties['width']) self.width = int(properties['width'])
self.height = int(properties['height']) self.height = int(properties['height'])
......
...@@ -45,4 +45,4 @@ class LocalBinaryPatternizer: ...@@ -45,4 +45,4 @@ class LocalBinaryPatternizer:
return (y / self.cell_size, x / self.cell_size) return (y / self.cell_size, x / self.cell_size)
def get_features_as_array(self): def get_features_as_array(self):
return [item for sublist in self.features for item in sublist] return [h.bins for h in [h for sub in self.features for h in sub]][0]
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment