Menggunakan perpustakaan PROJ.4 untuk mengubah dari koordinat sistem koordinat lokal ke sistem koordinat global menggunakan titik kontrol tanah?

9

Saya memiliki cloud point yang koordinatnya berkaitan dengan sistem koordinat lokal. Saya juga memiliki titik kontrol tanah dengan nilai GPS. Bisakah saya mengonversi koordinat lokal ini ke sistem koordinat global menggunakan PROJ.4 atau perpustakaan lain?

Setiap kode dalam Python untuk masalah yang disebutkan di atas akan sangat membantu.

pengguna18953
sumber
Beberapa kode diharapkan?
huckfinn
Koordinat GPS biasanya WGS84, jadi mereka mungkin sudah mendunia. Jika titik kontrol ground dalam proyeksi lokal, dengan datum berbeda dari GPS (misalnya NAD83), datum harus dikonversi. PROJ4 mendukung pergeseran datum sejauh yang saya tahu.
Oyvind
Ini pertanyaan serupa, tetapi dengan lebih banyak detail: gis.stackexchange.com/questions/357910 .
trusktr

Jawaban:

7

Anda tampaknya ingin melakukan transformasi affine antara sistem koordinat lokal Anda dan sistem koordinat georeferensi.

Affine mentransformasikan secara mendasar semua sistem koordinat dan dapat diwakili oleh persamaan matriks di bawah ini.

|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)

Namun, Anda memiliki masalah dua langkah.

  1. Temukan matriks transformasi dari pasangan koordinat input dan output yang diketahui (titik GPS Anda dan lokasi masing-masing dalam kisi yang ditentukan secara lokal).
  2. Gunakan matriks transformasi ini untuk georeferensi awan titik Anda.

Proj.4 unggul di # 2: mentransfer antara sistem koordinat georeferensi dengan matriks transformasi yang dikenal. Setahu saya tidak bisa digunakan untuk menemukan matriks transformasi dari data titik. Namun, Anda dapat melakukan semuanya dengan mudah dengan menggunakan aljabar linier ringan (inversi matriks kuadrat-terkecil) di Numpy. Saya telah menggunakan versi kelas ini untuk mengurangi data dari beberapa studi lapangan:

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

Ini dapat digunakan sebagai berikut:

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

projected_coordinatessekarang di WGS84, UTM, atau sistem koordinat apa pun yang direkam oleh GPS Anda. Fitur utama dari metode ini adalah dapat digunakan dengan sejumlah titik pengikat (3 atau lebih) dan mendapatkan akurasi semakin banyak titik pengikat digunakan. Anda pada dasarnya menemukan yang paling cocok melalui semua poin dasi Anda.

Daven Quinn
sumber
Halo! Anda menyebutkan bahwa Proj (Proj4) tidak dapat menangani bagian transformasi kustom? Apakah itu berarti secara teknis tidak ada jawaban Proj murni untuk pertanyaan di gis.stackexchange.com/questions/357910 ?
trusktr
0

Saya terjebak dalam masalah yang sama beberapa minggu yang lalu, saya menemukan skrip python yang dapat membantu. Solusi asli dari sini

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)
Garth Cooper
sumber