Fixed some edge cases on the geo_tag_images.py script. Added explanation to the --kml function. Added more examples for the execution of the script.

This commit is contained in:
h3ct0r
2016-08-02 23:34:26 -03:00
committed by Lorenz Meier
parent 124e1c26d9
commit 3deefb1a79
2 changed files with 75 additions and 38 deletions
+13 -5
View File
@@ -8,14 +8,22 @@ logconv.m: This is a MATLAB script which will automatically convert and display
sdlog2_dump.py: This is a Python script (compatible with v2 and v3) which converts the self-describing binary log format to a CSV file. To export a CSV file from within a shell (Windows CMD or BASH on Linux / Mac OS), run:
python sdlog2_dump.py log001.bin -f "export.csv" -t "TIME" -d "," -n ""
```
python sdlog2_dump.py log001.bin -f "export.csv" -t "TIME" -d "," -n ""
```
geo_tag_images.py: Use this script to geotag a set of images. It uses GPS time and file creation date to synchronize the images, so it needs that the images have a valid creation date.
geo_tag_images.py: Use this script to geotag a set of images. It uses GPS time and file creation date to synchronize the images, so it needs that the images have a valid creation date. Can generate a KML file to view where the photos were taken in Google Earth (including height).
python geo_tag_images.py --logfile=mylog.bin --input=images/ --output=tagged/
```sh
python geo_tag_images.py --logfile=mylog.bin --input=images/ --output=tagged/ --kml -v
python geo_tag_images.py -l=mylog.bin -i=images/ -o=tagged/ --kml -v
```
geotagging.py: Use this script to geotag a set of images. It uses the CAM trigger data from the log file for image association.
python geotagging.py --logfile=mylog.bin --input=images/ --output=tagged/
```sh
python geotagging.py --logfile=mylog.bin --input=images/ --output=tagged/
```
Python can be downloaded from http://python.org, but is available as default on Mac OS and Linux.
+62 -33
View File
@@ -9,7 +9,7 @@
# Example Syntax:
# python geotag.py --logfile=log001.bin --input=images/ --output=imagesWithTag/ --offset=-0.4 -v
#
# Author: Hector Azpurua
# Author: Hector Azpurua hector@azpurua.com
# Based on the script of Andreas Bircher
import os
@@ -22,6 +22,7 @@ import argparse
from lxml import etree
import datetime, calendar
from shutil import copyfile
from subprocess import check_output
from pykml.factory import KML_ElementMaker as KML
from pykml.factory import GX_ElementMaker as GX
@@ -50,7 +51,7 @@ class Main:
self.logfile = args['logfile']
self.input = args['input']
self.output = args['output']
self.klm = args['klm']
self.kml = args['kml']
self.verbose = args['verbose']
self.offset = args['offset']
self.time_tresh = args['treshold']
@@ -58,6 +59,9 @@ class Main:
self.tdiff_list = []
self.non_processed_files = []
self.tagged_gps = []
print '[INFO] Loading logs and images locations...'
self.gps_list = self.load_gps_from_log(self.logfile, self.offset)
self.img_list = self.load_image_list(self.input)
@@ -73,11 +77,11 @@ class Main:
self.tag_images()
if self.klm and len(self.tdiff_list) > 0:
self.gen_klm()
if self.kml and len(self.tdiff_list) > 0:
self.gen_kml()
if len(self.non_processed_files) > 0:
print '[WARNING] Some images werent processed:'
print '[WARNING] Some images werent processed (', len(self.non_processed_files), 'of', len(self.img_list), '):'
for elem in self.non_processed_files:
print '\t', elem
@@ -132,7 +136,7 @@ class Main:
return local_dt.replace(microsecond=utc_dt.microsecond)
def gen_klm(self):
def gen_kml(self):
"""
Generate a KML file with keypoints on the locations of the pictures, including height
:return:
@@ -171,7 +175,7 @@ class Main:
KML.styleUrl('#{0}'.format(style_dot)),
KML.Point(
KML.extrude(True),
KML.altitudeMode('relativeToGround'),
KML.altitudeMode('absolute'),
KML.coordinates("{},{},{}".format(gps.lon, gps.lat, gps.alt))
),
KML.name(str(ii)) if ii % 5 == 0 or ii == 1 else KML.name()
@@ -183,7 +187,7 @@ class Main:
KML.Placemark(
KML.styleUrl('#{0}'.format(style_path)),
KML.LineString(
KML.altitudeMode('relativeToGround'),
KML.altitudeMode('absolute'),
KML.coordinates(
' '.join(["{},{},{}".format(gps.lon, gps.lat, gps.alt) for gps in self.tagged_gps])
)
@@ -207,9 +211,18 @@ class Main:
:param elem:
:return:
"""
dlist_len = len(datetime_list)
i = bisect.bisect_left(datetime_list, elem)
# Cleanup of the indices
if i < 0:
i = 0
elif i >= dlist_len:
i = dlist_len - 1
date = datetime_list[i]
diff = (date - elem).total_seconds()
diff = abs((date - elem).total_seconds())
if diff > self.time_tresh:
return -1, diff
@@ -258,32 +271,46 @@ class Main:
:param offset:
:return:
"""
os.system('python sdlog2_dump.py ' + log_file + ' -f log.csv')
f = open('log.csv', 'rb')
reader = csv.reader(f)
headers = reader.next()
line = {}
for h in headers:
line[h] = []
for row in reader:
for h, v in zip(headers, row):
line[h].append(v)
gps_list = []
for seq in range(0, len(line['GPS_Lat']) - 1):
gps_time = int(line['GPS_TimeMS'][seq + 1])
gps_week = int(line['GPS_Week'][seq + 1])
gps_lat = float(line['GPS_Lat'][seq + 1])
gps_lon = float(line['GPS_Lng'][seq + 1])
gps_alt = float(line['GPS_RelAlt'][seq + 1])
out = check_output(["python", "sdlog2_dump.py", log_file, "-m GPS", "-v"])
for line in out.splitlines():
if not line.startswith("MSG GPS:"):
continue
vdict = {}
pairs = re.split(r'[;,:]\s*', line)
for pair in pairs:
e = pair.split('=')
if len(e) == 2:
vdict[e[0]] = float(e[1])
gps_time = vdict['TimeMS']
gps_week = vdict['Week']
gps_lat = vdict['Lat']
gps_lon = vdict['Lng']
gps_alt = vdict['Alt']
date = self.gps_week_seconds_to_datetime(gps_week, gps_time, leapmillis=offset)
print date
gps_list.append(GpsPosition(date, gps_lat, gps_lon, gps_alt))
return gps_list
def get_image_creation_date(self, filename):
exiv_image = pyexiv2.ImageMetadata(filename)
exiv_image.read()
# Prefer DateTime/Original over the other values
if 'Exif.Photo.DateTimeOriginal' in exiv_image:
cdate = exiv_image['Exif.Photo.DateTimeOriginal'].value
return cdate
elif 'Exif.Image.DateTime' in exiv_image:
cdate = exiv_image['Exif.Image.DateTime'].value
return cdate
else:
epoch = os.path.getmtime(filename)
return datetime.datetime.fromtimestamp(epoch)
def load_image_list(self, input_folder, file_type='jpg'):
"""
Load image list from a folder given a file type
@@ -304,15 +331,16 @@ class Main:
tagged_gps = []
img_size = len(self.img_list)
print '[INFO] Number of images:', img_size
print '[INFO] Number of gps logs:', len(self.gps_list)
dt_list = [x.timestamp for x in self.gps_list]
img_seq = 1
for i in xrange(img_size):
base_path, filename = os.path.split(self.img_list[i])
cdate = datetime.datetime.fromtimestamp(os.path.getmtime(self.img_list[i]))
cdate = self.get_image_creation_date(self.img_list[i])
gps_i, img_tdiff = self.get_closest_datetime_index(dt_list, cdate)
base_path, filename = os.path.split(self.img_list[i])
if gps_i == -1:
self.non_processed_files.append(filename)
@@ -326,8 +354,9 @@ class Main:
(i+1, img_size, filename, cdate, closest_gps.timestamp, img_tdiff, closest_gps.lat, closest_gps.lon, closest_gps.alt)
print msg
copyfile(self.img_list[i], self.output + str(img_seq) + filename)
self.set_gps_location(self.output + str(img_seq) + filename, closest_gps.lat, closest_gps.lon, closest_gps.alt)
output_filename = self.output + str(img_seq) + '_' + filename
copyfile(self.img_list[i], output_filename)
self.set_gps_location(output_filename, closest_gps.lat, closest_gps.lon, closest_gps.alt)
self.tagged_gps.append(closest_gps)
img_seq += 1
@@ -359,7 +388,7 @@ class Main:
default=-17000, required=False, type=float
)
parser.add_argument(
'-klm', '--klm', help='Save the in KML format the information of all tagged images.',
'-kml', '--kml', help='Save the in KML format the information of all tagged images.',
required=False, action='store_true'
)
parser.add_argument(