| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164 |
- from pylab import array, zeros, inv, dot, svd, shape, 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):
- filename = '%04d/00991_%04d%02d' % (folder_nr, folder_nr, file_nr)
- self.dom = parse('../images/Infos/%s.info' % filename)
- properties = self.get_properties()
- self.image = GrayscaleImage('../images/Images/%s.jpg' % filename)
- self.width = int(properties['width'])
- self.height = int(properties['height'])
- self.read_xml()
- # sets the entire license plate of an image
- def retrieve_data(self, 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)
- 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]
- ])
- P = inv(self.get_transformation_matrix(matrix))
- data = array([zeros(M, float)] * N)
- 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]
- data[j][i] = self.pV(or_coor_h[0], or_coor_h[1])
- return data
- def get_transformation_matrix(self, matrix):
- # Get the vector p and the values that are in there by taking the SVD.
- # Since D is diagonal with the eigenvalues sorted from large to small on
- # the diagonal, the optimal q in min ||Dq|| is q = [[0]..[1]]. Therefore,
- # p = Vq means p is the last column in V.
- U, D, V = svd(matrix)
- p = V[8][:]
- return array([
- [ p[0], p[1], p[2] ],
- [ p[3], p[4], p[5] ],
- [ p[6], p[7], p[8] ]
- ])
- 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.'''
- 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
- b = y_high - y
- c = x - x_low
- d = y - y_low
- 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
- return 0
- # Testing purposes
- def show(self):
- from pylab import imshow, show
- imshow(self.data, cmap="gray")
- show()
- def get_properties(self):
- children = self.get_children("properties")
- properties = {}
- for child in children:
- if child.nodeType == child.TEXT_NODE:
- properties[child.nodeName] = child.data
- elif child.nodeType == child.ELEMENT_NODE:
- properties[child.nodeName] = child.firstChild.data
- return properties
- # TODO : create function for location / characters as they do the same
- def read_xml(self):
- children = self.get_children("plate") # most recent version
- for child in children:
- if child.nodeName == "regnum":
- self.license_full = child.firstChild.data
- elif child.nodeName == "identification-letters":
- self.country = child.firstChild.data
- elif child.nodeName == "location":
- self.corners = self.get_corners(child)
- elif child.nodeName == "characters":
- nodes = child.childNodes
- self.characters = []
- for character in nodes:
- if character.nodeName == "character":
- value = self.get_node("char", character).firstChild.data
- corners = self.get_corners(character)
- data = self.retrieve_data(corners)
- image = NormalizedCharacterImage(data=data)
- self.characters.append(Character(value, corners, image))
- else:
- pass
- def get_node(self, node, dom=None):
- if not dom:
- dom = self.dom
- return dom.getElementsByTagName(node)[0]
- def get_children(self, node, dom=None):
- return self.get_node(node, dom).childNodes
- def get_corners(self, child):
- nodes = self.get_children("quadrangle", child)
- corners = []
- for corner in nodes:
- if corner.nodeName == "point":
- corners.append(Point(corner))
- return corners
|