从.HGT文件中提取高度?


20

我想在地图上为SRTM3数据文件中的高程指定特定的长/纬度位置,但不知道如何查找特定值。因此,我想举个例子,说明如何在N50E14.hgt海拔高度找到50°24'58.888“ N,14°55'11.377” E。


1
您正在使用什么软件?SRTM文档中有一些关于.hgt文件格式的注释,但是具体的分步解答取决于您可用的软件。
2012年

1
我没有软件,我是C#程序员,并且正在编写自己的应用程序。我能够为每个像素分配长/纬度,现在我想搜索每个点的高程。最佳数据格式应类似于CSV文件。因此,我可以在一排中找到经度,纬度和高度。我已经搜索了SRTM文档,但是我仍然无法想象如何在文件上提供数据挖掘。
MartinS 2012年

Answers:


30

资料格式

我将在如何对数据读取器进行编程方面作为一个小练习。看一下文档

SRTM数据分为两个级别:SRTM1(用于美国及其领土和财产),其数据在纬度和经度上以一弧秒的间隔进行采样;而SRTM3(在世界范围内)以三个弧度秒进行采样。

数据在“地理”投影中按一度的纬度和经度图块划分,也就是说,在纬度和经度等距间隔内的栅格表示完全没有投影,但是易于操作和镶嵌。

文件名是指图块左下角的纬度和经度-例如N37W105的左下角在北纬37度和西经105度处。更确切地说,这些坐标是指左下像素的几何中心,在SRTM3数据的情况下,其范围约为90米。

高程文件的扩展名为.HGT,并带有两个字节的整数。字节按摩托罗拉“ big-endian”顺序排列,最高有效字节在前,可直接由系统(例如使用Power PC处理器的Sun SPARC,Silicon Graphics和Macintosh计算机)读取。DEC Alpha,2006年以后制造的大多数PC和Macintosh计算机都使用Intel(“小端”)顺序,因此可能需要进行某些字节交换。高度以米为单位参照WGS84 / EGM96大地水准面。数据空值分配的值为-32768。

如何进行

对于您的位置,北纬50°24'58.888“ N 14°55'11.377”,您已经找到正确的瓷砖N50E14.hgt。让我们找出您感兴趣的像素。第一纬度,50°24'58.888“ N:

24'58.888" = (24 * 60)" + 58.888" = 1498.888"

弧秒。除以三并四舍五入为最接近的整数将得到500的网格行。对经度的相同计算将在网格列1104中产生。

快速入门文档缺少有关文件中行和列的组织方式的信息,但完整文档中指出:

数据按行主要顺序存储(第1行的所有数据,然后是第2行的所有数据,依此类推)

文件中的第一行很可能是最北端的,即,如果我们对下边缘的第500行感兴趣,我们实际上必须查看行

1201 - 500 = 701

从文件开始。我们的网格单元是数字

(1201 * 700) + 1104 = 841804

从文件的开头(即跳过700行,并在第701行中取样1104)。每个样本两个字节意味着我们必须跳过文件中的前1683606个字节,然后读取两个字节才能获取网格单元。数据是big-endian的,这意味着您需要在例如Intel平台上交换两个字节。

样例程序

一个用于检索正确数据的简单Python程序如下所示(有关struct模块的使用,请参阅文档):

import struct

def get_sample(filename, n, e):
    i = 1201 - int(round(n / 3, 0))
    j = int(round(e / 3, 0))
    with open(filename, "rb") as f:
        f.seek(((i - 1) * 1201 + (j - 1)) * 2)  # go to the right spot,
        buf = f.read(2)  # read two bytes and convert them:
        val = struct.unpack('>h', buf)  # ">h" is a signed two byte integer
        if not val == -32768:  # the not-a-valid-sample value
            return val
        else:
            return None

if __name__ == "__main__":
    n = 24 * 60 + 58.888
    e = 55 * 60 + 11.377
    tile = "N50E14.hgt"  # Or some magic to figure it out from position
    print get_sample(tile, n, e)

请注意,有效的数据检索将不得不看起来更加复杂(例如,不为每个样本打开文件)。

备择方案

您也可以使用可以直接读取.hgt文件的程序。但这很无聊。


击败我,并启动更多细节!
2012年

很好的解释,爱你。谢谢你的帮助。你们大家
MartinS 2012年

1
+1是,行从北到南排序。一旦映射了其中一个文件,这一点就很清楚了。另外,考虑通过双线性插值法在位置周围的四个像元中心之间获取高度。
whuber

感谢您提供的全面信息!我有一个问题:当我们在寻找50°24'58.888的高程数据时,为什么当从北向南对行进行排序时,从下边缘减去行号500?谢谢!
乔治

如果我没记错的话,我相信(j-1)应该只是j。值j的范围是0到1200,因此不需要减去
1。– Malipivo

6

GDAL可以使用SRTMHGT驱动程序读取/写入这些栅格格式。这意味着您可以使用QGIS,ArcGIS查看栅格,或使用GDAL实用程序(如gdallocationinfo)从某个点获取值,例如:

将DMS转换为DD:

  • 纬度:50°24'58.888“ N = 50 +(24/60)+(58.888 / 3600)= 50.4163577778
  • 长:14°55'11.377“ E = 14 +(55/60)+(11.377 / 3600)= 14.9198269444

然后在shell中使用gdallocationinfo file.hgt -wgs84 long lat

$ gdallocationinfo N50E14.hgt -wgs84 14.9198269444 50.4163577778
Report:
  Location: (1104P,700L)
  Band 1:
    Value: 216

海拔是216 m。


1
南侧或西侧的位置如何?
Muhammet Ali Asan

2

如果您确实使用QGIS,请检查是否安装了python插件“ Point Sampling Tool”。您可以在->增强(Python)->分析中找到它。

选择所需位置的点层,然后启动PST,选择hgt(或任何光栅/多边形文件),然后选择新的点形状进行输出。

就这样 :-)

  Chris

0

克里斯(Chris)的回答表明,从QGIS中的某个层采样点很简单。

但是,由于您对我的评论的回复明确了您正在编写自己的程序以从.hgt文件中读取高程值,因此请另外查看SRTM文档中的Quickstart PDF。它说明了高程数据的存储方式。总结一下:

  • SRTM3文件包含一系列大端整数值。
  • 每个整数值都代表一个海拔高度,“以WGS84 / EGM96大地水准面为基准,以米为单位”,而的值-32768表示无数据像素。
  • 有1201行的1201行,所以总共应该有1442401个整数值。

您说可以在lon / lat坐标和像素之间转换,因此获取高程只是从文件中的适当偏移量读取整数值的问题。给定像素坐标xy相对于场景的左上角,基本上是offset = (y * 1201) + x。像素0,0是文件中的第一个整数,像素1200,1200是文件中的最后一个整数。


1
这是正确的,但是缺少bhell的答案提供的一些关键细节,包括坐标与单元中心相关联。因此,例如,N50E014.hgt的左上角实际上是位于东经13.99958 E,纬度51.00042 N.
whuber
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.