Disclaimer per i contenuti del Blog


DISCLAIMER:Questo blog non rappresenta una testata giornalistica in quanto viene aggiornato senza alcuna periodicità . Non può pertanto considerarsi un prodotto editoriale ai sensi della legge n° 62 del 7.03.2001.
L'autore non è responsabile per quanto pubblicato dai lettori nei commenti ad ogni post. Verranno cancellati i commenti ritenuti offensivi o lesivi dell’immagine o dell’onorabilità di terzi, di genere spam, razzisti o che contengano dati personali non conformi al rispetto delle norme sulla Privacy. Alcuni testi o immagini inserite in questo blog sono tratte da internet e, pertanto, considerate di pubblico dominio; qualora la loro pubblicazione violasse eventuali diritti d'autore, vogliate comunicarlo via email. Saranno immediatamente rimossi. L'autore del blog non è responsabile dei siti collegati tramite link, del loro contenuto che può essere soggetto a variazioni nel tempo ne degli eventuali danni derivanti dall'utilizzo proprio od improprio delle informazioni presenti nei post.

martedì 10 novembre 2015

PHP: Georeferenziare un'immagine utilizzando un file GPX

Procedendo con lo sviluppo di polpiteam.it, il mio portale per la condivisione di percorsi escursionistici, mi sono imbattuto nel problema, apparentemente complesso, di georeferenziare delle immagini scattate con fotocamere prive di GPS durante una escursione per poterle posizionare su una mappa di Google Maps, lungo la linea del percorso ricavata da un GPS.
Complesso solo apparentemente perché una fortunata googolata mi ha portato a conoscenza di un software per Windows che, utilizzando il file GPX del percorso ed interpolandolo con la data/ora di scatto, permetteva di estrapolare latitudine e longitudine dello scatto. Il programma in se non mi è servito a nulla ma l'idea SI!

Ho implementato in PHP un piccolo esempio (scaricabile qui) con tanto di immagine e file GPX per provarlo subito.

Ecco il codice, si potrebbe ottimizzare utilizzando una ricerca dicotomica sull'array dei punti (l'array ha un indice numerico proprio in previsione di questa modifica) e sicuramente andranno aggiunti ulteriori controlli ma l'idea è funzionante ed utilizzabile:

<?php
//*******************************************************
//* Esempio di una semplice tecnica per georeferenziare *
//* immagini scattate con fotocamera priva di GPS       *
//* elaborando il file GPX ottenuto utilizzando uno dei *
//* tanti software di registrazione percorsi installato *
//* sullo SmartPhone.                                   *
//*                                                     *
//* NOTA:                                               *
//* E' necessario che la versione minima di PHP sia la  *
//* 4.2.0, che siano utilizzabili le librerie standard  *
//* "SimpleXML" ed "Exif"                               *
//*                                                     *
//*                                                     *
//*******************************************************
//* Paolo Bertinetti - info@paolobertinetti.it          *
//*******************************************************

//* Inizializzo il timezone (IMPORTANTE)
date_default_timezone_set("Europe/Rome");

//******************************************************
//* Questa funzione restituisce un array con tutti i   *
//* punti presenti nel file GPX                        *
//******************************************************
function loadGPX($gpx){
    //* Carico in una array tutti i trackpoint del file GPX
    $gpxArray = new SimpleXMLElement(file_get_contents($gpx));
    $tp = array();
    foreach ($gpxArray->trk->trkseg as $seg) {
        foreach ($seg->trkpt as $point) {
            $tp[count($tp)] = array("lat"=>(float)$point->attributes()->{'lat'}, 
                                    "lon"=>(float)$point->attributes()->{'lon'}, 
                                    "ele"=>(int)$point->ele, 
                                    "time"=>(string)$point->time);
        }
    }
    return $tp;
} 

//******************************************************
//* Questa funzione cerca nell'array il primo elemento *
//* del GPX con data/ora maggiore od uguale a quella   *
//* della fotografia                                   *
//******************************************************
function searchImage($img, $tp) {
//* Carico in un array le informazioni EXIF, 
//* se presenti, per ricavare data ed ora dello scatto
    $exif = exif_read_data($img, "ANY_TAG", true);
//* Verifico la presenza dei dati EXIF
    if (!($exif === false)) {
//* Verifico la presenza della sezione dedicata 
//* alla data/ora dello scatto
        if (isset($exif["EXIF"]["DateTimeOriginal"])) {
//* Compongo data ed ora nel formato "AAAA-MM-GG HH:MM:SS"
            $d = explode(" ", $exif["EXIF"]["DateTimeOriginal"]);
            $dateTime = str_replace(":", "-", $d[0])." ".$d[1];
//* Ora $dateTime contiene la data della foto, converto in formato UTC
            $dtUTC = gmdate('Y-m-d H:i:s', strtotime($dateTime));
//* Separo data ed ora...
            list($d, $t) = split(" ", $dtUTC);
//* ...e li ricompongo ottenendo il formato utile per la 
//* comparazione con il campo <time></time> del file GPX
            $dt = $d."T".$t."Z";
//* Verifico che la data da cercare sia inclusa nell'array di coordinate
            if ($dt >= $tp[0]["time"] and $dt <= $tp[count($tp)-1]["time"]) {
                foreach  ($tp as $point) {
//* Cerco il primo elemento del GPX con data posteriore a quella dell'immagine
                    if ($point["time"] >= $dt) {
//* Trovato!
                        $answer = array(0, $point["lat"] ,$point["lon"], $point["ele"]);
                        break;
                    }
                }
            }
            else {
// La data dell'immagine non è compresa bel file GPX
                $answer = array(1, null, null, null); 
            }
        }
        else {
// Campo DateTimeOriginal non trovato nella sezione EXIF
            $answer = array(2, null, null, null); 
        }
    }
    else {
// Dati EXIF non trovati nell'immagine
        $answer = array(3, null, null, null); 
    }
    return $answer;
}

/*** MAIN *****************************************************************/

//* Inizializzo le variabili con il nome del file GPX e quello del file JPG
$gpxName = "testgpx.gpx";
$imgName = "testimg.jpg";
//* Chiamo la routine di caricamento GPX
$trackPoints = loadGPX($gpxName);
//* Chiamo la routine di ricerca della data/ora di scatto nel file GPX
list($rc, $la, $lo, $al) = searchImage($imgName, $trackPoints);
//* Visualizzo i risultati
echo $rc===0  ? "Lat:$la Lon:$lo Alt:$al" : "Data scatto non trovata nel file GPX";
?>


Nessun commento:

Posta un commento