Commit 84952000 authored by Jayke Meijer's avatar Jayke Meijer

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

parents 93292816 a68fe0cd
...@@ -6,12 +6,6 @@ class Character: ...@@ -6,12 +6,6 @@ class Character:
self.corners = corners self.corners = corners
self.image = image self.image = image
# Testing purposes
def show(self):
from pylab import imshow, show
imshow(self.data, cmap="gray")
show()
def get_feature_vector(self): def get_feature_vector(self):
pattern = LocalBinaryPatternizer(self.image) pattern = LocalBinaryPatternizer(self.image)
......
from svmutil import svm_train, svm_problem, svm_parameter, svm_predict, \ from svmutil import svm_train, svm_problem, svm_parameter, svm_predict, \
LINEAR, svm_save_model, svm_load_model svm_save_model, svm_load_model
from cPickle import dump, load from cPickle import dump, load
...@@ -13,7 +13,7 @@ class Classifier: ...@@ -13,7 +13,7 @@ class Classifier:
f.close() f.close()
else: else:
self.param = svm_parameter() self.param = svm_parameter()
self.param.kernel_type = LINEAR self.param.kernel_type = 2
self.param.C = c self.param.C = c
self.character_map = {} self.character_map = {}
self.model = None self.model = None
......
...@@ -3,63 +3,63 @@ from LicensePlate import LicensePlate ...@@ -3,63 +3,63 @@ from LicensePlate import LicensePlate
from Classifier import Classifier from Classifier import Classifier
from cPickle import dump, load from cPickle import dump, load
#chars = [] chars = []
#
#for i in range(9): for i in range(9):
# for j in range(100): for j in range(100):
# try: try:
# filename = '%04d/00991_%04d%02d.info' % (i, i, j) filename = '%04d/00991_%04d%02d.info' % (i, i, j)
# print 'loading file "%s"' % filename print 'loading file "%s"' % filename
# plate = LicensePlate(i, j) plate = LicensePlate(i, j)
#
# if hasattr(plate, 'characters'): if hasattr(plate, 'characters'):
# chars.extend(plate.characters) chars.extend(plate.characters)
# except: except:
# print 'epic fail' print 'epic fail'
#
#print 'loaded %d chars' % len(chars) print 'loaded %d chars' % len(chars)
#
#dump(chars, file('chars', 'w+')) dump(chars, file('chars', 'w+'))
#---------------------------------------------------------------- #----------------------------------------------------------------
#chars = load(file('chars', 'r')) chars = load(file('chars', 'r'))
#learned = [] learned = []
#learning_set = [] learning_set = []
#test_set = [] test_set = []
#
#for char in chars: for char in chars:
# if learned.count(char.value) > 80: if learned.count(char.value) > 80:
# test_set.append(char) test_set.append(char)
# else: else:
# learning_set.append(char) learning_set.append(char)
# learned.append(char.value) learned.append(char.value)
#
#dump(learning_set, file('learning_set', 'w+')) dump(learning_set, file('learning_set', 'w+'))
#dump(test_set, file('test_set', 'w+')) dump(test_set, file('test_set', 'w+'))
#---------------------------------------------------------------- #----------------------------------------------------------------
learning_set = load(file('learning_set', 'r')) learning_set = load(file('learning_set', 'r'))
# Train the classifier with the learning set # Train the classifier with the learning set
classifier = Classifier(c=3) classifier = Classifier(c=30)
classifier.train(learning_set) classifier.train(learning_set)
#classifier.save('classifier') classifier.save('classifier')
#---------------------------------------------------------------- #----------------------------------------------------------------
#classifier = Classifier(filename='classifier') classifier = Classifier(filename='classifier')
#test_set = load(file('test_set', 'r')) test_set = load(file('test_set', 'r'))
#l = len(test_set) l = len(test_set)
#matches = 0 matches = 0
#
#for i, char in enumerate(test_set): for i, char in enumerate(test_set):
# prediction = classifier.classify(char) prediction = classifier.classify(char)
#
# if char.value == prediction: if char.value == prediction:
# print ':) ------> Successfully recognized "%s"' % char.value print ':) ------> Successfully recognized "%s"' % char.value,
# matches += 1 matches += 1
# else: else:
# print ':( Expected character "%s", got "%s"' \ print ':( Expected character "%s", got "%s"' \
# % (char.value, prediction), % (char.value, prediction),
#
# print ' -- %d of %d (%d%% done)' % (i + 1, l, int(100 * (i + 1) / l)) print ' -- %d of %d (%d%% done)' % (i + 1, l, int(100 * (i + 1) / l))
#
#print '\n%d matches (%d%%), %d fails' % (matches, \ print '\n%d matches (%d%%), %d fails' % (matches, \
# int(100 * matches / len(test_set)), \ int(100 * matches / len(test_set)), \
# len(test_set) - matches) len(test_set) - matches)
import traceback, os.path
class Error:
def __init__(self, message=None):
stack = traceback.extract_stack()
origin_of_call = stack[0]
where_it_went_wrong = stack[1]
if message:
print message, "\n"
print "Error in", origin_of_call[0], "on line", origin_of_call[1]
print " : ", origin_of_call[3], "\n"
# Inside try function, so -2 lines as exept and Error() are 2 lines
print "Function called in", where_it_went_wrong[0]
print "around line", (where_it_went_wrong[1] - 2), "\n"
\ No newline at end of file
from GrayscaleImage import GrayscaleImage from GrayscaleImage import GrayscaleImage
from scipy.ndimage import convolve1d from scipy.ndimage import convolve1d
from pylab import ceil, zeros, pi, e, exp, sqrt, array from pylab import ceil, zeros, pi, exp, sqrt, array
class GaussianFilter: class GaussianFilter:
...@@ -8,11 +8,12 @@ class GaussianFilter: ...@@ -8,11 +8,12 @@ class GaussianFilter:
self.scale = scale self.scale = scale
def gaussian(self, x): def gaussian(self, x):
'''Return the value of a 1D Gaussian function for a given x and scale''' """Return the value of a 1D Gaussian function for a given x."""
return exp(-(x ** 2 / (2 * self.scale ** 2))) / (sqrt(2 * pi) * self.scale) return exp(-(x ** 2 / (2 * self.scale ** 2))) \
/ (sqrt(2 * pi) * self.scale)
def get_1d_gaussian_kernel(self): def get_1d_gaussian_kernel(self):
'''Sample a one-dimensional Gaussian function of scale s''' """Sample a one-dimensional Gaussian function of scale s."""
radius = int(ceil(3 * self.scale)) radius = int(ceil(3 * self.scale))
size = 2 * radius + 1 size = 2 * radius + 1
...@@ -25,7 +26,7 @@ class GaussianFilter: ...@@ -25,7 +26,7 @@ class GaussianFilter:
return result return result
def get_filtered_copy(self, image): def get_filtered_copy(self, image):
'''Apply a gaussian blur to an image, to suppress noise.''' """Apply a gaussian blur to an image, to suppress noise."""
kernel = self.get_1d_gaussian_kernel() kernel = self.get_1d_gaussian_kernel()
image = convolve1d(image.data, kernel, axis=0, mode='nearest') image = convolve1d(image.data, kernel, axis=0, mode='nearest')
return GrayscaleImage(None, convolve1d(image, kernel, axis=1, mode='nearest')) return GrayscaleImage(None, convolve1d(image, kernel, axis=1, mode='nearest'))
......
from pylab import imshow, imread, show from pylab import imshow, imread, show
from scipy.misc import imresize
from matplotlib.pyplot import hist from matplotlib.pyplot import hist
from scipy.misc import imresize, imsave from scipy.misc import imresize, imsave
...@@ -9,7 +8,7 @@ class GrayscaleImage: ...@@ -9,7 +8,7 @@ class GrayscaleImage:
if image_path != None: if image_path != None:
self.data = imread(image_path) self.data = imread(image_path)
extension = image_path.split('.',3)[-1] extension = image_path.split('.', 3)[-1]
if extension == "jpg": if extension == "jpg":
self.data = self.data[::-1] self.data = self.data[::-1]
......
...@@ -15,3 +15,4 @@ class Histogram: ...@@ -15,3 +15,4 @@ class Histogram:
def get_bin_index(self, number): def get_bin_index(self, number):
return (number - self.min) / ((self.max - self.min) / len(self.bins)) return (number - self.min) / ((self.max - self.min) / len(self.bins))
from copy import deepcopy
from Rectangle import Rectangle from Rectangle import Rectangle
from GrayscaleImage import GrayscaleImage
class LetterCropper: class LetterCropper:
......
from pylab import array, zeros, inv, dot, svd, shape, floor from pylab import array, zeros, inv, dot, svd, floor
from xml.dom.minidom import parse from xml.dom.minidom import parse
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 from NormalizedCharacterImage import NormalizedCharacterImage
'''
Creates a license plate object based on an XML file. The image should be
placed in a folder 'images' the xml file in a folder 'xml'
TODO: perhaps remove non required XML lookups
'''
class LicensePlate: class LicensePlate:
def __init__(self, folder_nr, file_nr): def __init__(self, folder_nr, file_nr):
...@@ -39,12 +32,12 @@ class LicensePlate: ...@@ -39,12 +32,12 @@ class LicensePlate:
matrix = array([ matrix = array([
[x0, y0, 1, 0, 0, 0, 0, 0, 0], [x0, y0, 1, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, x0, y0, 1, 0, 0, 0], [ 0, 0, 0, x0, y0, 1, 0, 0, 0],
[x1, y1, 1, 0, 0, 0, -M*x0, -M*y1, -M], [x1, y1, 1, 0, 0, 0, -M * x0, -M * y1, -M],
[ 0, 0, 0, x1, y1, 1, 0, 0, 0], [ 0, 0, 0, x1, y1, 1, 0, 0, 0],
[x2, y2, 1, 0, 0, 0, -M*x2, -M*y2, -M], [x2, y2, 1, 0, 0, 0, -M * x2, -M * y2, -M],
[ 0, 0, 0, x2, y2, 1, -N*x2, -N*y2, -N], [ 0, 0, 0, x2, y2, 1, -N * x2, -N * y2, -N],
[x3, y3, 1, 0, 0, 0, 0, 0, 0], [x3, y3, 1, 0, 0, 0, 0, 0, 0],
[ 0, 0, 0, x3, y3, 1, -N*x3, -N*y3, -N] [ 0, 0, 0, x3, y3, 1, -N * x3, -N * y3, -N]
]) ])
P = inv(self.get_transformation_matrix(matrix)) P = inv(self.get_transformation_matrix(matrix))
...@@ -53,7 +46,9 @@ class LicensePlate: ...@@ -53,7 +46,9 @@ class LicensePlate:
for i in range(0, M): for i in range(0, M):
for j in range(0, N): for j in range(0, N):
or_coor = dot(P, ([[i],[j],[1]])) or_coor = dot(P, ([[i],[j],[1]]))
or_coor_h = or_coor[1][0] / or_coor[2][0], or_coor[0][0] / or_coor[2][0] or_coor_h = (or_coor[1][0] / or_coor[2][0],
or_coor[0][0] / or_coor[2][0])
data[j][i] = self.pV(or_coor_h[0], or_coor_h[1]) data[j][i] = self.pV(or_coor_h[0], or_coor_h[1])
return data return data
...@@ -75,9 +70,7 @@ class LicensePlate: ...@@ -75,9 +70,7 @@ class LicensePlate:
def pV(self, x, y): def pV(self, x, y):
image = self.image image = self.image
'''Get the value of a point x,y in the given image, where x and y are not #Get the value of a point (interpolated x, y) in the given image
necessary integers, so the value is interpolated from its neighbouring
pixels.'''
if image.in_bounds(x, y): if image.in_bounds(x, y):
x_low = floor(x) x_low = floor(x)
x_high = floor(x + 1) x_high = floor(x + 1)
......
from Histogram import Histogram from Histogram import Histogram
from numpy import zeros, byte
from math import ceil from math import ceil
class LocalBinaryPatternizer: class LocalBinaryPatternizer:
......
from GrayscaleImage import GrayscaleImage from GrayscaleImage import GrayscaleImage
from LocalBinaryPatternizer import LocalBinaryPatternizer from LocalBinaryPatternizer import LocalBinaryPatternizer
from LetterCropper import LetterCropper
from matplotlib.pyplot import imshow, subplot, show, axis, bar
from numpy import arange
image = GrayscaleImage("../images/test.png") image = GrayscaleImage("../images/test.png")
......
class Rectangle: class Rectangle:
def __init__(self, x, y, width, height): def __init__(self, x, y, width, height):
self.x = x; self.x = x
self.y = y; self.y = y
self.width = width; self.width = width
self.height = height; self.height = height
from GrayscaleImage import GrayscaleImage from GrayscaleImage import GrayscaleImage
from NormalizedCharacterImage import NormalizedCharacterImage from NormalizedCharacterImage import NormalizedCharacterImage
from LetterCropper import LetterCropper
image = GrayscaleImage("../images/test10.png") image = GrayscaleImage("../images/test10.png")
normalized_character_image = NormalizedCharacterImage(image) normalized_character_image = NormalizedCharacterImage(image)
......
from LicensePlate import LicensePlate
'''
create new LicensePlate object:
i.e you can do
plate = LicensePlate("../XML/test.info") # some xml file from rein
now available:
plate.image
plate.width
plate.height
Are the entire image widht / height and image is the corresponding image file
provided by rein (i.e other folder somewhere)
plate.corners
plate.license_full # the entire license plate as a string so 2334AB
plate.characters # for each character from license_full a Character object
exists, kinda same as the license plate. You have a value
= the character / number
a corners -> i.e list of points (Point objects)
TODO had to go so this text is full of crap maybe, anyway enjoy
'''
plate = LicensePlate("../XML/0000/00991_000000.info") # some xml file from rein
print plate.characters[0].value
#plate.characters[0].show()
\ 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