Skip to content
Snippets Groups Projects
Commit b63701bf authored by Andreas Bircher's avatar Andreas Bircher Committed by Lorenz Meier
Browse files

adding geotagging python script

parent e2be45e8
No related branches found
No related tags found
No related merge requests found
#!/usr/bin/env python
#
# __geotagging__
# Tag the images recorded during a flight with geo location extracted from
# a PX4 log file.
#
# This file accepts *.jpg format images and reads position information
# from a *.px4log file
#
# Example Syntax:
# python geotagging.py --logfile=log001.px4log --input=images/
# --output=imagesWithTag/
#
# Author: Andreas Bircher, Wingtra, http://wingtra.com, in 2016
#
#
__author__ = "Andreas Bircher"
import glob
import os
import pyexiv2
import fractions
from PIL import Image
from PIL.ExifTags import TAGS
import sys
from shutil import copyfile
from optparse import OptionParser
from numpy import genfromtxt
import shutil
import csv
class TriggerList( object ):
def __init__( self ):
self.CAMT_seq = []
self.CAMT_timestamp = []
self.GPOS_Lat = []
self.GPOS_Lon = []
self.GPOS_Alt = []
class ImageList( object ):
def __init__( self ):
self.jpg = []
self.raw = []
def to_degree(value, loc):
if value < 0:
loc_value = loc[0]
elif value > 0:
loc_value = loc[1]
else:
loc_value = ""
absolute_value = abs(value)
deg = int(absolute_value)
t1 = (absolute_value-deg)*60
min = int(t1)
sec = round((t1 - min)* 60, 5)
return (deg, min, sec, loc_value)
def SetGpsLocation(file_name, lat, lng):
"""
Adding GPS tag
"""
lat_deg = to_degree(lat, ["S", "N"])
lng_deg = to_degree(lng, ["W", "E"])
exiv_lat = (pyexiv2.Rational(lat_deg[0] * 60 + lat_deg[1], 60), pyexiv2.Rational(lat_deg[2] * 100, 6000), pyexiv2.Rational(0, 1))
exiv_lng = (pyexiv2.Rational(lng_deg[0] * 60 + lng_deg[1], 60), pyexiv2.Rational(lng_deg[2] * 100, 6000), pyexiv2.Rational(0, 1))
exiv_image = pyexiv2.ImageMetadata(file_name)
exiv_image.read()
exiv_image["Exif.GPSInfo.GPSLatitude"] = exiv_lat
exiv_image["Exif.GPSInfo.GPSLatitudeRef"] = lat_deg[3]
exiv_image["Exif.GPSInfo.GPSLongitude"] = exiv_lng
exiv_image["Exif.GPSInfo.GPSLongitudeRef"] = lng_deg[3]
exiv_image["Exif.Image.GPSTag"] = 654
exiv_image["Exif.GPSInfo.GPSMapDatum"] = "WGS-84"
exiv_image["Exif.GPSInfo.GPSVersionID"] = '2 0 0 0'
exiv_image.write(True)
def LoadPX4log(px4_log_file):
"""
load px4 log file and extract trigger locations
"""
os.system('python sdlog2_dump.py ' + px4_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)
trigger_list = TriggerList()
for seq in range(0, len(line['CAMT_seq']) - 1):
if line['CAMT_seq'][seq] != line['CAMT_seq'][seq + 1]:
trigger_list.CAMT_seq.append(line['CAMT_seq'][seq + 1])
trigger_list.CAMT_timestamp.append(line['CAMT_timestamp'][seq + 1])
trigger_list.GPOS_Lat.append(line['GPOS_Lat'][seq + 1])
trigger_list.GPOS_Lon.append(line['GPOS_Lon'][seq + 1])
trigger_list.GPOS_Alt.append(line['GPOS_Alt'][seq + 1])
return trigger_list
def LoadImageList(input_folder):
"""
load the image list
"""
image_list = ImageList()
for jpg_image in glob.glob(input_folder + "/*.jpg"):
image_list.jpg.append(jpg_image)
for jpg_image in glob.glob(input_folder + "/*.JPG"):
image_list.jpg.append(jpg_image)
for raw_image in glob.glob(input_folder + "/*.RC"):
image_list.raw.append(raw_image)
if len(image_list.jpg) != len(image_list.raw) and len(image_list.jpg) * len(image_list.raw) != 0:
print("Unequal number of jpg and raw images")
if len(image_list.jpg) == 0 and len(image_list.raw) == 0:
print("No images found")
return image_list
def FilterTrigger(trigger_list, image_list):
"""
filter triggers to allow exact matching with recorded images
"""
if len(image_list.jpg) != len(trigger_list.CAMT_seq) and len(image_list.raw) != len(trigger_list.CAMT_seq):
# filter trigger list to match the number of pics
print("No trigger filter implemented yet.")
return trigger_list
def TagImages(trigger_list, image_list, output_folder):
"""
load px4 log file and extract trigger locations
"""
print len(image_list.jpg)
print len(trigger_list.GPOS_Lat)
print len(trigger_list.GPOS_Lon)
for image in range(len(image_list.jpg)):
base_path, filename = os.path.split(image_list.jpg[image])
copyfile(image_list.jpg[image], output_folder + "/" + filename)
SetGpsLocation(output_folder + "/" + filename, float(trigger_list.GPOS_Lat[image]), float(trigger_list.GPOS_Lon[image]))
for image in range(len(image_list.raw)):
base_path, filename = os.path.split(image_list.raw[image])
copyfile(image_list.raw[image], output_folder + "/" + filename)
SetGpsLocation(output_folder + "/" + filename, float(trigger_list.GPOS_Lat[image]), float(trigger_list.GPOS_Lon[image]))
def main():
"""
Main method
"""
parser = OptionParser()
parser.add_option("-l", "--logfile", dest = "LogFile",
help = "PX4 log file containing recorded positions",
metavar = "string")
parser.add_option("-i", "--input", dest = "InputFolder",
help = "Input folder containing untagged images",
type = "string")
parser.add_option("-o", "--output", dest = "OutputFolder",
help = "Output folder to contain tagged images",
type = "string")
(options, args) = parser.parse_args()
if not options.LogFile:
print "please type python " \
"geotagging.py --logfile=[filename] --intput=[folder] [--output=[folder]]"
elif not options.InputFolder:
print "please type python " \
"geotagging.py --logfile=[filename] --intput=[folder] [--output=[folder]]s"
else:
trigger_list = LoadPX4log(options.LogFile)
image_list = LoadImageList(options.InputFolder)
if not options.OutputFolder:
options.OutputFolder = "imagesWithTag"
if not os.path.exists(options.OutputFolder):
os.makedirs(options.OutputFolder)
trigger_list = FilterTrigger(trigger_list, image_list)
TagImages(trigger_list, image_list, options.OutputFolder)
if __name__ == "__main__":
main()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment