如何从 Google Maps Static API 图像上的 x,y 像素计算出纬度和经度

问题描述 投票:0回答:1

我正在开发一个函数,该函数给出以下参数并返回纬度和经度。该图像来自谷歌地图静态 api。谷歌地图使用墨卡托投影。我试图弄清楚如何从图像上的 x,y 像素准确获取纬度和经度。我进行了多种形式的计算,它们似乎略有偏差。

:param x, y: Pixel coordinates.
:param zoom: Zoom level of the image.
:param scale: Scale factor of the image.
:param image_center_lat_lon: Tuple of latitude and longitude at the image center.
:param image_size: Size of the image in pixels.

以下是我使用过的两个函数示例,结果接近但不准确

def pixel_to_lat_lon(x, y, zoom, scale, image_center_lat_lon, image_size):

    C = 640 * scale * (2 ** zoom)  # Total number of pixels in the map's width or height
    lat_center, lon_center = image_center_lat_lon
    image_size_scaled = (image_size[0] * scale, image_size[1] * scale)

    # Calculate pixel coordinates of the center of the image
    center_x = (lon_center + 180) / 360 * C
    center_y = (1 - math.log(math.tan(math.radians(lat_center)) + 1 / math.cos(math.radians(lat_center))) / math.pi) / 2 * C

    # Calculate the latitude and longitude from the pixel coordinates
    pixel_x = center_x - image_size_scaled[0] / 2 + x
    pixel_y = center_y - image_size_scaled[1] / 2 + y

    lon = pixel_x / C * 360 - 180
    lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * pixel_y / C)))
    lat = math.degrees(lat_rad)

    return lat, lon

示例2:

def project(lat_lng, zoom, scale, tile_size):
    """Project latitude, longitude to world coordinates."""
    lat, lng = lat_lng
    siny = math.sin(lat * math.pi / 180.0)
    siny = min(max(siny, -0.9999), 0.9999)
    x = tile_size * (0.5 + lng / 360.0) * scale * (2 ** zoom)
    y = tile_size * (0.5 - math.log((1 + siny) / (1 - siny)) / (4 * math.pi)) * scale * (2 ** zoom)
    return x, y

def unproject(world_coordinate, zoom, scale, tile_size):
    """Unproject world coordinates to latitude, longitude."""
    x, y = world_coordinate
    lng = (x / (tile_size * scale * (2 ** zoom)) - 0.5) * 360.0
    n = math.pi - 2.0 * math.pi * y / (tile_size * scale * (2 ** zoom))
    lat = (180.0 / math.pi) * math.atan(0.5 * (math.exp(n) - math.exp(-n)))
    return lat, lng

def pixel_to_lat_lon(x, y, zoom, scale, image_center_lat_lon, image_size):
    tile_size = 640  
    center_x, center_y = project(image_center_lat_lon, zoom, scale, tile_size)
    
    # Calculate the center pixel of the image
    image_center_x = image_size[0] / 2
    image_center_y = image_size[1] / 2

    # Adjust x and y to be absolute pixel coordinates on the map
    abs_x = center_x + (x - image_center_x)
    abs_y = center_y + (y - image_center_y)
    
    # Convert absolute pixel coordinates back to latitude and longitude
    return unproject((abs_x, abs_y), zoom, scale, tile_size)

以下是谷歌地图 API 图像支持文档的一些参考链接:

地图和图块坐标

Google Maps 静态 API 参数用法,有助于理解缩放和缩放

测试案例1:

{
  "latitude": 25.64208985300285,
  "longitude": -80.37262545716628,
  "zoom": 18,
  "scale": 2,
  "size": 640,
  "pixelX": 767.4027099609375,
  "pixelY": 700.3953857421875
}

测试案例2:

{
  "latitude": 25.63934327097157,
  "longitude": -80.35101258254728,
  "zoom": 18,
  "scale": 2,
  "size": 640,
  "pixelX": 247.67588806152344,
  "pixelY": 239.9282989501953
}

测试用例的结果是粗略的估计。但根据Google Maps UI应该反映泳池的中心,纬度和经度应该大致在:

测试用例1:25.641942181931114,-80.37228858417026

测试用例2:25.640310082174018,-80.3520713140406

python python-3.x google-maps google-maps-api-3 gis
1个回答
0
投票

使用 pyproj 库和 Transformer 解决了在 WGS84 和 Google Maps Mercator 之间移动的问题

google_maps_proj = Proj('epsg:3857')
wgs84 = Proj('epsg:4326')

transformer = Transformer.from_proj(wgs84, google_maps_proj, always_xy=True)
© www.soinside.com 2019 - 2024. All rights reserved.