Commit 0dcaa652 authored by Richard Torenvliet's avatar Richard Torenvliet

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

Conflicts:
	docs/report.tex
parents 16018f03 6043646c
docs/codediagram.png

133 KB | W: | H:

docs/codediagram.png

113 KB | W: | H:

docs/codediagram.png
docs/codediagram.png
docs/codediagram.png
docs/codediagram.png
  • 2-up
  • Swipe
  • Onion skin
No preview for this file type
This diff is collapsed.
This diff is collapsed.
...@@ -8,6 +8,8 @@ class Character: ...@@ -8,6 +8,8 @@ class Character:
self.filename = filename self.filename = filename
def get_single_cell_feature_vector(self, neighbours=5): def get_single_cell_feature_vector(self, neighbours=5):
"""Get the histogram of Local Binary Patterns over this entire
image."""
if hasattr(self, 'feature'): if hasattr(self, 'feature'):
return return
...@@ -15,6 +17,7 @@ class Character: ...@@ -15,6 +17,7 @@ class Character:
self.feature = pattern.single_cell_features_vector() self.feature = pattern.single_cell_features_vector()
def get_feature_vector(self, cell_size=None): def get_feature_vector(self, cell_size=None):
"""Get the concatenated histograms of Local Binary Patterns. """
pattern = LBP(self.image) if cell_size == None \ pattern = LBP(self.image) if cell_size == None \
else LBP(self.image, cell_size) else LBP(self.image, cell_size)
......
from svmutil import svm_train, svm_problem, svm_parameter, svm_predict, \ from svmutil import svm_train, svm_problem, svm_parameter, svm_predict, \
svm_save_model, svm_load_model, RBF svm_save_model, svm_load_model, RBF
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): verbose=0):
self.neighbours = neighbours
if filename: if filename:
# If a filename is given, load a model from the given filename # If a filename is given, load a model from the given filename
self.model = svm_load_model(filename) self.model = svm_load_model(filename)
...@@ -19,6 +16,7 @@ class Classifier: ...@@ -19,6 +16,7 @@ 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.neighbours = neighbours
self.verbose = verbose self.verbose = verbose
def save(self, filename): def save(self, filename):
......
...@@ -22,20 +22,6 @@ class GrayscaleImage: ...@@ -22,20 +22,6 @@ class GrayscaleImage:
for x in xrange(self.data.shape[1]): for x in xrange(self.data.shape[1]):
yield y, x, self.data[y, x] yield y, x, self.data[y, x]
#self.__i_x = -1
#self.__i_y = 0
#return self
#def next(self):
# self.__i_x += 1
# if self.__i_x == self.width:
# self.__i_x = 0
# self.__i_y += 1
# if self.__i_y == self.height:
# raise StopIteration
# return self.__i_y, self.__i_x, self[self.__i_y, self.__i_x]
def __getitem__(self, position): def __getitem__(self, position):
return self.data[position] return self.data[position]
......
...@@ -6,13 +6,9 @@ class Histogram: ...@@ -6,13 +6,9 @@ class Histogram:
self.max = max self.max = max
def add(self, number): def add(self, number):
#bin_index = self.get_bin_index(number)
#self.bins[bin_index] += 1
self.bins[number] += 1 self.bins[number] += 1
def remove(self, number): def remove(self, number):
#bin_index = self.get_bin_index(number)
#self.bins[bin_index] -= 1
self.bins[number] -= 1 self.bins[number] -= 1
def get_bin_index(self, number): def get_bin_index(self, number):
......
...@@ -13,14 +13,16 @@ class NormalizedCharacterImage(GrayscaleImage): ...@@ -13,14 +13,16 @@ class NormalizedCharacterImage(GrayscaleImage):
self.blur = blur self.blur = blur
self.gaussian_filter() self.gaussian_filter()
self.increase_contrast() #self.increase_contrast()
self.height = height self.height = height
self.resize() self.resize()
def increase_contrast(self): # def increase_contrast(self):
self.data -= self.data.min() # """Increase the contrast by performing a grayscale mapping from the
self.data = self.data.astype(float) / self.data.max() # current maximum and minimum to a range between 0 and 1."""
# self.data -= self.data.min()
# self.data = self.data.astype(float) / self.data.max()
def gaussian_filter(self): def gaussian_filter(self):
GaussianFilter(self.blur).filter(self) GaussianFilter(self.blur).filter(self)
......
...@@ -80,6 +80,7 @@ def load_test_set(neighbours, blur_scale, verbose=0): ...@@ -80,6 +80,7 @@ def load_test_set(neighbours, blur_scale, verbose=0):
def generate_sets(neighbours, blur_scale, verbose=0): def generate_sets(neighbours, blur_scale, verbose=0):
"""Split the entire dataset into a trainingset and a testset."""
suffix = '_%s_%s' % (blur_scale, neighbours) suffix = '_%s_%s' % (blur_scale, neighbours)
learning_set_file = 'learning_set%s.dat' % suffix learning_set_file = 'learning_set%s.dat' % suffix
test_set_file = 'test_set%s.dat' % suffix test_set_file = 'test_set%s.dat' % suffix
......
...@@ -12,8 +12,8 @@ def load_classifier(neighbours, blur_scale, c=None, gamma=None, verbose=0): ...@@ -12,8 +12,8 @@ def load_classifier(neighbours, blur_scale, c=None, gamma=None, verbose=0):
if verbose: if verbose:
print 'Loading classifier...' print 'Loading classifier...'
classifier = Classifier(filename=classifier_file, verbose=verbose) classifier = Classifier(filename=classifier_file, \
classifier.neighbours = neighbours neighbours=neighbours, verbose=verbose)
elif c != None and gamma != None: elif c != None and gamma != None:
if verbose: if verbose:
print 'Training new classifier...' print 'Training new classifier...'
......
from os import mkdir from os import mkdir
from os.path import exists from os.path import exists
from pylab import array, zeros, inv, dot, svd, floor from pylab import imsave, array, zeros, inv, dot, norm, 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
# sets the entire license plate of an image # Gets the character data from a picture with a license plate
def retrieve_data(image, corners): def retrieve_data(plate, corners):
x0, y0 = corners[0].to_tuple() x0,y0, x1,y1, x2,y2, x3,y3 = corners
x1, y1 = corners[1].to_tuple()
x2, y2 = corners[2].to_tuple()
x3, y3 = corners[3].to_tuple()
M = int(1.2 * (max(x0, x1, x2, x3) - min(x0, x1, x2, x3))) M = 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([
...@@ -29,7 +25,7 @@ def retrieve_data(image, corners): ...@@ -29,7 +25,7 @@ def retrieve_data(image, corners):
[ 0, 0, 0, x3, y3, 1, -N * x3, -N * y3, -N] [ 0, 0, 0, x3, y3, 1, -N * x3, -N * y3, -N]
]) ])
P = inv(get_transformation_matrix(matrix)) P = 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):
...@@ -38,7 +34,7 @@ def retrieve_data(image, corners): ...@@ -38,7 +34,7 @@ def retrieve_data(image, 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(image, or_coor_h[0], or_coor_h[1]) data[j][i] = pV(plate, or_coor_h[0], or_coor_h[1])
return data return data
...@@ -50,108 +46,92 @@ def get_transformation_matrix(matrix): ...@@ -50,108 +46,92 @@ def get_transformation_matrix(matrix):
U, D, V = svd(matrix) U, D, V = svd(matrix)
p = V[8][:] p = V[8][:]
return array([ return inv(array([[p[0],p[1],p[2]], [p[3],p[4],p[5]], [p[6],p[7],p[8]]]))
[ 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 image.in_bounds(x, y): if not image.in_bounds(x, y):
x_low = floor(x) return 0
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 x_low, x_high = floor(x), floor(x+1)
b = y_high - y y_low, y_high = floor(y), floor(y+1)
c = x - x_low x_y = (x_high - x_low) * (y_high - y_low)
d = y - y_low
return image[x_low, y_low] / x_y * a * b \ a = x_high - x
+ image[x_high, y_low] / x_y * c * b \ b = y_high - y
+ image[x_low , y_high] / x_y * a * d \ c = x - x_low
+ image[x_high, y_high] / x_y * c * d d = y - y_low
return 0 return image[x_low, y_low] / x_y * a * b \
+ image[x_high, y_low] / x_y * c * b \
+ image[x_low , y_high] / x_y * a * d \
+ image[x_high, y_high] / x_y * c * d
def xml_to_LicensePlate(filename, save_character=None): def xml_to_LicensePlate(filename, save_character=None):
image = GrayscaleImage('../images/Images/%s.jpg' % filename) plate = GrayscaleImage('../images/Images/%s.jpg' % filename)
dom = parse('../images/Infos/%s.info' % filename) dom = parse('../images/Infos/%s.info' % filename)
result_characters = [] country = ''
result = []
version = dom.getElementsByTagName("current-version")[0].firstChild.data version = get_node(dom, "current-version")
info = dom.getElementsByTagName("info") infos = by_tag(dom, "info")
for i in info: for info in infos:
if version == i.getElementsByTagName("version")[0].firstChild.data: if not version == get_node(info, "version"):
continue
country = i.getElementsByTagName("identification-letters")[0].firstChild.data country = get_node(info, "identification-letters")
temp = i.getElementsByTagName("characters") temp = by_tag(info, "characters")
if len(temp): if not temp: # no characters where found in the file
characters = temp[0].childNodes break
else:
characters = []
break
for i, character in enumerate(characters): characters = temp[0].childNodes
if character.nodeName == "character":
value = character.getElementsByTagName("char")[0].firstChild.data
corners = get_corners(character)
if not len(corners) == 4: for i, char in enumerate(characters):
break if not char.nodeName == "character":
continue
character_data = retrieve_data(image, corners) value = get_node(char, "char")
character_image = NormalizedCharacterImage(data=character_data) corners = get_corners(char)
result_characters.append(Character(value, corners, character_image, filename)) if not len(corners) == 8:
break
if save_character: data = retrieve_data(plate, corners)
single_character = GrayscaleImage(data=character_data) image = NormalizedCharacterImage(data=data)
result.append(Character(value, corners, image, filename))
if save_character:
character_image = GrayscaleImage(data=data)
path = "../images/LearningSet/%s" % value
image_path = "%s/%d_%s.jpg" % (path, i, filename.split('/')[-1])
path = "../images/LearningSet/%s" % value if not exists(path):
image_path = "%s/%d_%s.jpg" % (path, i, filename.split('/')[-1]) mkdir(path)
if not exists(path): if not exists(image_path):
mkdir(path) character_image.save(image_path)
if not exists(image_path): return LicensePlate(country, result)
single_character.save(image_path)
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 = []
margin_y = 3 def by_tag(node, tag):
margin_x = 2 return node.getElementsByTagName(tag)
corners.append( def get_attr(node, attr):
Point(get_coord(nodes[0], "x") - margin_x, return int(node.getAttribute(attr))
get_coord(nodes[0], "y") - margin_y)
)
corners.append( def get_corners(dom):
Point(get_coord(nodes[1], "x") + margin_x, p = by_tag(dom, "point")
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)
)
return corners # Extra padding
y = 3
x = 2
def get_coord(node, attribute): # return 8 values (x0,y0, .., x3,y3)
return int(node.getAttribute(attribute)) 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
\ 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