Commit 8c3cfd52 authored by Richard Torenvliet's avatar Richard Torenvliet

Merge branch 'master' of github.com:taddeus/licenseplates

parents 2c68e580 df98d883
......@@ -172,11 +172,7 @@ order. Starting with dividing the pattern in to cells of size 16.
result is a feature vector of the image.
\item Feed these vectors to a support vector machine. This will ''learn'' which
<<<<<<< HEAD
vector indicates what vector is which character.
=======
vectors indicate what letter.
>>>>>>> 2e1b2e8c8db4f802d203791a6f03eeca7d0aff70
\end{itemize}
......
*.dat
results.txt
results*.txt
......@@ -7,11 +7,12 @@ class Character:
self.image = image
self.filename = filename
def get_single_cell_feature_vector(self):
def get_single_cell_feature_vector(self, neighbours=5):
if hasattr(self, 'feature'):
return
self.feature = LBP(self.image).single_cell_features_vector()
pattern = LBP(self.image, neighbours=neighbours)
self.feature = pattern.single_cell_features_vector()
def get_feature_vector(self, cell_size=None):
pattern = LBP(self.image) if cell_size == None \
......
......@@ -3,8 +3,8 @@ from svmutil import svm_train, svm_problem, svm_parameter, svm_predict, \
class Classifier:
def __init__(self, c=None, gamma=None, filename=None, cell_size=12):
self.cell_size = cell_size
def __init__(self, c=None, gamma=None, filename=None, neighbours=3):
self.neighbours = neighbours
if filename:
# If a filename is given, load a model from the given filename
......@@ -34,7 +34,7 @@ class Classifier:
% (char.value, i + 1, l, int(100 * (i + 1) / l))
classes.append(float(ord(char.value)))
#features.append(char.get_feature_vector())
char.get_single_cell_feature_vector()
char.get_single_cell_feature_vector(self.neighbours)
features.append(char.feature)
problem = svm_problem(classes, features)
......@@ -56,7 +56,7 @@ class Classifier:
"""Classify a character object, return its value."""
true_value = 0 if true_value == None else ord(true_value)
#x = character.get_feature_vector(self.cell_size)
character.get_single_cell_feature_vector()
character.get_single_cell_feature_vector(self.neighbours)
p = svm_predict([true_value], [character.feature], self.model)
prediction_class = int(p[0][0])
......
......@@ -3,9 +3,13 @@ from math import ceil
class LocalBinaryPatternizer:
def __init__(self, image, cell_size=16):
def __init__(self, image, cell_size=16, neighbours=3):
self.cell_size = cell_size
self.image = image
self.pattern_callback, self.bins = {
3: (self.pattern_3x3, 256),
5: (self.pattern_5x5, 4096)
}[neighbours]
def setup_histograms(self):
cells_in_width = int(ceil(self.image.width / float(self.cell_size)))
......@@ -16,9 +20,9 @@ class LocalBinaryPatternizer:
self.histograms.append([])
for j in xrange(cells_in_width):
self.histograms[i].append(Histogram(256, 0, 256))
self.histograms[i].append(Histogram(self.bins, 0, self.bins))
def local_binary_pattern(self, y, x, value):
def pattern_3x3(self, y, x, value):
return (self.is_pixel_darker(y - 1, x - 1, value) << 7) \
| (self.is_pixel_darker(y - 1, x , value) << 6) \
| (self.is_pixel_darker(y - 1, x + 1, value) << 5) \
......@@ -26,7 +30,21 @@ class LocalBinaryPatternizer:
| (self.is_pixel_darker(y + 1, x + 1, value) << 3) \
| (self.is_pixel_darker(y + 1, x , value) << 2) \
| (self.is_pixel_darker(y + 1, x - 1, value) << 1) \
| (self.is_pixel_darker(y , x - 1, value) << 0)
| (self.is_pixel_darker(y , x - 1, value))
def pattern_5x5(self, y, x, value):
return (self.is_pixel_darker(y - 1, x - 2, value) << 11) \
| (self.is_pixel_darker(y , x - 2, value) << 10) \
| (self.is_pixel_darker(y + 1, x - 2, value) << 9) \
| (self.is_pixel_darker(y + 2, x - 1, value) << 8) \
| (self.is_pixel_darker(y + 2, x , value) << 7) \
| (self.is_pixel_darker(y + 2, x + 1, value) << 6) \
| (self.is_pixel_darker(y + 1, x + 2, value) << 5) \
| (self.is_pixel_darker(y , x + 2, value) << 4) \
| (self.is_pixel_darker(y - 1, x + 2, value) << 3) \
| (self.is_pixel_darker(y - 2, x + 1, value) << 2) \
| (self.is_pixel_darker(y - 2, x , value) << 1) \
| (self.is_pixel_darker(y - 2, x - 1, value))
def create_features_vector(self):
'''Walk around the pixels in clokwise order, shifting 1 bit less at
......@@ -36,7 +54,7 @@ class LocalBinaryPatternizer:
for y, x, value in self.image:
cy, cx = self.get_cell_index(y, x)
self.histograms[cy][cx].add(self.local_binary_pattern(y, x, value))
self.histograms[cy][cx].add(self.pattern_callback(y, x, value))
return self.get_features_as_array()
......@@ -55,15 +73,14 @@ class LocalBinaryPatternizer:
f.extend(hist.bins)
return f
#return [h.bins for h in [h for sub in self.histograms for h in sub]][0]
def get_single_histogram(self):
"""Create a single histogram of the local binary patterns in the
image."""
h = Histogram(256, 0, 256)
h = Histogram(self.bins, 0, self.bins)
for y, x, value in self.image:
h.add(self.local_binary_pattern(y, x, value))
h.add(self.pattern_callback(y, x, value))
h.normalize()
......
......@@ -5,19 +5,22 @@ from GaussianFilter import GaussianFilter
class NormalizedCharacterImage(GrayscaleImage):
def __init__(self, image=None, data=None, size=(60, 40), blur=1.1, \
crop_threshold=0.9):
def __init__(self, image=None, data=None, height=None, blur=1.1):
if image != None:
GrayscaleImage.__init__(self, data=deepcopy(image.data))
elif data != None:
GrayscaleImage.__init__(self, data=deepcopy(data))
self.blur = blur
self.crop_threshold = crop_threshold
self.size = size
self.gaussian_filter()
self.increase_contrast()
#self.crop_threshold = crop_threshold
#self.crop_to_letter()
#self.resize()
self.height = height
self.resize()
def increase_contrast(self):
self.data -= self.data.min()
......@@ -31,4 +34,9 @@ class NormalizedCharacterImage(GrayscaleImage):
cropper.crop_to_letter(self)
def resize(self):
GrayscaleImage.resize(self, self.size)
"""Resize the image to a fixed height."""
if self.height == None:
return
h, w = self.data.shape
GrayscaleImage.resize(self, (self.height, self.height * w / h))
#!/usr/bin/python
from cPickle import load
from os import listdir
from os.path import exists
from cPickle import load, dump
from sys import argv, exit
from GrayscaleImage import GrayscaleImage
from NormalizedCharacterImage import NormalizedCharacterImage
from Character import Character
from Classifier import Classifier
if len(argv) < 3:
print 'Usage: python %s NEIGHBOURS BLUR_SCALE' % argv[0]
exit(1)
neighbours = int(argv[1])
blur_scale = float(argv[2])
suffix = '_%s_%s' % (blur_scale, neighbours)
chars_file = 'characters%s.dat' % suffix
learning_set_file = 'learning_set%s.dat' % suffix
test_set_file = 'test_set%s.dat' % suffix
classifier_file = 'classifier%s.dat' % suffix
results_file = 'results%s.txt' % suffix
# Load characters
if exists(chars_file):
print 'Loading characters...'
chars = load(open(chars_file, 'r'))
else:
print 'Going to generate character objects...'
chars = []
for char in sorted(listdir('../images/LearningSet')):
for image in sorted(listdir('../images/LearningSet/' + char)):
f = '../images/LearningSet/' + char + '/' + image
image = GrayscaleImage(f)
norm = NormalizedCharacterImage(image, blur=blur_scale, height=42)
#imshow(norm.data, cmap='gray'); show()
character = Character(char, [], norm)
character.get_single_cell_feature_vector(neighbours)
chars.append(character)
print char
print 'Saving characters...'
dump(chars, open(chars_file, 'w+'))
# Load learning set and test set
if exists(learning_set_file):
print 'Loading learning set...'
learning_set = load(open(learning_set_file, 'r'))
print 'Learning set:', [c.value for c in learning_set]
print 'Loading test set...'
test_set = load(open(test_set_file, 'r'))
print 'Test set:', [c.value for c in test_set]
else:
print 'Going to generate learning set and test set...'
learning_set = []
test_set = []
learned = []
for char in chars:
if learned.count(char.value) == 70:
test_set.append(char)
else:
learning_set.append(char)
learned.append(char.value)
print 'Learning set:', [c.value for c in learning_set]
print '\nTest set:', [c.value for c in test_set]
print '\nSaving learning set...'
dump(learning_set, file(learning_set_file, 'w+'))
print 'Saving test set...'
dump(test_set, file(test_set_file, 'w+'))
# Perform a grid-search to find the optimal values for C and gamma
C = [float(2 ** p) for p in xrange(-5, 16, 2)]
Y = [float(2 ** p) for p in xrange(-15, 4, 2)]
best_classifier = None
print 'Loading learning set...'
learning_set = load(file('learning_set.dat', 'r'))
print 'Learning set:', [c.value for c in learning_set]
print 'Loading test set...'
test_set = load(file('test_set.dat', 'r'))
print 'Test set:', [c.value for c in test_set]
# Perform a grid-search on different combinations of soft margin and gamma
results = []
best = (0,)
i = 0
for c in C:
for y in Y:
classifier = Classifier(c=c, gamma=y)
classifier = Classifier(c=c, gamma=y, neighbours=neighbours)
classifier.train(learning_set)
result = classifier.test(test_set)
......@@ -33,22 +99,30 @@ for c in C:
% (i, len(C) * len(Y), c, y, int(round(result * 100)))
i = 0
s = ' c\y'
print '\n c\y',
for y in Y:
print '| %f' % y,
s += '| %f' % y
print
s += '\n'
for c in C:
print ' %7s' % c,
s += ' %7s' % c
for y in Y:
print '| %8d' % int(round(results[i] * 100)),
s += '| %8d' % int(round(results[i] * 100))
i += 1
print
s += '\n'
s += '\nBest result: %.3f%% for C = %f and gamma = %f' % best[:3]
print 'Saving results...'
f = open(results_file, 'w+')
f.write(s + '\n')
f.close()
print '\nBest result: %.3f%% for C = %f and gamma = %f' % best[:3]
print 'Saving best classifier...'
best[3].save(classifier_file)
best[3].save('classifier.dat')
print '\n' + s
#!/usr/bin/python
from os import listdir
from cPickle import dump
from pylab import imshow, show
from sys import argv, exit
from GrayscaleImage import GrayscaleImage
from NormalizedCharacterImage import NormalizedCharacterImage
from Character import Character
if len(argv) < 4:
print 'Usage: python %s FILE_SUFFIX BLUR_SCALE NEIGHBOURS' % argv[0]
exit(1)
c = []
for char in sorted(listdir('../images/LearningSet')):
for image in sorted(listdir('../images/LearningSet/' + char)):
f = '../images/LearningSet/' + char + '/' + image
image = GrayscaleImage(f)
norm = NormalizedCharacterImage(image, blur=1, size=(48, 36))
#imshow(norm.data, cmap='gray')
#show()
norm = NormalizedCharacterImage(image, blur=float(argv[2]), height=42)
#from pylab import imshow, show
#imshow(norm.data, cmap='gray'); show()
character = Character(char, [], norm)
character.get_single_cell_feature_vector()
character.get_single_cell_feature_vector(int(argv[3]))
c.append(character)
print char
dump(c, open('characters.dat', 'w+'))
print 'Saving characters...'
dump(c, open('characters%s.dat' % argv[1], 'w+'))
#!/usr/bin/python
from cPickle import dump, load
from sys import argv, exit
if len(argv) < 2:
print 'Usage: python %s FILE_SUFFIX' % argv[0]
exit(1)
print 'Loading characters...'
chars = load(file('characters%s.dat' % argv[1], 'r'))
learning_set = []
test_set = []
#s = {}
#
#for char in chars:
# if char.value not in s:
# s[char.value] = [char]
# else:
# s[char.value].append(char)
#
#for value, chars in s.iteritems():
# learning_set += chars[::2]
# test_set += chars[1::2]
learned = []
for char in chars:
if learned.count(char.value) == 70:
test_set.append(char)
else:
learning_set.append(char)
learned.append(char.value)
print 'Learning set:', [c.value for c in learning_set]
print '\nTest set:', [c.value for c in test_set]
print '\nSaving learning set...'
dump(learning_set, file('learning_set%s.dat' % argv[1], 'w+'))
print 'Saving test set...'
dump(test_set, file('test_set%s.dat' % argv[1], 'w+'))
#!/usr/bin/python
from xml_helper_functions import xml_to_LicensePlate
from Classifier import Classifier
from cPickle import dump, load
chars = load(file('characters.dat', 'r'))
learning_set = []
test_set = []
#s = {}
#
#for char in chars:
# if char.value not in s:
# s[char.value] = [char]
# else:
# s[char.value].append(char)
#
#for value, chars in s.iteritems():
# learning_set += chars[::2]
# test_set += chars[1::2]
learned = []
from Classifier import Classifier
for char in chars:
if learned.count(char.value) == 70:
test_set.append(char)
else:
learning_set.append(char)
learned.append(char.value)
if len(argv) < 5:
print 'Usage: python %s FILE_SUFFIX C GAMMA NEIGHBOURS' % argv[0]
exit(1)
print 'Learning set:', [c.value for c in learning_set]
print 'Test set:', [c.value for c in test_set]
print 'Saving learning set...'
dump(learning_set, file('learning_set.dat', 'w+'))
print 'Saving test set...'
dump(test_set, file('test_set.dat', 'w+'))
#----------------------------------------------------------------
print 'Loading learning set'
learning_set = load(file('learning_set.dat', 'r'))
learning_set = load(file('learning_set%s.dat' % argv[1], 'r'))
# Train the classifier with the learning set
classifier = Classifier(c=512, gamma=.125, cell_size=12)
classifier = Classifier(c=float(argv[1]), \
gamma=float(argv[2]), \
neighbours=int(argv[3]))
classifier.train(learning_set)
classifier.save('classifier.dat')
print 'Saved classifier'
#----------------------------------------------------------------
print 'Loading classifier'
classifier = Classifier(filename='classifier.dat')
print 'Loading test set'
test_set = load(file('test_set.dat', 'r'))
test_set = load(file('test_set%s.dat' % argv[1], 'r'))
l = len(test_set)
matches = 0
......
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