xml_helper_functions.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. from os import mkdir
  2. from os.path import exists
  3. from pylab import imsave, array, zeros, inv, dot, norm, svd, floor
  4. from xml.dom.minidom import parse
  5. from Character import Character
  6. from GrayscaleImage import GrayscaleImage
  7. from NormalizedCharacterImage import NormalizedCharacterImage
  8. from LicensePlate import LicensePlate
  9. from data import IMAGES_FOLDER
  10. # Gets the character data from a picture with a license plate
  11. def retrieve_data(plate, corners):
  12. x0,y0, x1,y1, x2,y2, x3,y3 = corners
  13. M = max(x0, x1, x2, x3) - min(x0, x1, x2, x3)
  14. N = max(y0, y1, y2, y3) - min(y0, y1, y2, y3)
  15. matrix = array([
  16. [x0, y0, 1, 0, 0, 0, 0, 0, 0],
  17. [ 0, 0, 0, x0, y0, 1, 0, 0, 0],
  18. [x1, y1, 1, 0, 0, 0, -M * x0, -M * y1, -M],
  19. [ 0, 0, 0, x1, y1, 1, 0, 0, 0],
  20. [x2, y2, 1, 0, 0, 0, -M * x2, -M * y2, -M],
  21. [ 0, 0, 0, x2, y2, 1, -N * x2, -N * y2, -N],
  22. [x3, y3, 1, 0, 0, 0, 0, 0, 0],
  23. [ 0, 0, 0, x3, y3, 1, -N * x3, -N * y3, -N]
  24. ])
  25. P = get_transformation_matrix(matrix)
  26. data = array([zeros(M, float)] * N)
  27. for i in range(M):
  28. for j in range(N):
  29. or_coor = dot(P, ([[i],[j],[1]]))
  30. or_coor_h = (or_coor[1][0] / or_coor[2][0],
  31. or_coor[0][0] / or_coor[2][0])
  32. data[j][i] = pV(plate, or_coor_h[0], or_coor_h[1])
  33. return data
  34. def get_transformation_matrix(matrix):
  35. # Get the vector p and the values that are in there by taking the SVD.
  36. # Since D is diagonal with the eigenvalues sorted from large to small
  37. # on the diagonal, the optimal q in min ||Dq|| is q = [[0]..[1]].
  38. # Therefore, p = Vq means p is the last column in V.
  39. U, D, V = svd(matrix)
  40. p = V[8][:]
  41. return inv(array([[p[0],p[1],p[2]], [p[3],p[4],p[5]], [p[6],p[7],p[8]]]))
  42. def pV(image, x, y):
  43. #Get the value of a point (interpolated x, y) in the given image
  44. if not image.in_bounds(x, y):
  45. return 0
  46. x_low, x_high = floor(x), floor(x+1)
  47. y_low, y_high = floor(y), floor(y+1)
  48. x_y = (x_high - x_low) * (y_high - y_low)
  49. a = x_high - x
  50. b = y_high - y
  51. c = x - x_low
  52. d = y - y_low
  53. return image[x_low, y_low] / x_y * a * b \
  54. + image[x_high, y_low] / x_y * c * b \
  55. + image[x_low , y_high] / x_y * a * d \
  56. + image[x_high, y_high] / x_y * c * d
  57. def xml_to_LicensePlate(filename, save_character=None):
  58. plate = GrayscaleImage('../images/Images/%s.jpg' % filename)
  59. dom = parse('../images/Infos/%s.info' % filename)
  60. country = ''
  61. result = []
  62. version = get_node(dom, "current-version")
  63. infos = by_tag(dom, "info")
  64. for info in infos:
  65. if not version == get_node(info, "version"):
  66. continue
  67. country = get_node(info, "identification-letters")
  68. temp = by_tag(info, "characters")
  69. if not temp: # no characters where found in the file
  70. break
  71. characters = temp[0].childNodes
  72. for i, char in enumerate(characters):
  73. if not char.nodeName == "character":
  74. continue
  75. value = get_node(char, "char")
  76. corners = get_corners(char)
  77. if not len(corners) == 8:
  78. break
  79. data = retrieve_data(plate, corners)
  80. image = NormalizedCharacterImage(data=data)
  81. result.append(Character(value, corners, image, filename))
  82. if save_character:
  83. character_image = GrayscaleImage(data=data)
  84. path = IMAGES_FOLDER + value
  85. image_path = "%s/%d_%s.jpg" % (path, i, filename.split('/')[-1])
  86. if not exists(path):
  87. mkdir(path)
  88. if not exists(image_path):
  89. character_image.save(image_path)
  90. return LicensePlate(country, result)
  91. def get_node(node, tag):
  92. return by_tag(node, tag)[0].firstChild.data
  93. def by_tag(node, tag):
  94. return node.getElementsByTagName(tag)
  95. def get_attr(node, attr):
  96. return int(node.getAttribute(attr))
  97. def get_corners(dom):
  98. p = by_tag(dom, "point")
  99. # Extra padding
  100. y = 3
  101. x = 2
  102. # return 8 values (x0,y0, .., x3,y3)
  103. return get_attr(p[0], "x") - x, get_attr(p[0], "y") - y,\
  104. get_attr(p[1], "x") + x, get_attr(p[1], "y") - y,\
  105. get_attr(p[2], "x") + x, get_attr(p[2], "y") + y,\
  106. get_attr(p[3], "x") - x, get_attr(p[3], "y") + y