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
images/Images
images/Infos
images/licenseplates
images/faulty
......@@ -3,7 +3,8 @@ from svmutil import svm_train, svm_problem, svm_parameter, svm_predict, \
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
if filename:
......@@ -18,6 +19,8 @@ class Classifier:
self.param.gamma = gamma # Parameter for radial kernel
self.model = None
self.verbose = verbose
def save(self, filename):
"""Save the SVM model in the given filename."""
svm_save_model(filename, self.model)
......@@ -30,8 +33,9 @@ class Classifier:
l = len(learning_set)
for i, char in enumerate(learning_set):
if self.verbose:
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)))
#features.append(char.get_feature_vector())
char.get_single_cell_feature_vector(self.neighbours)
......@@ -57,6 +61,7 @@ class Classifier:
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(self.neighbours)
#p = svm_predict([true_value], [character.feature], self.model, '-b 1')
p = svm_predict([true_value], [character.feature], self.model)
prediction_class = int(p[0][0])
......
......@@ -2,8 +2,10 @@ from GrayscaleImage import GrayscaleImage
from scipy.ndimage import gaussian_filter
class GaussianFilter:
"""This class can apply a Gaussian blur on an image."""
def __init__(self, scale):
"""Create a GaussianFilter object with a given scale."""
self.scale = scale
def get_filtered_copy(self, image):
......@@ -12,12 +14,15 @@ class GaussianFilter:
return GrayscaleImage(None, image)
def filter(self, image):
"""Apply a Gaussian blur on the image data."""
image.data = gaussian_filter(image.data, self.scale)
def get_scale(self):
"""Return the scale of the Gaussian kernel."""
return self.scale
def set_scale(self, scale):
"""Set the scale of the Gaussian kernel."""
self.scale = float(scale)
scale = property(get_scale, set_scale)
......@@ -57,7 +57,7 @@ class LocalBinaryPatternizer:
| (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
'''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
feature number of a pixel'''
self.setup_histograms()
......
......@@ -86,7 +86,7 @@ i = 0
for c in C:
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)
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
from matplotlib.pyplot import imshow, subplot, show
from LocalBinaryPatternizer import LocalBinaryPatternizer
from GrayscaleImage import GrayscaleImage
from cPickle import load
from numpy import zeros, resize
from numpy import zeros
chars = load(file('characters.dat', 'r'))[::2]
left = None
......
#!/usr/bin/python
from os import listdir
from cPickle import load
from sys import argv, exit
from time import time
......
from os import mkdir
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 Point import Point
from Character import Character
from GrayscaleImage import GrayscaleImage
from NormalizedCharacterImage import NormalizedCharacterImage
from LicensePlate import LicensePlate
# Gets the character data from a picture with a license plate
def retrieve_data(plate, corners):
x0,y0, x1,y1, x2,y2, x3,y3 = corners
# sets the entire license plate of an image
def retrieve_data(image, 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)
matrix = array([
......@@ -25,7 +29,7 @@ def retrieve_data(plate, corners):
[ 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)
for i in range(M):
......@@ -34,7 +38,7 @@ def retrieve_data(plate, corners):
or_coor_h = (or_coor[1][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
......@@ -46,15 +50,19 @@ def get_transformation_matrix(matrix):
U, D, V = svd(matrix)
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):
#Get the value of a point (interpolated x, y) in the given image
if not image.in_bounds(x, y):
return 0
x_low, x_high = floor(x), floor(x+1)
y_low, y_high = floor(y), floor(y+1)
if image.in_bounds(x, y):
x_low = floor(x)
x_high = floor(x + 1)
y_low = floor(y)
y_high = floor(y + 1)
x_y = (x_high - x_low) * (y_high - y_low)
a = x_high - x
......@@ -67,42 +75,44 @@ def pV(image, x, y):
+ image[x_low , y_high] / x_y * a * d \
+ image[x_high, y_high] / x_y * c * d
return 0
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)
country = ''
result = []
version = get_node(dom, "current-version")
infos = by_tag(dom, "info")
result_characters = []
for info in infos:
if not version == get_node(info, "version"):
continue
version = dom.getElementsByTagName("current-version")[0].firstChild.data
info = dom.getElementsByTagName("info")
country = get_node(info, "identification-letters")
temp = by_tag(info, "characters")
for i in info:
if version == i.getElementsByTagName("version")[0].firstChild.data:
if not temp: # no characters where found in the file
break
country = i.getElementsByTagName("identification-letters")[0].firstChild.data
temp = i.getElementsByTagName("characters")
if len(temp):
characters = temp[0].childNodes
else:
characters = []
break
for i, char in enumerate(characters):
if not char.nodeName == "character":
continue
value = get_node(char, "char")
corners = get_corners(char)
for i, character in enumerate(characters):
if character.nodeName == "character":
value = character.getElementsByTagName("char")[0].firstChild.data
corners = get_corners(character)
if not len(corners) == 8:
if not len(corners) == 4:
break
data = retrieve_data(plate, corners)
image = NormalizedCharacterImage(data=data)
result.append(Character(value, corners, image, filename))
character_data = retrieve_data(image, corners)
character_image = NormalizedCharacterImage(data=character_data)
result_characters.append(Character(value, corners, character_image, filename))
if save_character:
character_image = GrayscaleImage(data=data)
single_character = GrayscaleImage(data=character_data)
path = "../images/LearningSet/%s" % value
image_path = "%s/%d_%s.jpg" % (path, i, filename.split('/')[-1])
......@@ -110,28 +120,38 @@ def xml_to_LicensePlate(filename, save_character=None):
mkdir(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):
return by_tag(node, tag)[0].firstChild.data
def get_corners(dom):
nodes = dom.getElementsByTagName("point")
corners = []
def by_tag(node, tag):
return node.getElementsByTagName(tag)
margin_y = 3
margin_x = 2
def get_attr(node, attr):
return int(node.getAttribute(attr))
corners.append(
Point(get_coord(nodes[0], "x") - margin_x,
get_coord(nodes[0], "y") - margin_y)
)
def get_corners(dom):
p = by_tag(dom, "point")
corners.append(
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
y = 3
x = 2
return corners
# return 8 values (x0,y0, .., x3,y3)
return get_attr(p[0], "x") - x, get_attr(p[0], "y") - y,\
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
def get_coord(node, attribute):
return int(node.getAttribute(attribute))
- 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