Geolocalizzare i tile OpenStreetMap 2: meglio…

Eccomi di nuovo

un piccolo post di correzione/ampliamento di quanto detto qui in precedenza. Si stava parlando di come identificare, all’interno di un file grafico contenente un tile di una mappa openstreetmap, le coordinate XY corrispondenti a una posizione geografica (latitudine/longitudine). Il metodo che avevo suggerito sostanzialmente consisteva in una interpolazione: conosco le coordinate gps degli estremi dell’immagine, interpolo linearmente e ricavo le coordinate di ciascun pixel. Questo metodo, ahimè, non funziona. O meglio, funziona per mappe in scala ridotta, mentre è assolutamente pessimo per mappe ampie, in cui, per via del tipo di proiezione utilizzato, i gradi di latitudine e longitudine non sono equispaziati.

Dopo aver provato di tutto, compreso studiare un libro di geografia, la soluzione mi è apparsa in sogno ed è di una banalità sconvolgente: basta usare la funzione di conversione coordinate/tile, facendosi ritornare anche i decimali!

Mi spiego meglio: la funzione di cui sopra e già vista in passato, dopo aver modificato il cast per passare da int a float, è:

def deg2num(self, lat_deg, lon_deg, zoom):
   lat_rad = math.radians(lat_deg)
   n = 2.0 ** zoom
   xtile = float((lon_deg + 180.0) / 360.0 * n)
   ytile = float((1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
   return (xtile, ytile)

A questo punto supponiamo di avere tra le mani il tile 100,200 con un certo zoom, e di voler trovare la posizione XY di una coppia di coordinate (lat,lon) che sappiamo a priori essere contenuti nel nostro tile. Se passiamo questi parametri alla funzione di cui sopra (lat, lon e zoom), dovremmo ottenere un risultato del tipo:

(100,12345 200,65432)

Ovvero le coordinate intere del nostro tile più una parte decimale. Dobbiamo prendere questi valori e togliere la parte intera, e moltiplicare i decimali rimanenti per la dimensione (rispettivamente larghezza e altezza) del nostro tile in pixel; nel caso dei tile openstreetmap entrambe le dimensioni sono 256.

Voilà!

Pubblicato in Uncategorized | Contrassegnato , , | Lascia un commento

Il valore dei dati personali

Oggi ho cliccato, scioccamente, sul link di un giochino su Facebook. Odio i giochini e i loro fastidiosissimi inviti, ma ho voluto provare poichè il titolo sembrava accattivante. Questo è quello che mi sono trovato davanti:

facebook_assurdo

Cioè, ma siamo impazziti? Io per provare un giochino idiota su un social network devo regalare al suo sviluppatore tutte le mie informazioni di profilo (la mia data di nascita?!?!? la mia residenza attuale!?!?!?!) e dargli carta bianca di pubblicare contenuto a mio nome e vedere la lista dei miei amici? Cioè, ma siamo scemi? Ma c’è davvero gente che accetta uno scambio del genere?

Purtroppo si. Aprite gli occhi, gente. Just my two cents, of course.

Pubblicato in Uncategorized | Contrassegnato , , | Lascia un commento

Disegnare grafici in Python con Matplotlib

example

Per disegnare grafici in Python esiste la comodissima libreria MatPlotLib (qui la versione per windows), in particolare il suo modulo PyPlot. Permette di creare canvas su cui poi realizzare grafici, con una sintassi Matlab-like. Ad esempio, per creare un grafico a partire da due vettori di coordinate cartesiane è sufficiente questo codice:

import matplotlib.pyplot as plt

# impostazione font assi
plt.rc('xtick', labelsize=8)
plt.rc('ytick', labelsize=8)

# creazione canvas (le misure sono in pollici))
plt.figure(figsize=(4, 1.5))

# disegno grafico
plt.plot([1,2,3,4,5], [10,20,30,40,50])

# titolo grafico
plt.title("test")

# salvataggio su file
plt.savefig("example.png")

Una cosa molto interessante per un lavoro che sto facendo in questi giorni è la possibilità di inserire un grafico pyplot in una immagine PIL, passando per un buffer. Una cosa del genere:

# parto da una immagine PIL
x = .....
# disegno il grafico
plt....

# creo un buffer vuoto
buf = io.BytesIO()

# salvo il plot nel buffer
plt.savefig(buf, format = 'png')

# "riavvolgo" il buffer
buf.seek(0)

# apro l'immagine nel buffer come immagine PIL
im = PILImage.open(buf)

# inserisco il grafico nell'immagine di partenza
# alle coordinate 600, 10 pixel
x.paste(im, (600,10))

# elimino il buffer
buf.close()
Pubblicato in Uncategorized | Contrassegnato , , , | Lascia un commento

Geolocalizzare i tile di OpenStreetMap

coordToXYNella scorsa puntata abbiamo visto come creare una mappa scaricando un tile da openstreetmap. In questa puntata vi mostrerò come creare una mappa geolocalizzata, ovvero una mappa in cui è possibile identificare un legame diretto tra la posizione del pixel (x, y) e una posizione geografica (latitudine – longitudine). In questo modo è possibile riportare coordinate geografiche direttamente sull’immagine.

Il procedimento è abbastanza semplice. Per prima cosa ci si procura la mappa. Supponiamo di scaricarla da OSM col metodo visto in precedenza. Sempre in precedenza abbiamo visto come calcolare gli indici del tile da scaricare a partire dalle coordinate di un punto e dallo zoom. E’ possibile anche l’operazione inversa: a partire dagli indici e dallo zoom è possibile calcolare le coordinate geografiche di un punto (in punto in alto a sinistra, ovvero a nord-ovest) nel tile.

import math
def num2deg(self, xtile, ytile, zoom):
  n = 2.0 ** zoom
  lon_deg = xtile / n * 360.0 - 180.0
  lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * ytile / n)))
  lat_deg = math.degrees(lat_rad)
  return (lat_deg, lon_deg)

Con questa funzione è semplice calcolare le coordinate di tre estremi della mappa, ad esempio gli angoli in alto. Vogliamo calcolare l’ampiezza della mappa sia in lunghezza che in larghezza espressa in gradi. Per trovare le coordinate dell’angolo in alto a destra si usa la funzione precedente sul tile X+1, per calcolare le coordinate dell’angolo in basso a sinistra il tile Y+1.

# calcolo delle coordinate del tile
# a partire dalle coordinate del punto che voglio disegnare
# (la funzione è quella vista nel post precedente)
x, y = deg2num(lat, lon, zoom)

# limiti mappa
upperLeftLat, upperLeftLon = num2deg(x, y, zoom)
upperRightLat, upperRightLon = num2deg(x+1, y, zoom)
bottomLeftLat, bottomLeftLon = num2deg(x, y+1, zoom)

A questo punto abbiamo le coordinate degli estremi della mappa, non dobbiamo fare altro che calcolare le dimensioni della mappa in pixel e fare le dovute proporzioni.

# coordinate da individuare sulla mappa
lat = XXXXXXX
lon = XXXXXXX

# larghezza e lunghezza della mappa in gradi
deltaLat = upperLeftLat - bottomLeftLat
deltaLon = upperRightLon - upperLeftLon

# larghezza e lunghezza della mappa in pixel
# (supponendo che la mappa sia un oggetto grafico PIL)
imgWidth, imgHeight = oggettoMappa.size

# coordinate calcolate
Y = imgHeight - int(float((lat - bottomLeftLat) * imgHeight) / float(deltaLat))
X = int(float((lon - upperLeftLon) * imgWidth) / float(deltaLon))
Pubblicato in Uncategorized | 1 commento

Recuperare una mappa con Python e OpenStreetMap

OpenStreetMap, come molti sanno, è un servizio online che realizza una mappa libera e gratuita di ogni parte del mondo, grazie a numerosissimi volontari che armati di gps e pazienza registrano informazioni geografiche e le inseriscono nel sistema. Uno dei servizi offerti da openstreetmap è la possibilità di scaricare, in modo facile, singole porzioni di mappa da utilizzare nei propri progetti.

Per scaricare un “quadratino” di mappa, vale a dire un PNG di 256×256 pixel, a partire da una coordinata GPS (latitudine e longitudine) e da un valore di zoom (da 1 a 18, 18 è molto dettagliato e 1 è molto ampio), bisogna per prima cosa calcolare le coordinate XY del quadratino stesso all’interno dei server di openstreetmap. Questo è il codice che uso normalmente, è in python ma può essere facilmente portato in qualunque altro linguaggio:

def deg2num(lat_deg, lon_deg, zoom):
   lat_rad = math.radians(lat_deg)
   n = 2.0 ** zoom
   xtile = int((lon_deg + 180.0) / 360.0 * n)
   ytile = int((1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
   return (xtile, ytile)

A questo punto si scarica il quadratino stesso dall’URL:

http://tile.openstreetmap.org/[ZOOM]/[X]/[Y].png

Ad esempio, per vedere la facoltà di ingegneria di brescia [45.5648 N, 10.2318 E], con uno zoom abbastanza alto (16), calcoliamo le coordinate XY=(34630, 23428) e scarichiamo l’URL:

http://tile.openstreetmap.org/16/34630/23428.png

Ed ecco il risultato:

Image

A questo punto, se vogliamo fare le cose in grande, possiamo costruire uno script python che scarica la mappa e la salva su un file:

import sys, math, os, urllib
import PIL, cStringIO
from PIL import ImageDraw
from PIL import Image as PILImage

def deg2num(lat_deg, lon_deg, zoom):
  lat_rad = math.radians(lat_deg)
  n = 2.0 ** zoom
  xtile = int((lon_deg + 180.0) / 360.0 * n)
  ytile = int((1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
  return (xtile, ytile)

def gpsUrl(lat, lon, zoom, xshift=0, yshift=0):
  (x, y) = deg2num(lat, lon, zoom)
  imUrl = "http://tile.openstreetmap.org/%s/%s/%s.png"%(zoom, x+xshift, y+yshift)
  return imUrl

def getImage(url):
  file = urllib.urlopen(url)
  imRead = cStringIO.StringIO(file.read())
  return PIL.Image.open(imRead)

lat = 45.5648
lon = 10.2318
zoom = 16
mappa = getImage(gpsUrl(lat, lon, zoom,0,0))
mappa.save("file.png")

Il programma di cui sopra richiede l’installazione della libreria python PIL. Ulteriori informazioni per l’installazione e il download sono disponibili qui.

Pubblicato in Uncategorized | Contrassegnato , , | 1 commento

Clonare un disco Virtualbox: il problema dell’UUID

In Virtualbox ciascun disco è rappresentato da un file. Quindi, per clonare un disco è sufficiente fare una copia del file. C’è però un inghippo: ogni disco fisso virtuale è rappresentato da un UUID, un identificativo UNICO. E Virtualbox non permette di aggiungere a una macchina due dischi con lo stesso UUID. La soluzione è nascosta in una funzioncina da riga di comando, da eseguire sul file copiato e che ne modifica l’UUID:

vboxmanage internalcommands sethduuid .\MyVM.vdi

Lascio qui questa perla per chi ne dovesse avere bisogno un domani.

Pubblicato in Uncategorized | Contrassegnato , , | Lascia un commento

Installazione PySide su Mac Os X

Sto installando PySide sul Mac. Si tratta di una libreria di binding tra Python e le QT, per realizzare interfacce grafiche (e non solo).. si, mi sono stufato di Tkinter… E’ più o meno la stessa cosa delle ben più note PyQT, ma con una licenza più libera (le PyQt sono solo GPL o commerciali, mentre PySide è LGPL e quindi può essere inserito anche in software non open.. casomai servisse).

Un paio di considerazioni che potrebbero far risparmiare tempo a qualcuno:

1) usate MacPorts.. l’installazione manuale dei pacchetti scaricati dal sito funziona ma fa qualche casino con i path e non riesco a venirne a capo.. il comando è:

sudo port install py27-pyside

2) pare che il CMake usato da macports per compilare le dipendenze vada di default a cercare librerie in /Library/Frameworks, ignorando quindi le equivalenti librerie nei port. Il che è un problema, visto che queste librerie (fornite con Mac Os) non sono compatibili. Ci sono sistemi più o meno raffinati per sistemare i path, ma il sistema migliore è momentaneamente rinominare la directory /Library/Frameworks con un nome diverso, e rimetterla a posto al termine della compilazione.

3) PySide richiede (ovviamente) le QT, e per compilarle ci vogliono ore.. è tutto automatico, comunque, quindi non dovete far altro che portare pazienza. Stessa cosa per il pacchetto py27-pyside…

4) Assicuratevi di avere almeno 3 o 4 giga liberi su disco.. la compilazione delle QT crea un mucchio di file temporanei..

5) Una volta fatto tutto, sappiate comunque che se volete essere certi del funzionamento dovete usare il python fornito nei macports:

/opt/local/bin/python2.7

Si, mi sa che mi sono incasinato con i path.. comunque in questo modo funziona!

Pubblicato in Uncategorized | Lascia un commento

Creare un ramdisk sotto Mac Os X

Un ramdisk altro non è che un “disco” virtuale, che funziona come un disco a tutti gli effetti ma risiede in RAM.. il che significa che:

1) è più veloce del normale disco di sistema
2) non è soggetto a usura, il che significa che è più adatto a operazioni di lettura/scrittura molto fitte (ad esempio quando si sperimenta con script o programmi particolari).
3) quando viene smontato, o quando si spegne il computer, il suo contenuto è PERSO IRRIMEDIABILMENTE, il che può essere positivo quando si lavora, ad esempio, con dati delicati.

Per creare un ramdisk si usa il comando:

diskutil eraseVolume HFS+ "ramdisk" `hdiutil attach -nomount ram://800000`

La seconda parte, tra apici retroversi (non quelli sotto il ? sulla tastiera, bensì quelli che si digitano premendo ALT+9), crea un disco in RAM, mentre la prima prende il disco appena creato, lo etichetta col nome “ramdisk” e lo formatta in HFS+, rendendolo pronto all’utilizzo. La dimensione è legata al numero in fondo al comando: 800’000 corrisponde a 400 MB.

Il nuovo disco appare nel finder e in dev (di solito è qualcosa del tipo /dev/disk1, 2, …). Per eliminarlo basta smontarlo, con l’iconcina di eject nel finder.

Ciao a tutti!

Mario 

Pubblicato in Uncategorized | Lascia un commento

Rsync: backup su Mac Os X

Rsync è una utility standard del mondo unix per sincronizzare tra loro due cartelle, sia in locale che in remoto (ad esempio via SSH). Rsync effettua una copia incrementale: se lancio una seconda volta il comando di sincronizzazione, rsync invierà solo i file che risultano modificati rispetto alla sincronizzazione precedente. Questo lo rende ottimo per fare copie di backup di cartelle di lavoro: io lo uso per tenere su una chiavetta USB la cartella contenente i miei lavori per l’università (una copia in più non fa mai male!).

Per usarlo su Mac Os X, bisogna però tenere conto di un paio di cosette che ho scoperto dopo noiose ricerche e quindi pubblico a beneficio dei miei 2 lettori:

1) Rsync è compreso nell’installazione standard di Mac Os X Snow Leopard (eh, lo so, ma il mio processore non è supportato da Lion quindi non ho informazioni più fresche); sfortunatamente è una versione giurassica. Si può risolvere aggiornando con MacPorts: supponendo che lo abbiate installato basta lanciare un comando:

sudo port install rsync

Una volta installato, però, non andrà a sovrascrivere la versione di rsync di default. Dovete quindi eseguirla andando a inserire il path completo in cui risulta installata la nuova versione:

/opt/local/bin/rsync

Per verificare la versione effettiva potete usare l’opzione –version

/opt/local/bin/rsync --version

2) Se volete essere sicuri di poter leggere i vostri backup con qualunque sistema operativo (cosa senz’altro desiderabile) conviene utilizzare una normalissima chiavetta usb formattata in FAT32. Questo però nasconde un’insidia: FAT32 gestisce le date a intervalli di 2 secondi.. se considerate che rsync va a vedere la data di modifica di un file per capire se copiarlo o meno, capirete che in assenza di provvedimenti ogni volta il backup sarà di TUTTI i file.. scomodo.. per rimediare si usa l’opzione

--modify-window=1

che lascia un margine di un secondo sulla valutazione del tempo di ultima modifica del file..

Concludendo, questa è la riga che uso per fare un backup dei miei dati (da una cartella /Users/mario/Documents/roba_di_scuola/ a una chiavetta con nome di partizione BACKUPPO); è un’unica riga, io l’ho separata per renderla più leggibile!

/opt/local/bin/rsync -aEv --modify-window=1 --progress
   /Users/mario/Documents/roba_di_scuola/ 
   /Volumes/BACKUPPO/roba_di_scuola/

Spero che vi possa essere d’aiuto, saluti a tutti!

Pubblicato in Uncategorized | Contrassegnato , , , | Lascia un commento

mvregen: un tool per rigenerare link MegaVideo

Ma quanto è bello MegaVideo? Per chi non lo sapesse, si tratta di una piattaforma per l’hosting di file video. Un utente si registra e carica i propri video su questo sito, e in cambio riceve un codice: usando quel codice un altro utente qualunque può vedere il suddetto video. Ovviamente, lo scopo nascosto (neanche troppo) della piattaforma è l’hosting di materiale protetto da copyright, ma si possono trovare anche cose legali.

Il problema è che, proprio per proteggere i contenuti (specie quelli illegali), non è possibile eseguire alcun tipo di ricerca sul sito: per vedere un video bisogna conoscerne il codice. Il codice è per intenderci quello nell’URL:

http://www.megavideo.com/?v=113GXHGK

E purtroppo i codici vengono spesso invalidati (o semplicemente scadono). Quindi capita molto spesso di trovarsi tra le mani con un elenco di URL che, una volta cliccati, puntano inesorabilmente a qualcosa del genere:

Per fortuna esiste la soluzione: in realtà, quando un file viene caricato su MegaVideo, ne vengono fatte più copie sui diversi server (o almeno così mi risulta), per meglio gestire il traffico sulla piattaforma. Quindi, per ogni URL cancellato spesso ne esistono altri che puntano allo stesso file. Si possono trovare facendo una ricerca (detta curiosamente “rigenerazione”) su certi siti specializzati, come ad esempio regen.megastreaming.org. Si va sul sito, si inserisce l’URL, si clicca, si aspetta, si dribbla la pubblicità, si ignorano i popup e forse alla fine si arriva al risultato (il risultato presentato in realtà mostra il link megavideo ma se cliccato porta a un servizio a pagamento, quindi bisogna pure fare il copia&incolla dell’url). Insomma, un pò lungo se uno si vuole rigenerare una lista completa di link..

E in questo punto si colloca mvregen. Si tratta di una simpatica utility in Python che si occupa di tutti i task noiosi relativi alla rigenerazione dei link MegaVideo. E’ sufficiente passare il codice da rigenerare da riga di comando (opzione -c):

./mvregen.py -c XXXXXXXX

oppure direttamente con l’url usando l’opzione -u:

./mvregen.py -u http://www.megavideo.com/v=XXXXXXXX

o addirittura si può passare un intero file esterno con un link per ogni riga, per rigenerare tutta una serie di link in un unico comando (vengono ignorate le linee vuote e quelle di commento, ovvero che iniziano con un #. Consiglio di mettere un commento prima di ogni link, poichè il commento viene stampato nell’output e aiuta a riconoscere il link rigenerato).

./mvregen.py -f miofile.txt

L’output (solo i link rigenerati più i commanti) può essere anche salvato su un file di testo, con l’opzione -o, o addirittura in formato HTML (per avere i link già pronti a essere cliccabili!), con l’opzione -t. Ad esempio, se ho un file di link megavideo non funzionanti chiamato link.txt e voglio creare un file HTML con i link rigenerati, basta usare:

./mvregen.py -f link.txt -t link.html

Per ulteriori informazioni è sufficiente lanciare il programma con l’opzione -h per leggere l’help online. Può anche essere interessante utilizzare l’opzione -v (verbose) per seguire i passaggi che il software esegue nel rigenerare i link.

Il tool, come dicevo, è scritto in Python, quindi si suppone che funzioni su qualunque piattaforma moderna. Io l’ho provato su MacOsX e Linux e funziona perfettamente. Lo sviluppo avviene su GitHub, da cui lo potete scaricare (c’è un pulsante “Downloads” da qualche parte). Ovviamente è rilasciato open source (sotto licenza MIT).

Spero possa essere utile a qualcuno. Se è così mi aspetto come minimo un commento :-)

Ciao!

 

Pubblicato in Uncategorized | Contrassegnato , , , , | 6 commenti