Как читать двоичные файлы 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, так что, если вы не можете использовать какие-либо языковые трюки для других языков, это было бы здорово.

5 ответов

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

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))

Поскольку записи имеют фиксированную длину (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-разрядное целое число со знаком и обработать его. Поскольку вы уже знаете размер сетки, вы можете читать ее построчно или любым другим способом, который удобен для вашего приложения. Это также означает, что вы можете произвольно искать конкретные координаты внутри файла данных.

Если вы хотите немного большей скорости, чем миллионы обращений к 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()

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

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

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

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

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

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

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

Другие вопросы по тегам