How to geolocate drone imagery from a csv table with Python and Piexif - Tutorial

geolocateDroneImagery.jpg

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.

4 Comments

Saul Montoya

Saul Montoya es Ingeniero Civil graduado de la Pontificia Universidad Católica del Perú en Lima con estudios de postgrado en Manejo e Ingeniería de Recursos Hídricos (Programa WAREM) de la Universidad de Stuttgart con mención en Ingeniería de Aguas Subterráneas y Hidroinformática.

 

Suscribe to our online newsletter

Subscribe for free newsletter, receive news, interesting facts and dates of our courses in water resources.