Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
L
licenseplates
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Taddeüs Kroes
licenseplates
Commits
84952000
Commit
84952000
authored
Dec 05, 2011
by
Jayke Meijer
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'master' of github.com:taddeus/licenseplates
parents
93292816
a68fe0cd
Changes
15
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
125 additions
and
196 deletions
+125
-196
src/Character.py
src/Character.py
+0
-6
src/Classifier.py
src/Classifier.py
+2
-2
src/ClassifierTest.py
src/ClassifierTest.py
+53
-53
src/Error.py
src/Error.py
+0
-17
src/GaussianFilter.py
src/GaussianFilter.py
+13
-12
src/GrayscaleImage.py
src/GrayscaleImage.py
+23
-24
src/Histogram.py
src/Histogram.py
+5
-4
src/LetterCropper.py
src/LetterCropper.py
+4
-6
src/LicensePlate.py
src/LicensePlate.py
+14
-21
src/LocalBinaryPatternizer.py
src/LocalBinaryPatternizer.py
+0
-1
src/LocalBinaryPatternizerTest.py
src/LocalBinaryPatternizerTest.py
+1
-4
src/NormalizedCharacterImage.py
src/NormalizedCharacterImage.py
+4
-4
src/Rectangle.py
src/Rectangle.py
+4
-4
src/combined_test.py
src/combined_test.py
+2
-3
src/license_xml_tester.py
src/license_xml_tester.py
+0
-35
No files found.
src/Character.py
View file @
84952000
...
...
@@ -6,12 +6,6 @@ class Character:
self
.
corners
=
corners
self
.
image
=
image
# Testing purposes
def
show
(
self
):
from
pylab
import
imshow
,
show
imshow
(
self
.
data
,
cmap
=
"gray"
)
show
()
def
get_feature_vector
(
self
):
pattern
=
LocalBinaryPatternizer
(
self
.
image
)
...
...
src/Classifier.py
View file @
84952000
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
...
...
@@ -13,7 +13,7 @@ class Classifier:
f
.
close
()
else
:
self
.
param
=
svm_parameter
()
self
.
param
.
kernel_type
=
LINEAR
self
.
param
.
kernel_type
=
2
self
.
param
.
C
=
c
self
.
character_map
=
{}
self
.
model
=
None
...
...
src/ClassifierTest.py
View file @
84952000
...
...
@@ -3,63 +3,63 @@ from LicensePlate import LicensePlate
from
Classifier
import
Classifier
from
cPickle
import
dump
,
load
#
chars = []
#
#
for i in range(9):
#
for j in range(100):
#
try:
#
filename = '%04d/00991_%04d%02d.info' % (i, i, j)
#
print 'loading file "%s"' % filename
#
plate = LicensePlate(i, j)
#
#
if hasattr(plate, 'characters'):
#
chars.extend(plate.characters)
#
except:
#
print 'epic fail'
#
#
print 'loaded %d chars' % len(chars)
#
#
dump(chars, file('chars', 'w+'))
chars
=
[]
for
i
in
range
(
9
):
for
j
in
range
(
100
):
try
:
filename
=
'%04d/00991_%04d%02d.info'
%
(
i
,
i
,
j
)
print
'loading file "%s"'
%
filename
plate
=
LicensePlate
(
i
,
j
)
if
hasattr
(
plate
,
'characters'
):
chars
.
extend
(
plate
.
characters
)
except
:
print
'epic fail'
print
'loaded %d chars'
%
len
(
chars
)
dump
(
chars
,
file
(
'chars'
,
'w+'
))
#----------------------------------------------------------------
#
chars = load(file('chars', 'r'))
#
learned = []
#
learning_set = []
#
test_set = []
#
#
for char in chars:
#
if learned.count(char.value) > 80:
#
test_set.append(char)
#
else:
#
learning_set.append(char)
#
learned.append(char.value)
#
#
dump(learning_set, file('learning_set', 'w+'))
#
dump(test_set, file('test_set', 'w+'))
chars
=
load
(
file
(
'chars'
,
'r'
))
learned
=
[]
learning_set
=
[]
test_set
=
[]
for
char
in
chars
:
if
learned
.
count
(
char
.
value
)
>
80
:
test_set
.
append
(
char
)
else
:
learning_set
.
append
(
char
)
learned
.
append
(
char
.
value
)
dump
(
learning_set
,
file
(
'learning_set'
,
'w+'
))
dump
(
test_set
,
file
(
'test_set'
,
'w+'
))
#----------------------------------------------------------------
learning_set
=
load
(
file
(
'learning_set'
,
'r'
))
# Train the classifier with the learning set
classifier
=
Classifier
(
c
=
3
)
classifier
=
Classifier
(
c
=
3
0
)
classifier
.
train
(
learning_set
)
#
classifier.save('classifier')
classifier
.
save
(
'classifier'
)
#----------------------------------------------------------------
#
classifier = Classifier(filename='classifier')
#
test_set = load(file('test_set', 'r'))
#
l = len(test_set)
#
matches = 0
#
#
for i, char in enumerate(test_set):
#
prediction = classifier.classify(char)
#
#
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)
classifier
=
Classifier
(
filename
=
'classifier'
)
test_set
=
load
(
file
(
'test_set'
,
'r'
))
l
=
len
(
test_set
)
matches
=
0
for
i
,
char
in
enumerate
(
test_set
):
prediction
=
classifier
.
classify
(
char
)
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
)
src/Error.py
deleted
100644 → 0
View file @
93292816
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
src/GaussianFilter.py
View file @
84952000
from
GrayscaleImage
import
GrayscaleImage
from
scipy.ndimage
import
convolve1d
from
pylab
import
ceil
,
zeros
,
pi
,
e
,
e
xp
,
sqrt
,
array
from
pylab
import
ceil
,
zeros
,
pi
,
exp
,
sqrt
,
array
class
GaussianFilter
:
def
__init__
(
self
,
scale
):
self
.
scale
=
scale
def
gaussian
(
self
,
x
):
'''Return the value of a 1D Gaussian function for a given x and scale'''
return
exp
(
-
(
x
**
2
/
(
2
*
self
.
scale
**
2
)))
/
(
sqrt
(
2
*
pi
)
*
self
.
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
)
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
))
size
=
2
*
radius
+
1
result
=
zeros
(
size
)
# Sample the Gaussian function
# Sample the Gaussian function
result
=
array
([
self
.
gaussian
(
x
-
radius
)
for
x
in
xrange
(
size
)])
# The sum of all kernel values is equal to one
result
/=
result
.
sum
()
result
/=
result
.
sum
()
return
result
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
()
image
=
convolve1d
(
image
.
data
,
kernel
,
axis
=
0
,
mode
=
'nearest'
)
return
GrayscaleImage
(
None
,
convolve1d
(
image
,
kernel
,
axis
=
1
,
mode
=
'nearest'
))
def
filter
(
self
,
image
):
kernel
=
self
.
get_1d_gaussian_kernel
()
image
.
data
=
convolve1d
(
image
.
data
,
kernel
,
axis
=
0
,
mode
=
'nearest'
)
image
.
data
=
convolve1d
(
image
.
data
,
kernel
,
axis
=
1
,
mode
=
'nearest'
)
def
get_scale
(
self
):
return
self
.
scale
def
set_scale
(
self
,
scale
):
self
.
scale
=
float
(
scale
)
...
...
src/GrayscaleImage.py
View file @
84952000
from
pylab
import
imshow
,
imread
,
show
from
scipy.misc
import
imresize
from
matplotlib.pyplot
import
hist
from
scipy.misc
import
imresize
,
imsave
...
...
@@ -8,21 +7,21 @@ class GrayscaleImage:
def
__init__
(
self
,
image_path
=
None
,
data
=
None
):
if
image_path
!=
None
:
self
.
data
=
imread
(
image_path
)
extension
=
image_path
.
split
(
'.'
,
3
)[
-
1
]
extension
=
image_path
.
split
(
'.'
,
3
)[
-
1
]
if
extension
==
"jpg"
:
self
.
data
=
self
.
data
[::
-
1
]
self
.
convert_to_grayscale
()
elif
data
!=
None
:
self
.
data
=
data
def
__iter__
(
self
):
self
.
__i_x
=
-
1
self
.
__i_y
=
0
return
self
def
next
(
self
):
self
.
__i_x
+=
1
if
self
.
__i_x
==
self
.
width
:
...
...
@@ -30,47 +29,47 @@ class GrayscaleImage:
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
):
return
self
.
data
[
position
]
def
convert_to_grayscale
(
self
):
if
len
(
self
.
data
.
shape
)
>
2
:
self
.
data
=
self
.
data
[:,:,:
3
].
sum
(
axis
=
2
)
/
3
def
crop
(
self
,
rectangle
):
self
.
data
=
self
.
data
[
rectangle
.
y
:
rectangle
.
y
+
rectangle
.
height
,
self
.
data
=
self
.
data
[
rectangle
.
y
:
rectangle
.
y
+
rectangle
.
height
,
rectangle
.
x
:
rectangle
.
x
+
rectangle
.
width
]
def
show
(
self
):
imshow
(
self
.
data
,
cmap
=
"gray"
)
show
()
def
make_histogram
(
self
):
return
hist
(
self
.
data
)
def
resize
(
self
,
size
):
# size is of type float
def
resize
(
self
,
size
):
# size is of type float
self
.
data
=
imresize
(
self
.
data
,
size
)
def
get_shape
(
self
):
return
self
.
data
.
shape
shape
=
property
(
get_shape
)
def
get_width
(
self
):
return
self
.
get_shape
()[
1
]
width
=
property
(
get_width
)
def
get_height
(
self
):
return
self
.
get_shape
()[
0
]
height
=
property
(
get_height
)
def
in_bounds
(
self
,
y
,
x
):
return
x
>=
0
and
x
<
self
.
width
and
y
>=
0
and
y
<
self
.
height
def
save
(
self
,
path
):
imsave
(
path
,
self
.
data
)
src/Histogram.py
View file @
84952000
...
...
@@ -4,14 +4,15 @@ class Histogram:
self
.
bins
=
[
0
]
*
bins
self
.
min
=
min
self
.
max
=
max
def
add
(
self
,
number
):
bin_index
=
self
.
get_bin_index
(
number
)
self
.
bins
[
bin_index
]
+=
1
def
remove
(
self
,
number
):
bin_index
=
self
.
get_bin_index
(
number
)
self
.
bins
[
bin_index
]
-=
1
def
get_bin_index
(
self
,
number
):
return
(
number
-
self
.
min
)
/
((
self
.
max
-
self
.
min
)
/
len
(
self
.
bins
))
\ No newline at end of file
return
(
number
-
self
.
min
)
/
((
self
.
max
-
self
.
min
)
/
len
(
self
.
bins
))
src/LetterCropper.py
View file @
84952000
from
copy
import
deepcopy
from
Rectangle
import
Rectangle
from
GrayscaleImage
import
GrayscaleImage
class
LetterCropper
:
def
__init__
(
self
,
threshold
=
0.9
):
self
.
threshold
=
threshold
def
crop_to_letter
(
self
,
image
):
self
.
image
=
image
self
.
determine_letter_bounds
()
...
...
@@ -24,10 +22,10 @@ class LetterCropper:
if
y
<
min_y
:
min_y
=
y
if
x
>
max_x
:
max_x
=
x
if
y
>
max_y
:
max_y
=
y
self
.
letter_bounds
=
Rectangle
(
min_x
,
min_y
,
min_x
,
min_y
,
max_x
-
min_x
,
max_y
-
min_y
)
src/LicensePlate.py
View file @
84952000
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
Error
import
Error
from
Point
import
Point
from
Character
import
Character
from
GrayscaleImage
import
GrayscaleImage
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
:
def
__init__
(
self
,
folder_nr
,
file_nr
):
...
...
@@ -37,14 +30,14 @@ class LicensePlate:
N
=
max
(
y0
,
y1
,
y2
,
y3
)
-
min
(
y0
,
y1
,
y2
,
y3
)
matrix
=
array
([
[
x0
,
y0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
],
[
0
,
0
,
0
,
x0
,
y0
,
1
,
0
,
0
,
0
],
[
x1
,
y1
,
1
,
0
,
0
,
0
,
-
M
*
x0
,
-
M
*
y1
,
-
M
],
[
0
,
0
,
0
,
x1
,
y1
,
1
,
0
,
0
,
0
],
[
x2
,
y2
,
1
,
0
,
0
,
0
,
-
M
*
x2
,
-
M
*
y2
,
-
M
],
[
0
,
0
,
0
,
x2
,
y2
,
1
,
-
N
*
x2
,
-
N
*
y2
,
-
N
],
[
x3
,
y3
,
1
,
0
,
0
,
0
,
0
,
0
,
0
],
[
0
,
0
,
0
,
x3
,
y3
,
1
,
-
N
*
x3
,
-
N
*
y3
,
-
N
]
[
x0
,
y0
,
1
,
0
,
0
,
0
,
0
,
0
,
0
],
[
0
,
0
,
0
,
x0
,
y0
,
1
,
0
,
0
,
0
],
[
x1
,
y1
,
1
,
0
,
0
,
0
,
-
M
*
x0
,
-
M
*
y1
,
-
M
],
[
0
,
0
,
0
,
x1
,
y1
,
1
,
0
,
0
,
0
],
[
x2
,
y2
,
1
,
0
,
0
,
0
,
-
M
*
x2
,
-
M
*
y2
,
-
M
],
[
0
,
0
,
0
,
x2
,
y2
,
1
,
-
N
*
x2
,
-
N
*
y2
,
-
N
],
[
x3
,
y3
,
1
,
0
,
0
,
0
,
0
,
0
,
0
],
[
0
,
0
,
0
,
x3
,
y3
,
1
,
-
N
*
x3
,
-
N
*
y3
,
-
N
]
])
P
=
inv
(
self
.
get_transformation_matrix
(
matrix
))
...
...
@@ -53,7 +46,9 @@ class LicensePlate:
for
i
in
range
(
0
,
M
):
for
j
in
range
(
0
,
N
):
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
])
return
data
...
...
@@ -75,9 +70,7 @@ class LicensePlate:
def
pV
(
self
,
x
,
y
):
image
=
self
.
image
'''Get the value of a point x,y in the given image, where x and y are not
necessary integers, so the value is interpolated from its neighbouring
pixels.'''
#Get the value of a point (interpolated x, y) in the given image
if
image
.
in_bounds
(
x
,
y
):
x_low
=
floor
(
x
)
x_high
=
floor
(
x
+
1
)
...
...
@@ -161,4 +154,4 @@ class LicensePlate:
if
corner
.
nodeName
==
"point"
:
corners
.
append
(
Point
(
corner
))
return
corners
return
corners
\ No newline at end of file
src/LocalBinaryPatternizer.py
View file @
84952000
from
Histogram
import
Histogram
from
numpy
import
zeros
,
byte
from
math
import
ceil
class
LocalBinaryPatternizer
:
...
...
src/LocalBinaryPatternizerTest.py
View file @
84952000
from
GrayscaleImage
import
GrayscaleImage
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"
)
lbp
=
LocalBinaryPatternizer
(
image
)
histograms
=
lbp
.
create_features_vector
()
print
histograms
\ No newline at end of file
print
histograms
src/NormalizedCharacterImage.py
View file @
84952000
...
...
@@ -4,7 +4,7 @@ from LetterCropper import LetterCropper
from
GaussianFilter
import
GaussianFilter
class
NormalizedCharacterImage
(
GrayscaleImage
):
def
__init__
(
self
,
image
=
None
,
data
=
None
,
size
=
(
60
,
40
),
blur
=
1.1
,
crop_threshold
=
0.9
):
if
image
!=
None
:
GrayscaleImage
.
__init__
(
self
,
data
=
deepcopy
(
image
.
data
))
...
...
@@ -22,13 +22,13 @@ class NormalizedCharacterImage(GrayscaleImage):
self
.
data
-=
self
.
data
.
min
()
self
.
data
/=
self
.
data
.
max
()
def
gausse_filter
(
self
):
def
gausse_filter
(
self
):
filter
=
GaussianFilter
(
1.1
)
filter
.
filter
(
self
)
def
crop_to_letter
(
self
):
cropper
=
LetterCropper
(
0.9
)
cropper
.
crop_to_letter
(
self
)
def
resize
(
self
):
GrayscaleImage
.
resize
(
self
,
self
.
size
)
\ No newline at end of file
GrayscaleImage
.
resize
(
self
,
self
.
size
)
src/Rectangle.py
View file @
84952000
class
Rectangle
:
def
__init__
(
self
,
x
,
y
,
width
,
height
):
self
.
x
=
x
;
self
.
y
=
y
;
self
.
width
=
width
;
self
.
height
=
height
;
self
.
x
=
x
self
.
y
=
y
self
.
width
=
width
self
.
height
=
height
src/combined_test.py
View file @
84952000
from
GrayscaleImage
import
GrayscaleImage
from
NormalizedCharacterImage
import
NormalizedCharacterImage
from
LetterCropper
import
LetterCropper
from
NormalizedCharacterImage
import
NormalizedCharacterImage
image
=
GrayscaleImage
(
"../images/test10.png"
)
normalized_character_image
=
NormalizedCharacterImage
(
image
)
normalized_character_image
.
show
()
\ No newline at end of file
normalized_character_image
.
show
()
src/license_xml_tester.py
deleted
100644 → 0
View file @
93292816
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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment