You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何用Python+GDAL将GeoTIFF经纬度坐标转换为像素坐标

经纬度转GeoTIFF像素坐标的Python实现方案

咱们先解决你遇到的两个核心问题:一是osr库调用时的参数错误,二是subprocess调用gdaltransform的执行问题。

方法一:基于GDAL原生API的稳定实现(推荐)

你之前用osr的代码出错,主要是三个原因:投影信息导入方式不对、坐标顺序搞反了,以及对TransformPoint的参数理解有误。下面是修正后的完整代码,用GDAL的Dataset直接读取图像的地理信息,更可靠:

from osgeo import gdal, osr
import numpy as np

# 让GDAL抛出异常,方便排查错误
gdal.UseExceptions()

def convert_latlon_to_pixel(lat, lon, tiff_file_path):
    # 打开GeoTIFF文件
    dataset = gdal.Open(tiff_file_path)
    if not dataset:
        raise FileNotFoundError(f"找不到或无法打开文件:{tiff_file_path}")
    
    # 获取图像的原生投影和目标经纬度投影(EPSG:4326)
    image_proj = osr.SpatialReference(wkt=dataset.GetProjection())
    wgs84_proj = osr.SpatialReference()
    wgs84_proj.ImportFromEPSG(4326)
    
    # 创建坐标转换器:从WGS84经纬度转换到图像的原生投影坐标
    coord_transformer = osr.CoordinateTransformation(wgs84_proj, image_proj)
    
    # 重点:EPSG:4326的坐标顺序是「经度在前,纬度在后」,别搞反!
    # TransformPoint返回 (投影X, 投影Y, 高程),高程我们可以忽略
    proj_x, proj_y, _ = coord_transformer.TransformPoint(lon, lat)
    
    # 获取图像的地理变换参数:(左上角X, 像素宽度, 旋转参数, 左上角Y, 旋转参数, 像素高度)
    geo_transform = dataset.GetGeoTransform()
    
    # 用地理变换公式计算像素坐标
    pixel_x = (proj_x - geo_transform[0]) / geo_transform[1]
    pixel_y = (proj_y - geo_transform[3]) / geo_transform[5]
    
    # 如果需要整数像素坐标,直接四舍五入即可
    return int(np.round(pixel_x)), int(np.round(pixel_y))

# 调用示例
tiff_path = "/path/imagename.tiff"
target_lat = -17.4380493164062
target_lon = 14.6951949085676
px, py = convert_latlon_to_pixel(target_lat, target_lon, tiff_path)
print(f"对应的像素坐标:({px}, {py})")

对你原osr代码的错误解析:

  1. source.ImportFromUrl(path + TIFFFilename)ImportFromUrl是用来从网络URL加载投影信息的,不是本地文件,应该从Dataset的GetProjection()获取图像的投影。
  2. 坐标顺序错误:你传入的是(lat, lon),但EPSG:4326要求的是(lon, lat),这会导致转换结果完全错误。
  3. 虽然TransformPoint的参数格式没问题,但前面的投影导入错误已经导致整个转换器失效,所以才抛出NotImplementedError。

方法二:修复subprocess调用gdaltransform的问题

你之前的subprocess调用有两个关键错误:参数格式不对,以及没有正确读取输出结果。下面是修正后的代码:

import subprocess
import numpy as np

def convert_via_gdaltransform(lat, lon, tiff_file_path):
    # 构建gdaltransform命令参数,注意顺序:先经度,后纬度
    cmd_args = [
        'gdaltransform',
        '-i',
        '-t_srs', 'epsg:4326',
        tiff_file_path,
        str(lon), str(lat)
    ]
    
    # 执行命令并捕获输出
    result = subprocess.run(
        cmd_args,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        text=True,
        check=True  # 如果命令执行失败,直接抛出异常
    )
    
    # 解析输出结果(gdaltransform会输出一行像素坐标)
    px_str, py_str = result.stdout.strip().split()
    return int(np.round(float(px_str))), int(np.round(float(py_str)))

# 调用示例
tiff_path = "/path/imagename.tiff"
target_lat = -17.4380493164062
target_lon = 14.6951949085676
px, py = convert_via_gdaltransform(target_lat, target_lon, tiff_path)
print(f"对应的像素坐标:({px}, {py})")

对你原subprocess代码的错误解析:

  1. TRY1中' -t_srs'前面多了空格,导致gdaltransform无法识别这个参数,应该写成'-t_srs',同时路径后面不要加\n
  2. TRY2中用shell=True但没有读取输出,也没有等待命令执行完成,用subprocess.run()并指定check=True可以自动处理错误,同时捕获stdout获取结果。

总结

推荐使用第一种方法,因为它不需要调用外部命令,代码更易维护,也更容易处理异常情况;第二种方法适合你已经熟悉gdaltransform命令的场景,但要注意参数顺序和格式。

内容的提问来源于stack exchange,提问作者drheinrich940

火山引擎 最新活动