Python+ENVI:遥感影像投影转换全攻略,解放双手的懒人必备技巧

遥感影像处理中,投影转换是一项常见步骤。ENVI能处理这类任务,但Python的功能更为出色,它能批量完成投影转换,大大减轻了我们的工作量。那么,Python是如何实现这一功能的?咱们来探究一下。

查看影像信息

查看影像资料看似简单,实则关键。在ENVI中,某些数据能明确显示地理坐标,但GDAL却无法识别,这可能导致投影转换直接失败。因此,最好事先确认GDAL能否读取投影信息。以前,我处理一批影像时,未先查看信息,导致转换时出现问题,浪费了大量时间。

在检查过程中,ds_geo和ds_prj这两个输出结果需特别关注。仿射地理变换的参数和投影坐标系的设定同样关键。这就像盖房子,如果基础参数设置错误,后续工程将难以顺利进行。投影转换亦是如此。

转换函数

这次操作使用了GDAL库中的Warp函数,这个函数大家应该不陌生,之前进行裁剪时也用它来过。这个函数功能强大,很多文章都有对其功能的介绍。我在之前的【Python&RS】GDAL批量裁剪遥感影像/栅格数据文章中,详细解释了这个函数的使用方法。有兴趣的朋友可以查阅一下,觉得有帮助的话,请给我点个赞。

def Get_data(filepath):
    ds = gdal.Open(filepath)  # 打开数据集dataset
    ds_width = ds.RasterXSize  # 获取数据宽度
    ds_height = ds.RasterYSize  # 获取数据高度
    ds_bands = ds.RasterCount  # 获取波段数
    ds_geo = ds.GetGeoTransform()  # 获取仿射地理变换参数
    ds_prj = ds.GetProjection()  # 获取投影信息
    print("影像的宽度为:" + str(ds_width))
    print("影像的高度为:" + str(ds_height))
    print("仿射地理变换参数为:" + str(ds_geo))
    print("投影坐标系为:" + str(ds_prj))
    return ds_geo
    # data = ds.ReadAsArray(0, 0, ds_width, ds_height)  # 以数组的形式读取整个数据集

在Warp函数中,dstSRS参数指的是目标投影坐标系统,我们使用EPSG编码来标识,比如32651代表的是UTM/WGS84 51N投影坐标系。若要了解其他坐标系的编码,可以查阅【Python&GIS】中关于如何通过经纬度生成矢量点文件的资料。熟练掌握这些编码及函数操作,投影转换将变得简单易行。

回调函数(没啥用)

前文已经提及了回调函数的相关内容,它主要承担两个职能。首先,它能够起到增加文字量的作用,当然这只是一个玩笑的说法;其次,它有助于记录操作进程。在进行代码投影转换时,若只是静静等待,确实会感到无聊。而引入回调函数后,我们便能够实时查看转换的进度,从而减轻了等待的枯燥感。以前没有使用回调函数时,代码毫无反应,让人误以为出现了错误。但自从添加了回调函数,我们便对整个过程有了更清晰的把握。

尽管对投影转换的结果影响不大,但它的存在让人感到安心,仿佛每一步都有明确的路径。这就像在长跑中,清楚自己已经跑了多远,以及距离终点还有多远,这样的认知让人更有毅力继续前进。

完整代码

def Projection_Transform(path_input1, path_output1):
    """
    :param path_input1: 待转换的数据路径
    :param path_output1: 转换后的数据路径
    :return: None
    """
    ds_input = gdal.Open(path_input1, gdal.GA_ReadOnly)  # 打开数据集dataset
    ds = gdal.Warp(path_output1, ds_input, dstSRS="EPSG:32651", resampleAlg='cubic', callback=Show_Progress)
    # 输出路径、输入影像、目标投影、重采样方法(最邻近内插双线性内插三次卷积等)、回调函数
    ds.BuildOverviews(overviewlist=[2, 4, 8, 16])
    # 创建金字塔
    ds = None

无论是借助ENVI或ArcGIS等软件进行坐标投影的转换,还是采用Python的相关库,本质上都是通过预设的参数来实现的。这类方法通常适用于一些常见的坐标系转换。但要达到最高精度,还是得使用四参数或七参数转换。当然,有时这些方法可能无法成功,但也不必过分烦恼,毕竟过分追求未必有所得。

学习Python或RS时,若遇到难题,可直接留言询问。若对批量处理有兴趣,不妨告诉我,我会把相关代码拿出来供大家共同学习。大家多在实践中探索,时间久了,自然能熟练运用其中的方法。

过往经验分享

以前我提到过矢量数据的投影转换技术。现在有了矢量数据与栅格数据的投影转换方法,这不就是一套完整的工具了吗?记得之前帮朋友处理了一大批矢量数据,我用Python完成了投影转换,他夸我效率很高。掌握了这些技巧,无论是工作还是学习,都能节省很多时间和精力。

def Show_Progress(percent, msg, tag):
    """
    :param percent: 进度,0~1
    :param msg:
    :param tag:
    :return:
    """
    print("开始进程......")
    if 25 <= percent*100 <= 26:
        print("进度:" + "%.2f" % (percent*100) + "%")
    if 50 <= percent*100 <= 51:
        print("进度:" + "%.2f" % (percent*100) + "%")
    if 75 <= percent*100 <= 76:
        print("进度:" + "%.2f" % (percent*100) + "%")

将矢量与栅格数据相结合,在应用中效果显著。例如,在进行地理信息分析时,这两种数据类型都会用到。掌握这两种处理方式,操作起来会更加得心应手。希望各位能多加实践,体会其中的便捷。

# -*- coding: utf-8 -*-
"""
@Time : 2023/6/26 17:03
@Auth : RS迷途小书童
@File :Raster Data Projection Transform.py
@IDE :PyCharm
@Purpose :栅格数据投影/坐标转换
"""
from osgeo import gdal
def Get_data(filepath):
    ds = gdal.Open(filepath)  # 打开数据集dataset
    ds_width = ds.RasterXSize  # 获取数据宽度
    ds_height = ds.RasterYSize  # 获取数据高度
    ds_bands = ds.RasterCount  # 获取波段数
    ds_geo = ds.GetGeoTransform()  # 获取仿射地理变换参数
    ds_prj = ds.GetProjection()  # 获取投影信息
    print("影像的宽度为:" + str(ds_width))
    print("影像的高度为:" + str(ds_height))
    print("仿射地理变换参数为:" + str(ds_geo))
    print("投影坐标系为:" + str(ds_prj))
    return ds_geo
    # data = ds.ReadAsArray(0, 0, ds_width, ds_height)  # 以数组的形式读取整个数据集
def Show_Progress(percent, msg, tag):
    """
    :param percent: 进度,0~1
    :param msg:
    :param tag:
    :return:
    """
    print("开始进程......")
    if 25 <= percent*100 <= 26:
        print("进度:" + "%.2f" % (percent*100) + "%")
    if 50 <= percent*100 <= 51:
        print("进度:" + "%.2f" % (percent*100) + "%")
    if 75 <= percent*100 <= 76:
        print("进度:" + "%.2f" % (percent*100) + "%")
def Projection_Transform(path_input1, path_output1):
    """
    :param path_input1: 待转换的数据路径
    :param path_output1: 转换后的数据路径
    :return: None
    """
    ds_input = gdal.Open(path_input1, gdal.GA_ReadOnly)  # 打开数据集dataset
    ds = gdal.Warp(path_output1, ds_input, dstSRS="EPSG:32651", resampleAlg='cubic', callback=Show_Progress)
    # 输出路径、输入影像、目标投影、重采样方法(最邻近内插双线性内插三次卷积等)、回调函数
    ds.BuildOverviews(overviewlist=[2, 4, 8, 16])
    # 创建金字塔
    ds = None
if __name__ == "__main__":
    path_input = "B:/sharpening2_proj"
    path_output = r"B:/sharpening1.tif"
    Get_data(path_input)
    Projection_Transform(path_input, path_output)

学习建议

学习Python处理遥感图像投影转换时,需多加练习和探索。可从基础的图像开始,逐步掌握查阅数据、运用转换工具等操作。遇到难题不要急躁,将错误信息记录下来,上网搜索或与同行交流,多数问题都能找到解决之道。

平日里应多浏览相关资料和文章,比如我之前撰写过的,通过学习别人的经验,我们也能更快地提升自己。通过实践中的不断总结,逐步积累,相信大家最终都能熟练地运用Python进行遥感影像的投影转换。大家是否有意尝试使用Python进行投影转换?若觉得这篇文章有所帮助,请不要忘记点赞和转发!

发表评论