Late to the party, but i had a similar issue. DJI drone had altitude reading offset by 50 meters. I used this python script to adjust the exif tag instead of re-flying the mission. Hope it can help other people.
-Edit. Provided additional script to adjust XMP header as well. Turns out Drone2Map will read XMP data instead of EXIF when xmp is available. However it should be run on Linux unless you want to compile exempi on windows. I used a Vbox image for this.
import glob
import piexif
from fractions import Fraction
def to_deg(value, loc):
"""convert decimal coordinates into degrees, munutes and seconds tuple
Keyword arguments: value is float gps-value, loc is direction list ["S", "N"] or ["W", "E"]
return: tuple like (25, 13, 48.343 ,'N')
"""
if value < 0:
loc_value = loc[0]
elif value > 0:
loc_value = loc[1]
else:
loc_value = ""
abs_value = abs(value)
deg = int(abs_value)
t1 = (abs_value-deg)*60
min = int(t1)
sec = round((t1 - min)* 60, 5)
return (deg, min, sec, loc_value)
def change_to_rational(number):
"""convert a number to rantional
Keyword arguments: number
return: tuple like (1, 2), (numerator, denominator)
"""
f = Fraction(str(round(number,4)))
return (f.numerator, f.denominator)
def change_to_decimal(fraction):
"""convert fraction tuple to decimal
keyword arguments: fraction -- tuple like (numerator, denominator)
return: float"""
return (fraction[0]/fraction[1])
def set_gps_location(file_name, lat, lng, altitude):
"""Adds GPS position as EXIF metadata
Keyword arguments:
file_name -- image file
lat -- latitude (as float)
lng -- longitude (as float)
altitude -- altitude (as float)
"""
lat_deg = to_deg(lat, ["S", "N"])
lng_deg = to_deg(lng, ["W", "E"])
exiv_lat = (change_to_rational(lat_deg[0]), change_to_rational(lat_deg[1]), change_to_rational(lat_deg[2]))
exiv_lng = (change_to_rational(lng_deg[0]), change_to_rational(lng_deg[1]), change_to_rational(lng_deg[2]))
gps_ifd = {
piexif.GPSIFD.GPSVersionID: (2, 0, 0, 0),
piexif.GPSIFD.GPSAltitudeRef: 1,
piexif.GPSIFD.GPSAltitude: change_to_rational(round(altitude)),
piexif.GPSIFD.GPSLatitudeRef: lat_deg[3],
piexif.GPSIFD.GPSLatitude: exiv_lat,
piexif.GPSIFD.GPSLongitudeRef: lng_deg[3],
piexif.GPSIFD.GPSLongitude: exiv_lng,
}
exif_dict = {"GPS": gps_ifd}
exif_bytes = piexif.dump(exif_dict)
piexif.insert(exif_bytes, file_name)
def change_gps_altitude(file_name, delta_altitude):
exif_dict = piexif.load(file_name)
gps_altitude = exif_dict['GPS'][piexif.GPSIFD.GPSAltitude]
gps_altitude = change_to_rational(change_to_decimal(gps_altitude)+delta_altitude)
print("altitude: " + str(gps_altitude))
exif_dict['GPS'][piexif.GPSIFD.GPSAltitude] = gps_altitude
exif_bytes = piexif.dump(exif_dict)
piexif.insert(exif_bytes, file_name)
delta_altitude = 47.97
path = "C:\\Users\\tli\\Pictures\\Drone2Map_Pilot\\"
file_list = [f for f in glob.glob(path + "**/*.JPG", recursive=True)]
for file_name in file_list:
print("Processing: " + file_name)
change_gps_altitude(file_name, delta_altitude)
XMP adjust
from libxmp import XMPFiles, consts
import glob
def change_xmp_altitude(file_name, delta_altitude):
xmpfile = XMPFiles(file_path=file_name, open_forupdate=True)
xmp = xmpfile.get_xmp()
dji_uri = "http://www.dji.com/drone-dji/1.0/"
xmp_absalt = xmp.get_property(dji_uri, "AbsoluteAltitude")
str_translation = dict.fromkeys(map(ord, '+'), None)
xmp_absalt = xmp_absalt.translate(str_translation)
xmp_absalt = "+" + str(round(float(xmp_absalt) + delta_altitude, 2))
xmp.set_property(dji_uri, "AbsoluteAltitude", xmp_absalt)
if xmpfile.can_put_xmp(xmp):
xmpfile.put_xmp(xmp)
xmpfile.close_file()
print(xmp_absalt, "New XMP Altitude Entered for: ", file_name)
delta_altitude = 47.97
path = "/home/tli/COG/Drone2MapTest"
file_list = [f for f in glob.glob(path + "**/*.JPG", recursive=True)]
for file_name in file_list:
print("Processing: " + file_name)
change_xmp_altitude(file_name, delta_altitude)