unknown %!s(int64=14) %!d(string=hai) anos
pai
achega
4b6c52d567
Modificáronse 5 ficheiros con 146 adicións e 59 borrados
  1. 10 26
      src/Character.py
  2. 6 0
      src/GrayscaleImage.py
  3. 114 23
      src/LicensePlate.py
  4. 13 7
      src/Point.py
  5. 3 3
      src/license_xml_tester.py

+ 10 - 26
src/Character.py

@@ -1,28 +1,12 @@
-from Point import Point
-
 # TODO cleanup the getElements stuff
 # TODO cleanup the getElements stuff
 class Character:
 class Character:
-    def __init__(self, character):
-        self.dom     = character
-        self.value   = self.get_node("char").firstChild.data
-
-        self.set_corners()
-        print self.corners
-
-    def set_corners(self):
-        corners = self.get_children("quadrangle")
-  
-        self.corners = []
-
-        for corner in corners:
-          if corner.nodeName == "point":
-              self.corners.append(Point(corner))
-
-    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 __init__(self, value, corners, image):
+        self.value   = value
+        self.corners = corners
+        self.image   = image
+        
+    # Testing purposes
+    def show(self):
+        from pylab import imshow, show
+        imshow(self.data, cmap="gray")
+        show()

+ 6 - 0
src/GrayscaleImage.py

@@ -8,6 +8,12 @@ class GrayscaleImage:
     def __init__(self, image_path = None, data = None):
     def __init__(self, image_path = None, data = None):
         if image_path:
         if image_path:
             self.data = imread(image_path)
             self.data = imread(image_path)
+            
+            extension = image_path.split('.',3)[-1]
+            
+            if extension == "jpg":
+              self.data = self.data[::-1]
+              
             self.convert_to_grayscale()
             self.convert_to_grayscale()
         elif data:
         elif data:
             self.data = data
             self.data = data

+ 114 - 23
src/LicensePlate.py

@@ -1,25 +1,109 @@
+from pylab import array, zeros, inv, dot, svd, shape, floor
 from xml.dom.minidom import parse 
 from xml.dom.minidom import parse 
 from Error import Error
 from Error import Error
 from Point import Point
 from Point import Point
 from Character import Character
 from Character import Character
+from GrayscaleImage import GrayscaleImage
 
 
+'''
+    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, file_path):
+    def __init__(self, xml_title):
         try:
         try:
-            self.dom = parse(file_path)
+            self.dom = parse('../XML/' + str(xml_title))
         except IOError:
         except IOError:
             Error("Incorrect file name given.")
             Error("Incorrect file name given.")
-            return None
         else:
         else:
             properties = self.get_properties()
             properties = self.get_properties()
 
 
-            self.image  = str(properties['uii']) + '.' + str(properties['type'])
-            self.width  = properties['width']
-            self.height = properties['height']
+            self.image  = GrayscaleImage('../images/' + str(properties['uii']) + '.' + str(properties['type']))
+            self.width  = int(properties['width'])
+            self.height = int(properties['height'])
 
 
-            info = self.set_plate()
+            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):
     def get_properties(self):
         children = self.get_children("properties")
         children = self.get_children("properties")
 
 
@@ -34,7 +118,7 @@ class LicensePlate:
         return properties
         return properties
 
 
     # TODO : create function for location / characters as they do the same
     # TODO : create function for location / characters as they do the same
-    def set_plate(self):
+    def read_xml(self):
         children = self.get_children("plate") # most recent version
         children = self.get_children("plate") # most recent version
         
         
         for child in children:
         for child in children:
@@ -43,26 +127,22 @@ class LicensePlate:
             elif child.nodeName == "identification-letters":
             elif child.nodeName == "identification-letters":
               self.country = child.firstChild.data
               self.country = child.firstChild.data
             elif child.nodeName == "location":
             elif child.nodeName == "location":
-                corners = self.get_children("quadrangle", child)
-          
-                self.corners = []
-
-                for corner in corners:
-                  if corner.nodeName == "point":
-                      self.corners.append(Point(corner))
-
+                self.corners = self.get_corners(child)
             elif child.nodeName == "characters":
             elif child.nodeName == "characters":
-                characters = child.childNodes
+                nodes = child.childNodes
   
   
-                self.license_characters = []
+                self.characters = []
 
 
-                for character in characters:
+                for character in nodes:
                   if character.nodeName == "character":
                   if character.nodeName == "character":
-                    self.license_characters.append(Character(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:
             else:
                 pass
                 pass
-                #print child.nodeName
             
             
     def get_node(self, node, dom=None):
     def get_node(self, node, dom=None):
         if not dom:
         if not dom:
@@ -71,4 +151,15 @@ class LicensePlate:
         return dom.getElementsByTagName(node)[0]
         return dom.getElementsByTagName(node)[0]
 
 
     def get_children(self, node, dom=None):
     def get_children(self, node, dom=None):
-        return self.get_node(node, dom).childNodes
+        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

+ 13 - 7
src/Point.py

@@ -1,8 +1,14 @@
 class Point:
 class Point:
-    def __init__(self, corner = None, coordinates = None):
-        if corner != None:
-            self.x = corner.getAttribute("x")
-            self.y = corner.getAttribute("y")
-        elif coordinates != None:
-            self.x = coordinates[0]
-            self.y = coordinates[1]
+    def __init__(self, x_or_corner=None, y=None):
+        if y != None:
+            self.x = x_or_corner
+            self.y = y
+        else:
+            self.x = int(x_or_corner.getAttribute("x"))
+            self.y = int(x_or_corner.getAttribute("y"))
+
+    def to_tuple(self):
+        return self.x, self.y
+        
+    def __str__(self):
+        return str(self.x) + " " + str(self.y)

+ 3 - 3
src/license_xml_tester.py

@@ -29,7 +29,7 @@ from LicensePlate import LicensePlate
  
  
 '''
 '''
 
 
-plate = LicensePlate("../XML/test.info") # some xml file from rein
+plate = LicensePlate("../XML/0000/00991_000000.info") # some xml file from rein
 
 
-for corner in plate.corners:
-  print corner.x, corner.y
+print plate.characters[0].value
+#plate.characters[0].show()