Sử dụng thư viện PROJ.4 để chuyển đổi từ tọa độ hệ tọa độ cục bộ sang hệ tọa độ toàn cầu bằng các điểm điều khiển mặt đất?


9

Tôi có một đám mây điểm có tọa độ đối với hệ tọa độ cục bộ. Tôi cũng có các điểm kiểm soát mặt đất với các giá trị GPS. Tôi có thể chuyển đổi các tọa độ cục bộ này sang hệ tọa độ toàn cầu bằng PROJ.4 hoặc bất kỳ thư viện nào khác không?

Bất kỳ mã nào trong Python cho vấn đề đã nêu ở trên sẽ là một trợ giúp tuyệt vời.


Một số mã dự kiến?
huckfinn

Các tọa độ GPS thường là WGS84, vì vậy chúng có thể là toàn cầu. Nếu các điểm điều khiển mặt đất nằm trong một phép chiếu cục bộ, với mốc thời gian khác với GPS (ví dụ NAD83), thì mốc này phải được chuyển đổi. PROJ4 hỗ trợ dịch chuyển dữ liệu theo như tôi biết.
Oyvind

Đây là một câu hỏi tương tự, nhưng với nhiều chi tiết hơn: gis.stackexchange.com/questions/357910 .
trusktr

Câu trả lời:


7

Bạn dường như đang tìm cách tiến hành một phép biến đổi affine giữa hệ tọa độ cục bộ của bạn và hệ tọa độ tham chiếu địa lý.

Biến đổi affine dưới tất cả các hệ tọa độ và có thể được biểu diễn bằng phương trình ma trận dưới đây.

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

Tuy nhiên, bạn có một vấn đề hai bước.

  1. Tìm ma trận biến đổi từ các cặp tọa độ đầu vào và đầu ra đã biết (các điểm GPS của bạn và các vị trí tương ứng của chúng trong lưới được xác định cục bộ của bạn).
  2. Sử dụng ma trận biến đổi này để định vị đám mây điểm của bạn.

Proj.4 vượt trội ở # 2: chuyển giữa các hệ tọa độ tham chiếu địa lý với ma trận biến đổi đã biết. Kiến thức của tôi không thể được sử dụng để tìm ma trận biến đổi từ dữ liệu điểm. Tuy nhiên, bạn có thể thực hiện toàn bộ mọi thứ một cách dễ dàng bằng cách sử dụng một số đại số tuyến tính nhẹ (đảo ngược ma trận bình phương nhỏ nhất) trong Numpy. Tôi đã sử dụng một phiên bản của lớp này để giảm dữ liệu từ một số nghiên cứu thực địa:

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

Nó có thể được sử dụng như vậy:

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

projected_coordinateshiện có trong WGS84, UTM hoặc bất kỳ hệ tọa độ nào được GPS ghi lại. Một tính năng chính của phương pháp này là nó có thể được sử dụng với bất kỳ số điểm liên kết nào (3 hoặc nhiều hơn) và đạt được độ chính xác khi sử dụng nhiều điểm liên kết hơn. Về cơ bản, bạn đang tìm kiếm sự phù hợp nhất thông qua tất cả các điểm ràng buộc của bạn.


Xin chào! Bạn đề cập rằng Proj (Proj4) không thể xử lý phần biến đổi tùy chỉnh? Điều đó có nghĩa là về mặt kỹ thuật không phải là một câu trả lời Proj thuần túy cho câu hỏi tại gis.stackexchange.com/questions3537910 ?
trusktr


0

Việc xác định hệ tọa độ cục bộ luôn dễ dàng hơn, như chúng tôi đã làm ở đây:

Phép chiếu lập thể của ellipsoid WGS84 trên mặt phẳng [python]

GDAL hiện có thể chuyển đổi dữ liệu vectơ bằng các điểm GCP.


Xin chào! Tôi mới đến những thứ này. Đây có phải là một phép chiếu "Stereographic" trong thực tế những gì tôi cần sử dụng cho câu hỏi của mình tại gis.stackexchange.com/questions3537910 không?
trusktr

0

Tôi đã bị mắc kẹt trong cùng một vấn đề vài tuần trước, tôi đã tìm ra một kịch bản python có thể giúp đỡ. Giải pháp gốc từ đây

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)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.