Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >栅格数据投影转换

栅格数据投影转换

作者头像
卡尔曼和玻尔兹曼谁曼
发布于 2019-01-22 01:43:03
发布于 2019-01-22 01:43:03
1.8K00
代码可运行
举报
运行总次数:0
代码可运行

使用GDAL提供的命令行工具进行转换

GDAL提供了gdalwarp命令可以方便地让我们进行影像拼接,重投影,裁剪,格式转换等功能

比如,我们需要将MODIS数据的Sinusoidal投影转为UTM投影,我们可以这样操作。

我需要转换的地区位于UTM的49度带内,我查看了一下其EPSG的编码为:EPSG:32649(WGS 84 / UTM zone 49N)

注:推荐大家一个网站,可以查阅各种投影的定义:http://spatialreference.org

然后,终端中执行如下命令:

gdalinfo MOD09A1.A2017361.h28v06.006.2018005034659.hdf (用于查看MODIS数据中的波段名称与地址,这里我们只转换第一波段)

gdalwarp -t_srs EPSG:32649 HDF4_EOS:EOS_GRID:"MOD09A1.A2017361.h28v06.006.2018005034659.hdf":MOD_Grid_500m_Surface_Reflectance:sur_refl_b01 MODSI_WARP_32649.tif-t_srs参数用于指定输出投影信息,可以是EPSG,或者OGC WKT,或者PROJ4格式,后面分别是输入数据和输出数据文件名)

使用代码进行转换

使用命令行转换,当然有两种方法啦:

第一,直接在代码中调用命令行工具的接口(比较懒的人,像我,当然直接用第一种啦,有现成的工具为什么不用);

第二,自己做投影转换之后的坐标计算,主要是计算重投影之后的GeoTransform参数,有了GeoTransform参数以及投影的定义,我们就可以通过SetGeoTransform()SetProjection()投影转换了.

下面我给出具体的实现代码:

第一种方法直接调用gdal.Warp()方法,该方法其实就是对gdalwarp命令的封装,第一个参数是输出文件,第二个参数是输入文件或者输入的Dataset,后面的都是可选参数(dstSRS参数指定输出投影)

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from osgeo import gdal

root_ds = gdal.Open('MOD09A1.A2017361.h28v06.006.2018005034659.hdf')
# 返回结果是一个list,list中的每个元素是一个tuple,每个tuple中包含了对数据集的路径,元数据等的描述信息
# tuple中的第一个元素描述的是数据子集的全路径
ds_list = root_ds.GetSubDatasets()

# 取出第1个数据子集(MODIS反射率产品的第一个波段)进行转换
# 第一个参数是输出数据,第二个参数是输入数据,后面可以跟多个可选项
gdal.Warp('reprojection.tif', ds_list[0][0], dstSRS='EPSG:32649')

# 关闭数据集
root_ds = None

在介绍第二种方法之前,我们有必要回忆一下之前说过的GDAL反射变换的六参数模型:

放射变换使用如下的公式表示栅格图上坐标和地理坐标的关系:

Xgeo=GT(0)+Xpixel∗GT(1)+Yline∗GT(2)Ygeo=GT(3)+Xpixel∗GT(4)+Yline∗GT(5)Xgeo=GT(0)+Xpixel∗GT(1)+Yline∗GT(2)Ygeo=GT(3)+Xpixel∗GT(4)+Yline∗GT(5)

\begin{matrix} X_{geo} = GT(0) + X_{pixel} * GT(1) + Y_{line} * GT(2) \\ Y_{geo} = GT(3) + X_{pixel} * GT(4) + Y_{line} * GT(5) \\ \end{matrix} (Xge0Xge0X_{ge0}, Yge0Yge0Y_{ge0})表示对应于图上坐标(XpixelXpixelX_{pixel}, YlineYlineY_{line})的实际地理坐标。对一个上北下南的图像,GT(2)和GT(4)等于0, GT(1)是像元的宽度, GT(5)是像元的高度的相反数。(GT(0),GT(3))坐标对表示左上角像元的左上角坐标。

通过这个放射变换,我们可以得到图上所有像元对应的地理坐标。

好了,所以我们需要计算对于上面的六参数,我们主要需要计算重投影以后图像左上角的坐标(最小的X坐标值和最大的Y坐标值),这个转换我们可以通过osr.CoordinateTransformation类进行,下面给出实现代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
from osgeo import gdal
from osgeo import osr

# root_ds = gdal.Open('/Users/tanzhenyu/Resources/DataWare/MODIS/MOD09A1.A2017361.h28v06.006.2018005034659.hdf')
# # 返回结果是一个list,list中的每个元素是一个tuple,每个tuple中包含了对数据集的路径,元数据等的描述信息
# # tuple中的第一个元素描述的是数据子集的全路径
# ds_list = root_ds.GetSubDatasets()
#
# # 取出第1个数据子集(MODIS反射率产品的第一个波段)进行转换
# # 第一个参数是输出数据,第二个参数是输入数据,后面可以跟多个可选项
# gdal.Warp('reprojection.tif', ds_list[0][0], dstSRS='EPSG:32649')
#
# # 关闭数据集
# root_ds = None


def reproject(src_file, dst_file, p_width, p_height, epsg_to):
    """
    :param src_file: 输入文件
    :param dst_file: 输出文件
    :param p_width: 输出图像像素宽度
    :param p_height: 输出图像像素高度
    :param epsg_to: 输出图像EPSG坐标代码
    :return:
    """
    # 首先,读取输入数据,然后获得输入数据的投影,放射变换参数,以及图像宽高等信息
    src_ds = gdal.Open(src_file)
    src_srs = osr.SpatialReference()
    src_srs.ImportFromWkt(src_ds.GetProjection())

    srs_trans = src_ds.GetGeoTransform()
    x_size = src_ds.RasterXSize
    y_size = src_ds.RasterYSize
    d_type = src_ds.GetRasterBand(1).DataType

    # 获得输出数据的投影,建立两个投影直接的转换关系
    dst_srs = osr.SpatialReference()
    dst_srs.ImportFromEPSG(epsg_to)
    tx = osr.CoordinateTransformation(src_srs, dst_srs)

    # 计算输出图像四个角点的坐标
    (ulx, uly, _) = tx.TransformPoint(srs_trans[0], srs_trans[3])
    (urx, ury, _) = tx.TransformPoint(srs_trans[0] + srs_trans[1] * x_size, srs_trans[3])
    (llx, lly, _) = tx.TransformPoint(srs_trans[0], srs_trans[3] + srs_trans[5] * y_size)
    (lrx, lry, _) = tx.TransformPoint(srs_trans[0] + srs_trans[1] * x_size + srs_trans[2] * y_size,
                                      srs_trans[3] + srs_trans[4] * x_size + srs_trans[5] * y_size)

    min_x = min(ulx, urx, llx, lrx)
    max_x = max(ulx, urx, llx, lrx)
    min_y = min(uly, ury, lly, lry)
    max_y = max(uly, ury, lly, lry)

    # 创建输出图像,需要计算输出图像的尺寸(重投影以后图像的尺寸会发生变化)
    driver = gdal.GetDriverByName('GTiff')
    dst_ds = driver.Create(dst_file,
                           int((max_x - min_x) / p_width),
                           int((max_y - min_y) / p_height),
                           1, d_type)
    dst_trans = (min_x, p_width, srs_trans[2],
                 max_y, srs_trans[4], -p_height)

    # 设置GeoTransform和Projection信息
    dst_ds.SetGeoTransform(dst_trans)
    dst_ds.SetProjection(dst_srs.ExportToWkt())
    # 进行投影转换
    gdal.ReprojectImage(src_ds, dst_ds,
                        src_srs.ExportToWkt(), dst_srs.ExportToWkt(),
                        gdal.GRA_Bilinear)
    dst_ds.GetRasterBand(1).SetNoDataValue(0)  # 设置NoData值
    dst_ds.FlushCache()

    del src_ds
    del dst_ds


if __name__ == '__main__':
    src_file = 'HDF4_EOS:EOS_GRID:"MOD09A1.A2017361.h28v06.006.2018005034659.hdf":MOD_Grid_500m_Surface_Reflectance:sur_refl_b01'
    dst_file = 'reprojection.tif'
    reproject(src_file, dst_file, 450, 450, 32649)
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2018年06月01日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
23种设计模式,装饰器模式实战
装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式作为现有类的一个包装。
小马哥学JAVA
2024/04/06
1810
一文搞懂设计模式—装饰器模式
装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许向现有对象添加新功能而不改变其结构。装饰器模式通过创建包装对象(装饰器)来动态地扩展对象的行为,是继承的替代方案之一。
BookSea
2024/02/29
6360
一文搞懂设计模式—装饰器模式
【面试题精讲】javaIO设计模式之装饰器模式
装饰器模式(Decorator Pattern)是一种结构型设计模式,它允许你动态地将新功能添加到对象中。它通过创建一个包装类来实现,在不改变原有对象的基础上,为对象添加额外的行为。
程序员朱永胜
2023/10/22
2610
GoF 23种经典的设计模式——装饰器模式
装饰器模式(Decorator Pattern)允许向一个现有的对象添加新的功能,同时又不改变其结构。这种类型的设计模式属于结构型模式,它是作为现有的类的一个包装。
Andromeda
2024/01/21
700
「聊设计模式」之装饰器模式(Decorator)
🏆本文收录于《聊设计模式》专栏,专门攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎持续关注&&收藏&&订阅!
bug菌
2023/11/06
3951
「聊设计模式」之装饰器模式(Decorator)
Java 设计模式:装饰者模式(Decorator Pattern)
装饰者模式属于结构型设计模式,允许通过动态包装对象的方式为对象添加新功能,提供比继承更灵活的扩展方式。该模式通过组合替代继承,遵循开闭原则(对扩展开放,对修改关闭)。
用户11531739
2025/03/14
380
设计模式(6)-装饰器(认识程序中的装饰器)
之前已经看过装饰器模式,但是感觉不是很清晰,但是有一种情况下出的代码,一定是装饰器。 Widget* aWidget = new BorderDecorator( new BorderDecorator( new ScrollDecorator( new TextField( 80, 24 )))); 可以看到,层层嵌套,每个类都可以按照一定的顺序嵌套多次。 比如将顺序改为如下: Widget* bWidget = new ScrollDecorator( new BorderDecorat
cloudskyme
2018/03/20
8170
设计模式(6)-装饰器(认识程序中的装饰器)
装饰器模式
装饰模式是一种结构型设计模式,允许动态地向对象添加新功能,而不会影响其他对象。装饰模式通过使用一系列装饰类,将额外的行为或责任以层叠的方式附加到对象上。
码事漫谈
2024/12/20
670
装饰器模式
设计模式 (三)——装饰者模式(Decorator,结构型)
使用设计模式可以提高代码的可复用性、可扩充性和可维护性。装饰者模式( Pattern)属于结构型模式,动态地将责任附加到对象上。若要扩展功能,装饰者提供了比继承更有弹性的替代方案。它是通过创建一个包装对象,通过包装对象来包裹真实的对象,以达到装饰目的。
恋喵大鲤鱼
2018/08/03
8090
设计模式 (三)——装饰者模式(Decorator,结构型)
【Java设计模式系列】装饰器模式(Decorator Pattern)
装饰模式以对用户透明的方式动态给一个对象附加功能。用户不会觉得对象在装饰前、后有何不同。装饰模式可在无需创造更多子类情况下,扩展对象的功能。
JavaEdge
2021/10/18
3550
结合案例深入解析装饰者模式
允许向一个现有的对象添加新的功能。同时又不改变其结构,它是作为现有的类的一个包装。
李红
2019/06/14
3650
结合案例深入解析装饰者模式
设计模式之装饰者模式(Decorator Pattern)问题提出引出装饰者模式定义装饰者模式实现装饰者模式总结与分析
装饰者模式可以做到在不修改任何底层代码的情况下,给对象增加的新的方法。 首先,我们通过对一个现实问题的模拟分析,了解什么是装饰者模式以及装饰者模式的作用。
desperate633
2018/08/22
5200
设计模式之装饰者模式(Decorator Pattern)问题提出引出装饰者模式定义装饰者模式实现装饰者模式总结与分析
跟着GPT学设计模式之装饰者模式
装饰者模式是一种结构型设计模式,它允许你在不修改已有对象的情况下,动态地向对象添加额外的功能。装饰者模式通过包装原始对象来扩展其功能,并提供了一种灵活的方式来组合多个装饰器。装饰器模式主要解决继承关系过于复杂的问题,通过组合来替代继承。它主要的作用是给原始类添加增强功能。
codetrend
2024/03/30
1040
Java设计模式:深入装饰器模式的三种写法(六)
Java中的装饰器模式是一种结构型设计模式,它允许你在不修改现有类的情况下,动态地将新功能添加到对象上。装饰器模式通过创建一个包装了原始对象的装饰器类来实现这一点。装饰器类与原始类具有相同的接口,因此它们可以互换使用。
公众号:码到三十五
2024/03/19
3630
Java设计模式:深入装饰器模式的三种写法(六)
设计模式---装饰者模式
装饰者模式(Decorator Pattern):动态地给一个对象增加一些额外的职责,增加对象功能来说,装饰模式比生成子类实现更为灵活。装饰模式是一种对象结构型模式。
大忽悠爱学习
2021/11/15
3250
设计模式(八)装饰器模式Decorator(结构型)
上面的类图看起来并不怎么坏,下面让我们再增加一些特性。表单验证阶段,你希望能够指出一个表单控制是否合法。你为非法控制使用的代码又一次继承其它组件,因此又需要产生大量的子类:
黄规速
2022/04/14
3880
设计模式(八)装饰器模式Decorator(结构型)
装饰器模式Decorator Pattern-23种常用设计模式快速入门教程
装饰器模式(Decorator Pattern)是一种结构型设计模式,它可以在不改变原有对象的基础上,动态地给对象添加新的职责和行为。 该模式的核心思想是以递归的方式,通过将对象包装在装饰器对象中,来不断添加新的行为和职责。装饰器模式的结构包括以下角色:
jack.yang
2025/04/05
420
Java设计模式-装饰器模式 理论代码相结合
上班族大多都有睡懒觉的习惯,每天早上上班时间都很紧张,于是很多人为了多睡一会,就会用方便的方式解决早餐问题。有些人早餐可能会吃煎饼,煎饼中可以加鸡蛋,也可以加香肠,但是不管怎么“加码”,都还是一个煎饼。在现实生活中,常常需要对现有产品增加新的功能或美化其外观,如房子装修、相片加相框等,都是装饰器模式。在我们自己行业就是这个东西得加需求啦
宁在春
2022/10/31
4120
Java设计模式-装饰器模式 理论代码相结合
Java设计模式之装饰器模式
在面向对象设计中,经常会遇到需要在不改变现有类结构的情况下,动态地为对象添加新的功能的需求。这时候,装饰器模式就派上了用场。
刺槐儿
2024/01/24
4600
设计模式之装饰器模式
装饰器模式(Decorator Pattern)是一种结构型设计模式,它可以在不改变现有对象的结构的情况下,动态地给对象增加一些额外的功能。装饰器模式通过创建一个包装对象(即装饰器)来包裹真实对象,并在保持真实对象的接口不变的前提下,为其提供额外的功能。装饰器模式可以在运行时根据需要选择不同的装饰器来组合和修改对象的行为。
wayn
2023/09/12
2330
设计模式之装饰器模式
推荐阅读
相关推荐
23种设计模式,装饰器模式实战
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验