forked from Archive/PX4-Autopilot
adding geotagging python script
This commit is contained in:
parent
e2be45e8e7
commit
b63701bfdb
|
@ -0,0 +1,189 @@
|
|||
#!/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()
|
Loading…
Reference in New Issue