как читать двоичные файлы NASA .hgt

Я уверен, что это действительно просто, если вы знаете что-нибудь о бинарных файлах, но я новичок на этот счет.

Как мне извлечь данные из файлов NASA .hgt? Вот описание с www2.jpl.nasa.gov/srtm/faq.html:

Файлы данных SRTM имеют такие имена, как «N34W119.hgt». Что означают буквы и цифры и что такое формат ".hgt"?

Каждый файл данных охватывает один градус широты и один градус долготы поверхности Земли. Первые семь символов обозначают юго-западный угол блока, где N, S, E и W означают север, юг, восток и запад. Таким образом, файл N34W119.hgt охватывает широты 34–35 северной широты и 118–119 западной долготы (этот файл включает центр Лос-Анджелеса, Калифорния). Расширение имени файла ".hgt" просто означает слово "высота", означающее высоту. Это НЕ тип формата. Эти файлы представлены в «сыром» формате (без заголовков и без сжатия), 16-разрядные целые числа со знаком, высота, измеренная в метрах над уровнем моря, в «географической» (массив широты и долготы) проекции, с пустотами данных, обозначенными -32768. , Международные файлы с тремя дугами-секундами имеют 1201 столбец и 1201 строку данных с общим размером файла 2 884 802 байта (= 1201 x 1201 x 2). В Соединенных Штатах файлы длиной 1 дуга-секунда имеют 3601 столбец и 3601 строку данных, а общий размер файла составляет 25 934 402 байта (= 3601 x 3601 x 2). Для получения дополнительной информации прочитайте текстовый файл «SRTM_Topo.txt» по адресу http://edcftp.cr.usgs.gov/pub/data/srtm/Readme.html.

Спасибо за любую помощь! Я собираюсь использовать эти данные в скрипте Python, так что, если вы не можете использовать какие-либо языковые трюки для других языков, это было бы здорово.

10.12.2008 20:05:36
Ссылка в вопросе не работает, но я думаю, что это тот же файл: dds.cr.usgs.gov/srtm/version1/Documentation/SRTM_Topo.txt
Hubro 14.05.2012 11:06:10
6 ОТВЕТОВ

Поскольку записи имеют фиксированную длину (16-разрядные целые числа со знаком) и вы знаете размер сетки (1201 x 1201 или 3601x3601), модуль Python struct кажется идеально подходящим (непроверенный код):

from struct import unpack,calcsize

# 'row_length' being 1201 or 3601 and 'row' being the raw data for one row
def read_row( row, row_length ):
    format = 'h'  # h stands for signed short

    for i in range(0, row_length):
        offset = i * calcsize(format)
        (height,) = unpack(format, row[offset : offset+calcsize(format))
        # do something with the height

Описывая его в более общих терминах, в основном вы хотите прочитать файл по 2 байта за раз, проанализировать прочитанные байты как 16-разрядное целое число со знаком и обработать его. Поскольку вы уже знаете размер сетки, вы можете читать ее построчно или любым другим способом, который удобен для вашего приложения. Это также означает, что вы можете произвольно искать конкретные координаты внутри файла данных.

7
10.12.2008 20:21:12
Вам действительно нужно использовать формат '! H'. big-endian, как описано в спецификации SRTM
skrat 6.02.2010 13:45:34
Либо '!h'или '>h'нужно работать, чтобы определить big-endian: docs.python.org/3/library/…
Kyle Barron 28.03.2020 18:43:27

Файлы данных NASA SRTM имеют формат Big-Endian, поэтому в зависимости от платформы, на которой вы читаете данные, вам может потребоваться выполнить преобразование из Big-Endian в Little-Endian.

Есть множество источников о том, как это сделать, у меня нет опыта работы с Python, поэтому я не могу вам помочь.

Но если вы забудете это, ваши ценности будут испорчены.

0
25.05.2009 14:39:23

Если у вас есть фотошоп, вы можете поиграть с необработанным импортом, чтобы заставить его читать эти файлы и сохранять их во что-то более полезное. Я имел некоторый успех в подобных вещах в прошлом.

0
6.06.2009 05:46:16

Если вы хотите немного больше скорости, чем вы получаете от миллионов вызовов struct.unpack, посмотрите на array.array. Хотя реализация «struct-and-for-loop» занимает несколько секунд на моем, предположительно, медленном ноутбуке, следующее практически мгновенно:

from array import array

f = open(filename, 'rb')
format = 'h'
row_length = 1201
data = array(format)
data.fromfile(f, row_length*row_length)
data.byteswap()
f.close()
5
31.01.2013 11:58:29

Проверенный пример:

import os
import math
import numpy

fn = 'DMV/N51E000.hgt'

siz = os.path.getsize(fn)
dim = int(math.sqrt(siz/2))

assert dim*dim*2 == siz, 'Invalid file size'

data = numpy.fromfile(fn, numpy.dtype('>i2'), dim*dim).reshape((dim, dim))
10
13.06.2013 19:09:10
Обратите внимание, что это сначала читает файл в плоский, 1D массив Numpy, а затем преобразует в 2D массив. Может быть быстрее сначала прочитать байты, а затем загрузить их прямо в двумерный массив: numpy.ndarray((dim, dim), numpy.dtype('>i2'), buffer)где bufferнаходятся необработанные байты из файла.
Kyle Barron 28.03.2020 19:14:02

https://gdal.org/drivers/raster/srtmhgt.html

    Input_HGT = 'N30E120.hgt'
    import gdal
    Raster = gdal.Open(Input_HGT) 

Все функции, доступные с GDAL для растровых файлов, могут быть применены к этому 'Растру', как Функции, доступные с переменной 'Растр'

1
8.08.2019 12:55:22