desarrollo,  python

Python y OpenStreetMap, GEOPY – cómo conocer una dirección a partir de coordenadas GPS.

En entradas anteriores vimos como obtener las coordenadas GPS donde se tomó una fotografía por medio de la interpretación de los datos EXIF.

Sin embargo, las coordenadas 37.3861888 -5.9925535 a la mayoría de nosotros nos dicen poco. Necesitamos convertirlo a algo más familiar para saber a que lugar nos referimos, una calle, una ciudad y un país, o un monumento conocido. Algo que «traduzca» 37.3861888 -5.9925535 a «la Giralda de Sevilla«.

Siguiendo con el ejemplo, si a partir de una foto obtengo las coordenadas 37.87943195 -4.77986509433761, ¿cómo se a que lugar corresponden?

Nominatim – OpenStreetMap

Nominatim es un servicio de OpenStreetMap, por supuesto gratuito, que proporciona información a partir de coordenadas GPS o una dirección.

Nominatim tiene una cómoda e intuitiva interfaz web y como veremos a continuación, una API accesible desde Python con la que podemos integrarlo en nuestros proyectos.

En el caso de Monumentos únicamente es necesario escribir su nombre, por ejemplo, la Mezquita de Córdoba:

O la Giralda de Sevilla:

Pulsando «details» obtendremos información más detallada:

Todo esto sin duda es muy util, ahora, veamos como utilizarlo en nuestro código.

Nominatim en Python – CoordsGPS a direcciones

Instalar Geopy

Instalamos geopy, cliente Python para los servicios de geocodificación más utilizados, entre ellos OpenStreetMap:

pip3 install geopy

Codigo fuente

Incluimos la referencias a las librerias:

from geopy.geocoders import Nominatim
from geopy.exc import GeopyError

Y dos funciones:

  • get_coords(saddress) – para obtener coordenadas a partir de dirección o nombre de monumento.
  • get_address(lan, lon) – para obtener dirección a partir de coordenadas.
def get_coords(saddress):
	try:
		geolocator = Nominatim(user_agent="altaruru_testgeopy")
		location = geolocator.geocode(saddress)
		print("C# %s %s  ---> %s" % (location.latitude, location.longitude, location.address))
		#print(location.raw)
		return location.latitude, location.longitude
	except:		
		debug.print_exception()
		return None	

def get_address(lan, lon):
	try:
		geolocator = Nominatim(user_agent="altaruru_testgeopy")
		scoord = ("%s %s" % (lan, lon))
		location = geolocator.reverse(scoord)
		print("A# %s %s  ---> %s" % (location.latitude, location.longitude, location.address))
		#print(location.raw)
		return location.address
	except:		
		debug.print_exception()
		return None	

Para el control de excepciones utilizo debug.print_exception(), si te interesa mira esta entrada: control de excepciones python

Ejemplo 1

print("###")
get_address("37.3937585","-5.9976877")
get_coords("Calle Betis 18, Sevilla, Andalucía, España")
get_coords("Mezquita, Córdoba, Andalucía, España")
print("###")

Genera la salida por Terminal:

###
A# 37.3937585 -5.9976877  ---> Catedral, Calle Virgen de los Buenos Libros, San Vicente, Casco Antiguo, Sevilla, Andalucía, 41001, España
C# 37.3057938 -4.6711331  ---> Calle Betis, Barriada  Olof Palme, Badolatosa, Sevilla, Andalucía, España
C# 37.87943195 -4.77986509433761  ---> Mezquita, El Salvador y La Compañía, Santiago, Distrito Centro, Córdoba, Andalucía, España
###

Ejemplo 2

Algunos ejemplos de llamadas

get_coords("Parque de Maria Luisa, Sevilla, Andalucía, España")
get_coords("Parque de los Príncipes, Sevilla, Andalucía, España")
get_coords("Catedral, Sevilla, Andalucía, España")
get_coords("Calle Triana, Tomares, Sevilla, Andalucía, España")
get_coords("Calle Betis 54, Sevilla, Andalucía, España")
get_coords("Calle Real, San Fernando, Cadiz, Andalucía, España")
get_coords("Mezquita, Córdoba, Andalucía, España")

Y la salida:

C# 37.374771 -5.98879429509356  ---> Parque de María Luisa, El Prado-Parque de María Luisa, Distrito Sur, Sevilla, Andalucía, España
C# 37.3739359 -6.0062220330977  ---> Parque de los Príncipes, Los Remedios, Sevilla, Andalucía, España
C# 37.3937585 -5.9976877  ---> Catedral, Calle Virgen de los Buenos Libros, San Vicente, Casco Antiguo, Sevilla, Andalucía, 41001, España
C# 37.3772046 -6.0364732  ---> Calle Triana, Sport Aljarafe, Tomares, Sevilla, Andalucía, 41910, España
C# 37.3821089 -5.9988061  ---> 54, Calle Betis, Nucleo Residencial Manuel Arellano, Triana, Sevilla, Andalucía, 41010, España
C# 36.4565316 -6.2079251  ---> Calle Real, San Fernando, Cádiz, Andalucía, 11100, España
C# 37.87943195 -4.77986509433761  ---> Mezquita, El Salvador y La Compañía, Santiago, Distrito Centro, Córdoba, Andalucía, España

Ejemplo 3 – Dirección de una fotografía

Por último, veamos como recuperar el lugar donde fue tomada una fotografía.

Para ello combinamos la función get_address() de esta entrada, con la recuperación de coordenadas desde EXIF:

sfilepath="/media/lubuntu/4A5B-42E5/cmrep/201606/20160621201251_efbbd74f15d4d1b8f3ca081f8af7b7f4.jpg"
exif=get_exif(sfilepath)
datetimeimg = exif["DateTimeOriginal"]
lat,lon=get_decimal_coordinates(exif['GPSInfo'])
saddress=get_address(lat, lon)
print("#######")
print("La fotografía %s fue tomada en %s el %s" % (sfilepath, saddress, datetimeimg))
print("#######")

Salida por Terminal:

#######
La fotografía /media/lubuntu/4A5B-42E5/cmrep/201606/20160621201251_efbbd74f15d4d1b8f3ca081f8af7b7f4.jpg fue tomada en Calle Triana, Sport Aljarafe, Tomares, Sevilla, Andalucía, 41910, España el 2016:06:21 20:12:51
#######

Conclusiones

Con apenas unas lineas y gracias a las comunidades que hacen posible proyectos como OpenStreetMaps, Nominatim o Geopy es posible construir soluciones fácilmente, desde aquí mi agradecimiento y reconocimiento a su labor.

Si alguien tiene dudas, como siempre en comentarios 😉

Saludos y feliz código!

Deja un comentario

Tu dirección de correo electrónico no será publicada.