Використовуючи бібліотеку PROJ.4 для перетворення з локальних координат системи в глобальну систему координат за допомогою наземних точок управління?


9

У мене є хмара точок, координати якої відносно локальної системи координат. У мене також є точки наземного управління зі значеннями GPS. Чи можу я перетворити ці локальні координати в глобальну систему координат за допомогою PROJ.4 або будь-якої іншої бібліотеки?

Будь-який код у Python для вищезазначеної проблеми був би чудовою допомогою.


Якийсь код очікували?
huckfinn

Координати GPS зазвичай WGS84, тому вони, ймовірно, вже глобальні. Якщо точки наземного контролю знаходяться в локальній проекції, мають іншу дату, ніж GPS (наприклад, NAD83), то дату необхідно перетворити. Наскільки я знаю, PROJ4 підтримує зміну даних.
Ойвінд

Ось подібне питання, але з набагато детальнішою інформацією: gis.stackexchange.com/questions/357910 .
trusktr

Відповіді:


7

Ви, здається, хочете провести афінну трансформацію між вашою локальною системою координат і геореференційованою системою координат.

Аффіні перетворюються в основі всіх систем координат і можуть бути представлені матричним рівнянням нижче.

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

Однак у вас є проблема в два кроки.

  1. Знайдіть матрицю перетворення з відомих пар координат вводу та виводу (ваші GPS-точки та їх місцеположення у вашій локально визначеній сітці).
  2. Використовуйте цю матрицю перетворення для геореференції хмари точок.

Proj.4 перевершує # 2: передача між геореференційними системами координат з відомими матрицями перетворення. Він не може до мого знання можна використовувати для пошуку матриці перетворення з даних точок. Однак ви можете зробити все це легко, використовуючи деяку легку лінійну алгебру (інверсія матриці найменших квадратів) в Numpy. Я використовував версію цього класу для зменшення даних з декількох польових досліджень:

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

Його можна використовувати як таке:

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

projected_coordinatesтепер знаходиться в WGS84, UTM або будь-якій іншій системі координат, записаній вашим GPS. Головною особливістю цього методу є те, що він може використовуватися з будь-якою кількістю крапок (3 і більше) та набирає точності, чим більше точок зв'язати. Ви, по суті, знаходите найкраще поєднання за всіма своїми балами.


Привіт! Ви згадуєте, що Proj (Proj4) не може обробляти користувацьку частину перетворення? Чи означає це, що технічно не є чистою відповіддю на питання на gis.stackexchange.com/questions/357910 ?
trusktr


0

Завжди простіше визначити локальну систему координат, як ми це зробили тут:

Стереографічна проекція еліпсоїда WGS84 на площину [пітон]

GDAL тепер може трансформувати векторні дані, використовуючи точки GCP.


Привіт! Я новачок у цьому матеріалі. Чи є "стереографічна" проекція насправді те, що мені потрібно використати для мого запитання на сайті gis.stackexchange.com/questions/357910 ?
trusktr

0

Я застряг у тій же проблемі кілька тижнів тому, я зрозумів сценарій пітона, який може допомогти. Оригінальне рішення звідси

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)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.