How to geolocate drone imagery from a csv table with Python and Piexif - Tutorial
/If your drone doesn´t write the GPS position on the image metadata, this is a tutorial that might be of your interest. When you have the images without any location reference and the image location on another text file you can use the code described below to generate geolocated drone imagery compatible with OpenDroneMap. The tutorial shows all the steps involved besides it has some sample data to practice.
Tutorial
Code
This is the complete Python code:
#!pip install piexif
import piexif
from PIL import Image
import os
import pandas as pd
Open source path and destination path
orgPath='../sensordata/'
destPath='../images/'
Open position data as pandas dataframe
gpsPos = pd.read_csv('../txt/telemetry.dat',index_col=0)
gpsPos.head()
latitude | longitude | altitude | |
---|---|---|---|
imageName | |||
DSC00038.JPG | -11.929715 | -37.662185 | 167.057 |
DSC00039.JPG | -11.929877 | -37.662186 | 167.417 |
DSC00040.JPG | -11.930037 | -37.662191 | 167.231 |
DSC00041.JPG | -11.930192 | -37.662196 | 166.544 |
DSC00042.JPG | -11.930352 | -37.662197 | 167.226 |
Definition of working function for lat and lon parsing
def convertLat(lat):
if lat > 0:
latMarker = b'N'
else:
latMarker = b'S'
lat = abs(lat)
degress = int(lat)
tempMinutes = (lat % 1)*60
minutes = int(tempMinutes)
tempSeconds = (tempMinutes % 1)*60
seconds = int(tempSeconds * 10000)
latTuple = ((degress, 1), (minutes, 1), (seconds, 10000))
return latMarker, latTuple
def convertLon(lon):
if lon > 0:
lonMarker = b'E'
else:
lonMarker = b'W'
lon = abs(lon)
degress = int(lon)
tempMinutes = (lon % 1)*60
minutes = int(tempMinutes)
tempSeconds = (tempMinutes % 1)*60
seconds = int(tempSeconds * 10000)
lonTuple = ((degress, 1), (minutes, 1), (seconds, 10000))
return lonMarker, lonTuple
Loop over files to save geolocated version
for index, row in gpsPos.iterrows():
#working with the exif data
exifDict = {'GPS':
{0: (2, 4, 0, 0),
5: 0}
}
latMarker, latTuple = convertLat(row.latitude)
lonMarker, lonTuple = convertLon(row.longitude)
exifDict['GPS'][1] = latMarker
exifDict['GPS'][2] = latTuple
exifDict['GPS'][3] = lonMarker
exifDict['GPS'][4] = lonTuple
exifDict['GPS'][6] = (int(row.altitude*1000),1000)
#working with the file
#opening the original file
orgName=os.path.join(orgPath,index)
img=Image.open(orgName)
#write the destination file
destNname=os.path.join(destPath,index)
exifBytes = piexif.dump(exifDict)
img.save(destNname, exif=exifBytes)
ODM command in docker to run the drone image processing:
docker run -it --rm -v "$(pwd)/images:/code/images" -v "$(pwd)/odm_orthophoto:/code/odm_orthophoto" -v "$(pwd)/odm_texturing:/code/odm_texturing" opendronemap/odm
Input data
You can download the input data from this link.