Commit f957089b authored by Richard Torenvliet's avatar Richard Torenvliet

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

parents 728d5238 a6f929bc
...@@ -15,3 +15,4 @@ images/BBB ...@@ -15,3 +15,4 @@ images/BBB
images/Images images/Images
images/Infos images/Infos
images/licenseplates images/licenseplates
images/faulty
...@@ -3,7 +3,8 @@ from svmutil import svm_train, svm_problem, svm_parameter, svm_predict, \ ...@@ -3,7 +3,8 @@ from svmutil import svm_train, svm_problem, svm_parameter, svm_predict, \
class Classifier: class Classifier:
def __init__(self, c=None, gamma=None, filename=None, neighbours=3): def __init__(self, c=None, gamma=None, filename=None, neighbours=3, \
verbose=0):
self.neighbours = neighbours self.neighbours = neighbours
if filename: if filename:
...@@ -18,6 +19,8 @@ class Classifier: ...@@ -18,6 +19,8 @@ class Classifier:
self.param.gamma = gamma # Parameter for radial kernel self.param.gamma = gamma # Parameter for radial kernel
self.model = None self.model = None
self.verbose = verbose
def save(self, filename): def save(self, filename):
"""Save the SVM model in the given filename.""" """Save the SVM model in the given filename."""
svm_save_model(filename, self.model) svm_save_model(filename, self.model)
...@@ -30,8 +33,9 @@ class Classifier: ...@@ -30,8 +33,9 @@ class Classifier:
l = len(learning_set) l = len(learning_set)
for i, char in enumerate(learning_set): for i, char in enumerate(learning_set):
if self.verbose:
print 'Found "%s" -- %d of %d (%d%% done)' \ print 'Found "%s" -- %d of %d (%d%% done)' \
% (char.value, i + 1, l, int(100 * (i + 1) / l)) % (char.value, i + 1, l, round(100 * (i + 1) / l))
classes.append(float(ord(char.value))) classes.append(float(ord(char.value)))
#features.append(char.get_feature_vector()) #features.append(char.get_feature_vector())
char.get_single_cell_feature_vector(self.neighbours) char.get_single_cell_feature_vector(self.neighbours)
...@@ -57,6 +61,7 @@ class Classifier: ...@@ -57,6 +61,7 @@ class Classifier:
true_value = 0 if true_value == None else ord(true_value) true_value = 0 if true_value == None else ord(true_value)
#x = character.get_feature_vector(self.cell_size) #x = character.get_feature_vector(self.cell_size)
character.get_single_cell_feature_vector(self.neighbours) character.get_single_cell_feature_vector(self.neighbours)
#p = svm_predict([true_value], [character.feature], self.model, '-b 1')
p = svm_predict([true_value], [character.feature], self.model) p = svm_predict([true_value], [character.feature], self.model)
prediction_class = int(p[0][0]) prediction_class = int(p[0][0])
......
...@@ -2,8 +2,10 @@ from GrayscaleImage import GrayscaleImage ...@@ -2,8 +2,10 @@ from GrayscaleImage import GrayscaleImage
from scipy.ndimage import gaussian_filter from scipy.ndimage import gaussian_filter
class GaussianFilter: class GaussianFilter:
"""This class can apply a Gaussian blur on an image."""
def __init__(self, scale): def __init__(self, scale):
"""Create a GaussianFilter object with a given scale."""
self.scale = scale self.scale = scale
def get_filtered_copy(self, image): def get_filtered_copy(self, image):
...@@ -12,12 +14,15 @@ class GaussianFilter: ...@@ -12,12 +14,15 @@ class GaussianFilter:
return GrayscaleImage(None, image) return GrayscaleImage(None, image)
def filter(self, image): def filter(self, image):
"""Apply a Gaussian blur on the image data."""
image.data = gaussian_filter(image.data, self.scale) image.data = gaussian_filter(image.data, self.scale)
def get_scale(self): def get_scale(self):
"""Return the scale of the Gaussian kernel."""
return self.scale return self.scale
def set_scale(self, scale): def set_scale(self, scale):
"""Set the scale of the Gaussian kernel."""
self.scale = float(scale) self.scale = float(scale)
scale = property(get_scale, set_scale) scale = property(get_scale, set_scale)
...@@ -57,7 +57,7 @@ class LocalBinaryPatternizer: ...@@ -57,7 +57,7 @@ class LocalBinaryPatternizer:
| (self.is_pixel_darker(y - 2, x - 1, value)) | (self.is_pixel_darker(y - 2, x - 1, value))
def create_features_vector(self): def create_features_vector(self):
'''Walk around the pixels in clokwise order, shifting 1 bit less at '''Walk around the pixels in clockwise order, shifting 1 bit less at
each neighbour starting at 7 in the top-left corner. This gives a 8-bit each neighbour starting at 7 in the top-left corner. This gives a 8-bit
feature number of a pixel''' feature number of a pixel'''
self.setup_histograms() self.setup_histograms()
......
...@@ -86,7 +86,7 @@ i = 0 ...@@ -86,7 +86,7 @@ i = 0
for c in C: for c in C:
for y in Y: for y in Y:
classifier = Classifier(c=c, gamma=y, neighbours=neighbours) classifier = Classifier(c=c, gamma=y, neighbours=neighbours, verbose=1)
classifier.train(learning_set) classifier.train(learning_set)
result = classifier.test(test_set) result = classifier.test(test_set)
......
#!/usr/bin/python
from cPickle import load
from sys import argv, exit
from pylab import imsave, plot, subplot, imshow, show, axis, title
from math import sqrt, ceil
import os
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)
test_set_file = 'test_set%s.dat' % suffix
classifier_file = 'classifier%s.dat' % suffix
print 'Loading classifier...'
classifier = Classifier(filename=classifier_file)
classifier.neighbours = neighbours
print 'Loading test set...'
test_set = load(file(test_set_file, 'r'))
l = len(test_set)
matches = 0
#classified = {}
classified = []
for i, char in enumerate(test_set):
prediction = classifier.classify(char, char.value)
if char.value != prediction:
classified.append((char, prediction))
#key = '%s_as_%s' % (char.value, prediction)
#if key not in classified:
# classified[key] = [char]
#else:
# classified[key].append(char)
print '"%s" was classified as "%s"' \
% (char.value, prediction)
else:
matches += 1
print '%d of %d (%d%% done)' % (i + 1, l, round(100 * (i + 1) / l))
print '\n%d matches (%d%%), %d fails' % (matches, \
round(100 * matches / l), \
len(test_set) - matches)
# Show a grid plot of all faulty classified characters
print 'Plotting faulty classified characters...'
rows = int(ceil(sqrt(l - matches)))
columns = int(ceil((l - matches) / float(rows)))
for i, pair in enumerate(classified):
char, prediction = pair
subplot(rows, columns, i + 1)
title('%s as %s' % (char.value, prediction))
imshow(char.image.data, cmap='gray')
axis('off')
show()
#print 'Saving faulty classified characters...'
#folder = '../images/faulty/'
#
#if not os.path.exists(folder):
# os.mkdir(folder)
#
#for filename, chars in classified.iteritems():
# if len(chars) == 1:
# imsave('%s%s' % (folder, filename), char.image.data, cmap='gray')
# else:
# for i, char in enumerate(chars):
# imsave('%s%s_%d' % (folder, filename, i), char.image.data, cmap='gray')
#!/usr/bin/python
from cPickle import dump, load
from Classifier import Classifier
if len(argv) < 5:
print 'Usage: python %s FILE_SUFFIX C GAMMA NEIGHBOURS' % argv[0]
exit(1)
print 'Loading learning set'
learning_set = load(file('learning_set%s.dat' % argv[1], 'r'))
# Train the classifier with the learning set
classifier = Classifier(c=float(argv[1]), \
gamma=float(argv[2]), \
neighbours=int(argv[3]))
classifier.train(learning_set)
print 'Loading test set'
test_set = load(file('test_set%s.dat' % argv[1], 'r'))
l = len(test_set)
matches = 0
for i, char in enumerate(test_set):
prediction = classifier.classify(char, char.value)
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)
#!/usr/bin/python #!/usr/bin/python
from matplotlib.pyplot import imshow, subplot, show from matplotlib.pyplot import imshow, subplot, show
from LocalBinaryPatternizer import LocalBinaryPatternizer from LocalBinaryPatternizer import LocalBinaryPatternizer
from GrayscaleImage import GrayscaleImage
from cPickle import load from cPickle import load
from numpy import zeros, resize from numpy import zeros
chars = load(file('characters.dat', 'r'))[::2] chars = load(file('characters.dat', 'r'))[::2]
left = None left = None
......
#!/usr/bin/python #!/usr/bin/python
from os import listdir from os import listdir
from cPickle import load
from sys import argv, exit from sys import argv, exit
from time import time from time import time
......
from os import mkdir from os import mkdir
from os.path import exists from os.path import exists
from pylab import imsave, array, zeros, inv, dot, norm, svd, floor from pylab import array, zeros, inv, dot, svd, floor
from xml.dom.minidom import parse from xml.dom.minidom import parse
from Point import Point
from Character import Character from Character import Character
from GrayscaleImage import GrayscaleImage from GrayscaleImage import GrayscaleImage
from NormalizedCharacterImage import NormalizedCharacterImage from NormalizedCharacterImage import NormalizedCharacterImage
from LicensePlate import LicensePlate from LicensePlate import LicensePlate
# Gets the character data from a picture with a license plate # sets the entire license plate of an image
def retrieve_data(plate, corners): def retrieve_data(image, corners):
x0,y0, x1,y1, x2,y2, x3,y3 = corners x0, y0 = corners[0].to_tuple()
x1, y1 = corners[1].to_tuple()
x2, y2 = corners[2].to_tuple()
x3, y3 = corners[3].to_tuple()
M = max(x0, x1, x2, x3) - min(x0, x1, x2, x3) M = int(1.2 * (max(x0, x1, x2, x3) - min(x0, x1, x2, x3)))
N = max(y0, y1, y2, y3) - min(y0, y1, y2, y3) N = max(y0, y1, y2, y3) - min(y0, y1, y2, y3)
matrix = array([ matrix = array([
...@@ -25,7 +29,7 @@ def retrieve_data(plate, corners): ...@@ -25,7 +29,7 @@ def retrieve_data(plate, corners):
[ 0, 0, 0, x3, y3, 1, -N * x3, -N * y3, -N] [ 0, 0, 0, x3, y3, 1, -N * x3, -N * y3, -N]
]) ])
P = get_transformation_matrix(matrix) P = inv(get_transformation_matrix(matrix))
data = array([zeros(M, float)] * N) data = array([zeros(M, float)] * N)
for i in range(M): for i in range(M):
...@@ -34,7 +38,7 @@ def retrieve_data(plate, corners): ...@@ -34,7 +38,7 @@ def retrieve_data(plate, corners):
or_coor_h = (or_coor[1][0] / or_coor[2][0], or_coor_h = (or_coor[1][0] / or_coor[2][0],
or_coor[0][0] / or_coor[2][0]) or_coor[0][0] / or_coor[2][0])
data[j][i] = pV(plate, or_coor_h[0], or_coor_h[1]) data[j][i] = pV(image, or_coor_h[0], or_coor_h[1])
return data return data
...@@ -46,15 +50,19 @@ def get_transformation_matrix(matrix): ...@@ -46,15 +50,19 @@ def get_transformation_matrix(matrix):
U, D, V = svd(matrix) U, D, V = svd(matrix)
p = V[8][:] p = V[8][:]
return inv(array([[p[0],p[1],p[2]], [p[3],p[4],p[5]], [p[6],p[7],p[8]]])) return array([
[ p[0], p[1], p[2] ],
[ p[3], p[4], p[5] ],
[ p[6], p[7], p[8] ]
])
def pV(image, x, y): def pV(image, x, y):
#Get the value of a point (interpolated x, y) in the given image #Get the value of a point (interpolated x, y) in the given image
if not image.in_bounds(x, y): if image.in_bounds(x, y):
return 0 x_low = floor(x)
x_high = floor(x + 1)
x_low, x_high = floor(x), floor(x+1) y_low = floor(y)
y_low, y_high = floor(y), floor(y+1) y_high = floor(y + 1)
x_y = (x_high - x_low) * (y_high - y_low) x_y = (x_high - x_low) * (y_high - y_low)
a = x_high - x a = x_high - x
...@@ -67,42 +75,44 @@ def pV(image, x, y): ...@@ -67,42 +75,44 @@ def pV(image, x, y):
+ image[x_low , y_high] / x_y * a * d \ + image[x_low , y_high] / x_y * a * d \
+ image[x_high, y_high] / x_y * c * d + image[x_high, y_high] / x_y * c * d
return 0
def xml_to_LicensePlate(filename, save_character=None): def xml_to_LicensePlate(filename, save_character=None):
plate = GrayscaleImage('../images/Images/%s.jpg' % filename) image = GrayscaleImage('../images/Images/%s.jpg' % filename)
dom = parse('../images/Infos/%s.info' % filename) dom = parse('../images/Infos/%s.info' % filename)
country = '' result_characters = []
result = []
version = get_node(dom, "current-version")
infos = by_tag(dom, "info")
for info in infos: version = dom.getElementsByTagName("current-version")[0].firstChild.data
if not version == get_node(info, "version"): info = dom.getElementsByTagName("info")
continue
country = get_node(info, "identification-letters") for i in info:
temp = by_tag(info, "characters") if version == i.getElementsByTagName("version")[0].firstChild.data:
if not temp: # no characters where found in the file country = i.getElementsByTagName("identification-letters")[0].firstChild.data
break temp = i.getElementsByTagName("characters")
if len(temp):
characters = temp[0].childNodes characters = temp[0].childNodes
else:
characters = []
break
for i, char in enumerate(characters): for i, character in enumerate(characters):
if not char.nodeName == "character": if character.nodeName == "character":
continue value = character.getElementsByTagName("char")[0].firstChild.data
corners = get_corners(character)
value = get_node(char, "char")
corners = get_corners(char)
if not len(corners) == 8: if not len(corners) == 4:
break break
data = retrieve_data(plate, corners) character_data = retrieve_data(image, corners)
image = NormalizedCharacterImage(data=data) character_image = NormalizedCharacterImage(data=character_data)
result.append(Character(value, corners, image, filename))
result_characters.append(Character(value, corners, character_image, filename))
if save_character: if save_character:
character_image = GrayscaleImage(data=data) single_character = GrayscaleImage(data=character_data)
path = "../images/LearningSet/%s" % value path = "../images/LearningSet/%s" % value
image_path = "%s/%d_%s.jpg" % (path, i, filename.split('/')[-1]) image_path = "%s/%d_%s.jpg" % (path, i, filename.split('/')[-1])
...@@ -110,28 +120,38 @@ def xml_to_LicensePlate(filename, save_character=None): ...@@ -110,28 +120,38 @@ def xml_to_LicensePlate(filename, save_character=None):
mkdir(path) mkdir(path)
if not exists(image_path): if not exists(image_path):
character_image.save(image_path) single_character.save(image_path)
return LicensePlate(country, result) return LicensePlate(country, result_characters)
def get_node(node, tag): def get_corners(dom):
return by_tag(node, tag)[0].firstChild.data nodes = dom.getElementsByTagName("point")
corners = []
def by_tag(node, tag): margin_y = 3
return node.getElementsByTagName(tag) margin_x = 2
def get_attr(node, attr): corners.append(
return int(node.getAttribute(attr)) Point(get_coord(nodes[0], "x") - margin_x,
get_coord(nodes[0], "y") - margin_y)
)
def get_corners(dom): corners.append(
p = by_tag(dom, "point") Point(get_coord(nodes[1], "x") + margin_x,
get_coord(nodes[1], "y") - margin_y)
)
corners.append(
Point(get_coord(nodes[2], "x") + margin_x,
get_coord(nodes[2], "y") + margin_y)
)
corners.append(
Point(get_coord(nodes[3], "x") - margin_x,
get_coord(nodes[3], "y") + margin_y)
)
# Extra padding return corners
y = 3
x = 2
# return 8 values (x0,y0, .., x3,y3) def get_coord(node, attribute):
return get_attr(p[0], "x") - x, get_attr(p[0], "y") - y,\ return int(node.getAttribute(attribute))
get_attr(p[1], "x") + x, get_attr(p[1], "y") - y,\
get_attr(p[2], "x") + x, get_attr(p[2], "y") + y,\
get_attr(p[3], "x") - x, get_attr(p[3], "y") + y
- Beste classifier runnen en kijken welke karakters fout gaan
- code documenteren
- verslag: conclusies aan parameters verbinden
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