Converting lat/lon coordinates to x/y?

For machine learning I need to convert array of coordinates in lon/lat format to simple floats where x=0,y=0 will be a most south/west coordinate and x=1,y=1 most north/east, and x=0.5,y=0.5 will be coordinate in a center.

What is a way to do this?

• Welcome to gis.stackexchange! Please note that a good question on this site is expected to show some degree of research on your part, i.e. what you have tried and - if applicable - code so far. For more info, you can check our faq. – underdark Oct 4 '16 at 17:13

Update

If utm coordinates are suitable for your purposes, then note that in lieu of pyproj, the utm package is now available and is simpler to use. Just be aware of lng, lat ordering vs. easting, northing ordering for the respective from_latlon and to_latlon functions, per the docs.

The below conversion example would become:

import utm
x, y = utm.from_latlon(input_lat, input_lon)

Original

Use pyproj for converting your lng, lat pairs to a projected coordinate system. In other words you need to convert from your geographic coordinate system (most likely EPSG code 4326) to a local projected coordinate system, e.g. a local UTM zone or regional system such as the British National Grid (EPSG code 27700).

import pyproj as proj

# setup your projections
crs_wgs = proj.Proj(init='epsg:4326') # assuming you're using WGS84 geographic
crs_bng = proj.Proj(init='epsg:27700') # use a locally appropriate projected CRS

# then cast your geographic coordinate pair to the projected system
x, y = proj.transform(crs_wgs, crs_bng, input_lon, input_lat)

Note that pyproj.transform() also works on numpy arrays, so you can therefore transform your lon, lat arrays to x, y arrays. You can then use numpy's built-in array methods to normalise your values.

For example:

import numpy as np
x = (x - x.min()) / (x.max() - x.min())
y = (y - y.min()) / (y.max() - y.min())

However, if you are using sklearn already, then you may as well use sklearn.preprocessing.normalize.

It depends on what metric you need to preserve. One obvious approach is to project it to some appropriate flat coordinate system. To do this, you can use the pyproj library. Then, simply rescale your coordinates to be in the range [0, 1]. However, this doesn't perfectly preserve spatial relationships because longitude and latitude are on a sphere (or an ellipsoid or geoid), and x,y coordinates are on a flat surface. You should read about different map projections to see what you may be losing. A good reference is Map Projections: A Working Manual. If your positions only cover a small patch of the Earth, the errors may be acceptable to you.

A second approach is to convert the longitude and latitude to (x, y, z) coordinates in 3d space. If you approximate the earth's surface as a sphere, then the formulae should be

x = sin(pi/2-lat) * cos(lon)
y = sin(pi/2-lat) * sin(lon)
z = cos(pi/2-lat)

where lon and lat are in radians. In this case however, z=-1 is the south pole, z=1 is the north pole, x=1 and x=-1 are the prime meridian, and the dateline, and y=1 and y=-1 are 90 degrees East and 90 degrees West. Again, you can rescale so that coordinates are [0,1] rather than [-1,1].

just use gdal.ApplyGeoTransform adn gdal.InvGeoTransform.Here's the python code:

src = gdal.Open(filename)
#if the file contains GeoTransform
geotrans = src.GetGeoTransform()
#if the file contains only GCPs
gcps = src.GetGCPs()
geotrans = gdal.GCPsToGeoTransform(gcps)

#from pixel coordinate to lat/lon
lat, lon = gdal.ApplyGeoTransform(geoTrans, x,y)

# from lat/lon to pixel coordinate
invTs = gdal.InvGeoTransform(ts)
x, y = gdal.ApplyGeoTransform(invTs, lat, lon)