The exact formatting of geo-tagged videos can vary between
manufacturers and models.

I have a Garmin Dashcam 60, which creates a separate geotagged mpeg
video every minute.

I create the following bash script to create geotagged images to be
uploaded to mapillary (or others).

------
#!/bin/sh


function getEpoch()
{
  vFilename=${1}


  # The Garmin created only save the date and time of creation, not for
each gps point
  # so extract the 'Create Date' string from the video
  vCreate=$(exiftool -ee $vFilename | grep -m 1 "Create Date")
  #  echo $vCreate

  #
  # Posix function to split the string into parts, Date is $4/Time is
$5
  set -- $vCreate
  vDate=$4
  vTime=$5

  #
  # Use the cut function to split the date into year/month/day
  vYear="$(cut -d':'  -f 1 <<< $vDate)"
  vMon="$(cut -d':'  -f 2 <<< $vDate)"
  vDay="$(cut -d':'  -f 3 <<< $vDate)"


  # Use the cut function to split the time into hour/minute/second
  vHour="$(cut -d':'  -f 1 <<< $vTime)"
  vMin="$(cut -d':'  -f 2 <<< $vTime)"
  vSec="$(cut -d':'  -f 3 <<< $vTime)"

  #
  # Generate the epcoch time for the start of each sequence
  # Helps avoid issues with timezones and DST
  vEpoch=$(date -d "$vYear-$vMon-$vDay $vHour:$vMin:$vSec" +%s)

echo $vEpoch
}

function extractGPX()
{
    vFilename=${1}
    echo $vFilename
    #
    # Ensure that gpx folder exists
    mkdir -p gpx

    #
    # Generate a gpx file for each video file with extracted gpx data
    exiftool -p /home/phil/Image-ExifTool-11.93/fmt_files/gpx.fmt -ee
$vFilename > gpx/$vFilename.gpx
}

function dateTimeFiles()
{
    vFilename=${1}
    vEpoch=${2}
    
    # Generate a timestamp and apply to video and gpx
    iTime='--date @'"$(($vEpoch))"''
    touch ${iTime} gpx/$vFilename.gpx
    touch ${iTime} $vFilename
}

function extractImages()
{
    vFilename=${1}
    #
    # Create a folder to put the images if it doesn't already exist
    mkdir -p images

    #
    # Extract images from video at 1 frame per second
    nice -n 100 ffmpeg -i $vFilename -vf fps=1
images/$vFilename.%02d.jpg
}
function dateTimeImages()
{
    vFilename=${1}
    vEpoch=${2}
    #
    # An image for each of the 60 seconds has been created
    # Set the creation time of each 
    for  i in {1..60}
    do
        printf -v j "%02d" $i
        iFile='images/'${vFilename}'.'$j'.jpg'
        iTime='--date @'"$(($vEpoch + $i - 1))"
        touch ${iTime} $iFile
    done
}

function geoTagImages()
{
    #
    # Geotag images based on file time of image
    exiftool -geotag gpx/$vFilename.gpx "-geotime<filemodifydate"
images/$vFilename.*
# Geotag images from an externally generated gpx file
    #    exiftool -geotag gpx/garmin.gpx "-geotime<filemodifydate"
images/$vFilename.*

    
    rm images/*jpg_original

    for  i in {1..60}
    do
        printf -v j "%02d" $i
        iFile='images/'${vFilename}'.'$j'.jpg'
        iTime='--date @'"$(($vEpoch + $i - 1))"
        touch ${iTime} $iFile
    done
}

function processVideo()
{
    vEpoch=$(getEpoch $vFilename)
    vv=$(extractGPX $vFilename)
    vv=$(dateTimeFiles $vFilename $vEpoch)
    vv=$(extractImages  $vFilename )
    vv=$(dateTimeImages $vFilename $vEpoch)
    vv=$(geoTagImages $vFilename $vEpoch)
}

if [ $1 ]
then
    vFilename=${1}
    $(processVideo $vFilename)
else
    for vFilename in *.mp4
    do
        $(processVideo $vFilename)
    done
fi
------

That certainly works and I have been using it for some years now,
although I did find I needed a second script to postprocess the files
to ensure there is at least 4m of movements between images, otherwise
mapillary becomes a movie at junctions.



------
#!/bin/sh


#
# Floor function
# Returns the floor value as an integer from a float
function floor()
{
    float_in=$1
    floor_val=${float_in/.*}
}

#
# Count values
vEmpty=0
vNoFix=0
vNotMoved=0

#
# Initialise values for comparison
aLat=0
aLon=0

for vFilename in  images/*.jpg
do
    #
    # When the dashcam stops, we end up with empty files, these
    # need to be removed
    minimumsize=1
    actualsize=$(du -k "$vFilename" | cut -f 1)
    if [ $actualsize -gt 0 ];
    then
        #
        # Get the Lat/Lon from the file
        bLat=$(exiftool -s -s -s -gpslatitude  -n $vFilename)
        bLon=$(exiftool -s -s -s -gpslongitude -n $vFilename)

        #
        # If there is no gps fix, the values returned will be ±180
        # Only need to check latitude to be able to filter out photos
        # without a valid fix

        floor $bLat
        #        echo $vFilename $bLat $floor_val
    
        if [ $floor_val -ne 180 ] && [ $floor_val -ne -180 ] && [
$floor_val -gt 1 ] 
        then
            # Photo has a valid fix
            # Get the distance travelled since last picture in metre
            geoGetDistance $aLat $aLon $bLat $bLon
            dist=$?

            if [ $dist -gt 4 ]
            then
                # Distance travelled is greater than minimum, so save
and move on to
                # next
                aLat=$bLat;
                aLon=$bLon;
            else
                # Not moved far enough, so delete
                rm $vFilename
                ((vNotMoved++))
            fi
        else
            # No fix so delete
            rm $vFilename
            ((vNoFix++))
        fi
    else
        # File is empty, so delete
        rm $vFilename
        ((vEmpty++))
    fi
done

echo Deleted $vNotMoved files with no movement
echo Deleted $vNoFix files with no fix
echo Deleted $vEmpty empty files
------

Phil (trigpoint)

_______________________________________________
Talk-GB mailing list
[email protected]
https://lists.openstreetmap.org/listinfo/talk-gb

Reply via email to