Utilizzando la libreria PROJ.4 per passare dalle coordinate del sistema di coordinate locali al sistema di coordinate globale usando i punti di controllo a terra?


9

Ho una nuvola di punti le cui coordinate sono rispetto ad un sistema di coordinate locale. Ho anche punti di controllo a terra con valori GPS. Posso convertire queste coordinate locali in un sistema di coordinate globale usando PROJ.4 o qualsiasi altra libreria?

Qualsiasi codice in Python per il problema sopra indicato sarebbe di grande aiuto.


Qualche codice previsto?
huckfinn,

Le coordinate GPS sono normalmente WGS84, quindi probabilmente sono già globali. Se i punti di controllo a terra si trovano in una proiezione locale, con un dato diverso rispetto al GPS (ad esempio NAD83), il dato deve essere convertito. PROJ4 supporta i turni di riferimento per quanto ne so.
Oyvind

Ecco una domanda simile, ma con molti più dettagli: gis.stackexchange.com/questions/357910 .
trusktr,

Risposte:


7

Sembra che tu stia cercando di condurre una trasformazione affine tra il tuo sistema di coordinate locale e un sistema di coordinate georeferenziato.

Affine trasforma sottilmente tutti i sistemi di coordinate e può essere rappresentato dall'equazione della matrice in basso.

|x_1 y_1 1| |a d|   |x'_1 y'_1|
|x_2 y_2 1| |b e| = |x'_2 y'_2|
|x_3 y_3 1| |c f|   |x'_3 y'_3|
input     transform.  output
coords    matrix      coords
(n x 3)   (3 x 2)     (n x 2)

Tuttavia, hai un problema in due passaggi.

  1. Trova la matrice di trasformazione da accoppiamenti noti di coordinate di input e output (i tuoi punti GPS e le rispettive posizioni nella griglia definita localmente).
  2. Usa questa matrice di trasformazione per georeferenziare la tua nuvola di punti.

Proj.4 eccelle al n. 2: trasferimento tra sistemi di coordinate georeferenziate con matrici di trasformazione note. Per quanto ne so, non può essere utilizzato per trovare una matrice di trasformazione dai dati dei punti. Tuttavia, puoi fare tutto facilmente usando una leggera algebra lineare (inversione di matrice dei minimi quadrati) in Numpy. Ho usato una versione di questa classe per ridurre i dati di numerosi studi sul campo:

import numpy as N 

def augment(a):
    """Add a final column of ones to input data"""
    arr = N.ones((a.shape[0],a.shape[1]+1))
    arr[:,:-1] = a
    return arr

class Affine(object):
    def __init__(self, array=None):
        self.trans_matrix = array

    def transform(self, points):
        """Transform locally projected data using transformation matrix"""
        return N.dot(augment(N.array(points)), self.trans_matrix)

    @classmethod
    def from_tiepoints(cls, fromCoords, toCoords):
        "Produce affine transform by ingesting local and georeferenced coordinates for tie points"""
        fromCoords = augment(N.array(fromCoords))
        toCoords = N.array(toCoords)
        trans_matrix, residuals, rank, sv = N.linalg.lstsq(fromCoords, toCoords)

        affine =  cls(trans_matrix) # Setup affine transform from transformation matrix
        sol = N.dot(fromCoords,affine.trans_matrix) # Compute model solution
        print "Pixel errors:"
        print (toCoords - sol)
        return affine

Può essere usato come tale:

transform = Affine.from_tiepoints(gps_points_local,gps_points_geo)
projected_data = transform.transform(local_point_cloud)

projected_coordinatesè ora in WGS84, UTM o in qualsiasi sistema di coordinate registrato dal GPS. Una delle principali caratteristiche di questo metodo è che può essere utilizzato con un numero qualsiasi di punti di pareggio (3 o più) e guadagna precisione più vengono utilizzati i punti di pareggio. In sostanza, stai trovando la soluzione migliore per tutti i tuoi punti di pareggio.


Ciao! Hai detto che Proj (Proj4) non è in grado di gestire la parte di trasformazione personalizzata? Ciò significa che tecnicamente non esiste una risposta Proj pura per la domanda su gis.stackexchange.com/questions/357910 ?
trusktr,



0

Ero bloccato nello stesso problema qualche settimana fa, ho capito uno script in pitone che può aiutare. Soluzione originale da qui

import pyproj
import math
import numpy as np
from statistics import mean
import scipy.optimize as optimize

#This function converts the numbers into text
def text_2_CRS(params):
    # print(params)  # <-- you'll see that params is a NumPy array
    x_0, y_0, gamma, alpha, lat_0, lonc = params # <-- for readability you may wish to assign names to the component variables
    pm = '+proj=omerc +lat_0='+ str(lat_0) +' +lonc='+ str(lonc) +' +alpha=' + str(alpha) + ' +gamma=' + str(
        gamma) + ' +k=0.999585495 +x_0=' + str(x_0) + ' +y_0=' + str(y_0) + ' +ellps=GRS80 +units=m +no_defs'
    return pm

#Optimisation function
def convert(params):
    pm = text_2_CRS(params)
    trans_points = []
    #Put your control points in mine grid coordinates here
    points_local = [[5663.648, 7386.58],
                    [20265.326, 493.126],
                    [1000, -10000],
                    [-1000, -10000],
                    [1331.817, 2390.206],
                    [5794, -1033.6],
                    ]
    # Put your control points here mga here
    points_mga = [[567416.145863305, 7434410.3451835],
                  [579090.883705669, 7423265.25196681],
                  [557507.390559793, 7419390.6658927],
                  [555610.407664593, 7420021.64968145],
                  [561731.125709093, 7431037.98474379],
                  [564883.285081307, 7426382.75146683],
                  ]
    for i in range(len(points_local)):
        #note that EPSG:28350 is MGA94 Zone 50
        trans = pyproj.transform(pyproj.Proj(pm), pyproj.Proj("EPSG:28350"), points_local[i][0], points_local[i][1])
        trans_points.append(trans)
    error = []
    #this finds the difference between the control points
    for i in range(len(points_mga)):
        x1 = trans_points[i][0]
        y1 = trans_points[i][1]
        x2 = points_mga[i][0]
        y2 = points_mga[i][1]
        error.append(math.sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2))

    print("Current Params are: ")
    with np.printoptions(precision=3, suppress=True):
        print(params)
    print("Current average error is: " + str(mean(error)) + " meters")
    print("String to use is: " + pm)
    print('')

    return mean(error)


#Add your inital guess
x_0 = 950
y_0 = -1200
gamma = -18.39841101
alpha=-0
lat_0 = -23.2583926082939
lonc = 117.589084840039


#define your control points
points_local = [[5663.648,7386.58],
          [20265.326,493.126],
          [1000,-10000],
          [-1000,-10000],
          [1331.817,2390.206],
          [5794,-1033.6],
          ]

points_mga = [[567416.145863305,7434410.3451835],
          [579090.883705669,7423265.25196681],
          [557507.390559793,7419390.6658927],
          [555610.407664593,7420021.64968145],
          [561731.125709093,7431037.98474379],
          [564883.285081307,7426382.75146683],
          ]


params = [x_0, y_0, gamma,alpha, lat_0, lonc]

error = convert(params)

print(error)

result = optimize.minimize(convert, params, method='Powell')
if result.success:
    fitted_params = result.x
    print(fitted_params)
else:
    raise ValueError(result.message)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.