No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

gis-svg-stitcher.py 7.8 KiB

hace 3 años
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. from wand.image import Image
  2. import PIL.Image
  3. import io
  4. import exiftool
  5. import subprocess
  6. import os
  7. import lxml.etree as ET
  8. import copy
  9. import cv2
  10. import flirimageextractor
  11. from matplotlib import cm
  12. import numpy as np
  13. import urllib.request
  14. dirname = os.path.dirname(__file__)
  15. working_dir = 'source_images_full'
  16. filename = os.path.join(dirname, 'canvas.svg')
  17. tree = ET.parse(filename)
  18. root = tree.getroot()
  19. d = root.nsmap
  20. main_layer = root.xpath('//*[@id="tiles"]', namespaces={'n': "http://www.w3.org/2000/svg"})[0]
  21. tile_rows = root.xpath('//*[@id="tile_rows"]', namespaces={'n': "http://www.w3.org/2000/svg"})[0]
  22. def deg_coordinates_to_decimal(coordStr):
  23. coordArr = value.split(', ')
  24. calculatedCoordArray = []
  25. for calculation in coordArr:
  26. calculationArr = calculation.split('/')
  27. calculatedCoordArray.append(int(calculationArr[0]) / int(calculationArr[1]))
  28. degrees = calculatedCoordArray[0]
  29. minutes = calculatedCoordArray[1]
  30. seconds = calculatedCoordArray[2]
  31. return (degrees + (minutes * 1/60) + (seconds * 1/60 * 1/60))
  32. # # extracting TIF Data
  33. # for root, directories, file in os.walk(os.path.join(dirname, working_dir)):
  34. # for file in file:
  35. # if(file.endswith(".jpg")):
  36. # print(os.path.join(root, file))
  37. # full_filepath = os.path.join(root, file)
  38. # with exiftool.ExifTool() as et:
  39. # cmd = ['exiftool', full_filepath, "-b", "-RawThermalImage"]
  40. # tif_data = subprocess.check_output(cmd)
  41. # tif_image = PIL.Image.open(io.BytesIO(tif_data))
  42. # tif_filepath = os.path.join(dirname, working_dir, file.split('.')[0] + '_thermal.tif')
  43. # tif_image.save(tif_filepath)
  44. # print(tif_filepath)
  45. # finding the boundaries of the whole canvas
  46. latsArr = []
  47. lonsArr = []
  48. for root_path, directories, file in os.walk(os.path.join(dirname, working_dir)):
  49. for file in file:
  50. if(file.endswith(".jpg")):
  51. print(os.path.join(root_path, file))
  52. full_filepath = os.path.join(root_path, file)
  53. with Image(filename=full_filepath) as image:
  54. print(image.width)
  55. print(image.height)
  56. for key, value in image.metadata.items():
  57. if key == 'exif:GPSLatitude':
  58. lat = deg_coordinates_to_decimal(value) # lat -> Y vertical
  59. latsArr.append(lat)
  60. print("{}: {}".format(key, value))
  61. print('lat '+ str(lat))
  62. if key == 'exif:GPSLongitude':
  63. lon = deg_coordinates_to_decimal(value) # lon -> X horizontal
  64. lonsArr.append(lon)
  65. print("{}: {}".format(key, value))
  66. print('lon '+ str(lon))
  67. minLat = min(latsArr)
  68. minLon = min(lonsArr)
  69. maxLat = max(latsArr)
  70. maxLon = max(lonsArr)
  71. width = maxLon - minLon
  72. height = maxLat- minLat
  73. # placing the images into the svg
  74. rotation = 125
  75. y_scale = -1800000 #-400000
  76. x_scale = 655000 #-950000
  77. # y_scale = 2600000 #-400000
  78. # x_scale = 1200000 #-950000
  79. image_rotation_up = rotation #32
  80. image_rotation_down = rotation + 180 #192
  81. for root_path, directories, file in os.walk(os.path.join(dirname, working_dir)):
  82. for file in file:
  83. if(file.endswith(".jpg")):
  84. print(os.path.join(root_path, file))
  85. full_filepath = os.path.join(root_path, file)
  86. with Image(filename=full_filepath) as image:
  87. print(image.width)
  88. print(image.height)
  89. for key, value in image.metadata.items():
  90. # print("{}: {}".format(key, value))
  91. if key == 'exif:GPSLatitude':
  92. lat = deg_coordinates_to_decimal(value) - minLat
  93. print('lat '+ str(lat))
  94. if key == 'exif:GPSLongitude':
  95. lon = deg_coordinates_to_decimal(value) - minLon
  96. print('lon '+ str(lon))
  97. if key == 'exif:GPSImgDirection':
  98. direction = value.split('/')
  99. rotation = int(direction[0])/int(direction[1])/2
  100. g_pos_el_attributes = {
  101. # 'x': str(lat*scale),
  102. # 'y': str(lon*scale),
  103. 'transform': "translate({}, {})".format(format(lon*x_scale, '.20f'), format(lat*y_scale, '.20f')),
  104. 'data-lat': format(lat, '.20f'),
  105. 'data-lon': format(lon, '.20f'),
  106. 'class': 'tile',
  107. 'id': 'tile_{}'.format(file.split('.')[0]),
  108. # 'style': 'opacity:.6',
  109. }
  110. g_pos_el = ET.SubElement(main_layer, 'g', attrib=g_pos_el_attributes)
  111. g_offset_corr_el_attributes = {
  112. 'transform': "translate(150, 0)",
  113. 'class': 'tile-offset-corr',
  114. }
  115. g_offset_corr_el = ET.SubElement(g_pos_el, 'g', attrib=g_offset_corr_el_attributes)
  116. g_center_el_attributes = {
  117. 'class': 'tile-center',
  118. 'transform': 'translate({}, {})'.format(str(image.width/2*-1), str(image.height/2*-1))
  119. }
  120. g_center_el = ET.SubElement(g_offset_corr_el, 'g', attrib=g_center_el_attributes)
  121. g_rot_el_attributes = {
  122. 'class': 'tile-rotate',
  123. 'data-image-rotation': str(image_rotation_up),
  124. 'data-image-dimensions': str(image.width/2) + ' ' + str(image.height/2),
  125. 'transform': 'rotate({} {} {})'.format(str(image_rotation_up), str(image.width/2), str(image.height/2))
  126. }
  127. g_rot_el = ET.SubElement(g_center_el, 'g', attrib=g_rot_el_attributes)
  128. xlinkns ="http://www.w3.org/1999/xlink"
  129. image_el = ET.SubElement(g_rot_el, 'image', {
  130. "class": 'thermal_image',
  131. "{%s}href" % xlinkns: file,
  132. "width": str(image.width),
  133. "height": str(image.height),
  134. "mask" : "url(#tilefademask)",
  135. })
  136. # transform_str = "translate(-{}, -{})".format(str(min(latsArr)*scale), str(min(lonsArr)*scale))
  137. # print(transform_str)
  138. # main_layer.attrib['transform'] = transform_str
  139. # sort elements
  140. def getkey(elem):
  141. # Used for sorting elements by @LIN.
  142. # returns a tuple of ints from the exploded @LIN value
  143. # '1.0' -> (1,0)
  144. # '1.0.1' -> (1,0,1)
  145. return float(elem.get('id').split('_')[2])
  146. main_layer[:] = sorted(main_layer, key=getkey)
  147. # rotate image if previous element is under the current one
  148. last_state = 'down'
  149. for index, el in enumerate(main_layer):
  150. if(el.getprevious() is not None):
  151. if (el.getprevious().attrib['data-lon'] > el.attrib['data-lon'] or (el.getprevious().attrib['data-lon'] == el.attrib['data-lon'] and last_state == 'up')):
  152. print('up')
  153. rot_el = el[0][0][0]
  154. # print(rot_el.attrib['data-image-rotation'])
  155. # print(rot_el.attrib['data-image-dimensions'])
  156. el.attrib['data-direction'] = 'up'
  157. # print(el.attrib['data-lat'], el.getprevious().attrib['data-lat'])
  158. else:
  159. rot_el = el[0][0][0]
  160. el.attrib['data-direction'] = 'down'
  161. # el.attrib['style'] = 'opacity:0'
  162. new_rotation = image_rotation_down #float(rot_el.attrib['data-image-rotation']) + 180
  163. rot_el.attrib['transform'] = "rotate({} {})".format(str(new_rotation), rot_el.attrib['data-image-dimensions'])
  164. print('down')
  165. # print(rot_el.attrib['data-image-rotation'])
  166. # print(rot_el.attrib['data-image-dimensions'])
  167. # merge tiles into groups
  168. print(index)
  169. print("el.attrib['data-direction'] " + el.attrib['data-direction'])
  170. print("last_state " + last_state)
  171. if index is 1 or last_state != el.attrib['data-direction']:
  172. current_row = ET.SubElement(tile_rows, 'g', attrib={ 'class': 'tile-row' })
  173. copyElem = copy.deepcopy(el)
  174. current_row.insert(0, copyElem)
  175. last_state = el.attrib['data-direction']
  176. root.remove(main_layer)
  177. with open(os.path.join(working_dir,'map.svg'), 'wb') as f:
  178. tree.write(f, encoding='utf-8')
  179. # # get some base satellite map for reference
  180. # apikey = "MYaMHCLtPz1fUfe0FzZqOMI35m893jIV80oeHG19Piw"
  181. # lon_center =
  182. # lat_center =
  183. # zoom =
  184. # map_width =
  185. # request = "https://image.maps.ls.hereapi.com/mia/1.6/mapview?apiKey={}&c={},{}&sb=mk&t=1&z={}&w={}&nodot".format(apikey, lon_center, lat_center, zoom, map_width)
  186. # svg = ET.tostring(tree, encoding="unicode")
  187. # print(svg)
  188. print('Done!')