2008-12-10 42 views
22

Tôi chắc chắn điều này thực sự đơn giản nếu bạn biết bất kỳ điều gì về tệp nhị phân, nhưng tôi là người mới trên điểm số đó.cách đọc các tệp nhị phân của NASA .hgt

Làm cách nào để trích xuất dữ liệu từ tệp .hgt của NASA? Dưới đây là mô tả từ www2.jpl.nasa.gov/srtm/faq.html:

Tệp dữ liệu SRTM có tên như "N34W119.hgt". Các chữ cái và số là gì và định dạng ".hgt" là gì?

Mỗi tệp dữ liệu bao gồm một độ vĩ độ bằng một độ kinh độ khối bề mặt trái đất. Bảy ký tự đầu tiên chỉ ra phía tây nam là góc của khối, với N, S, E và W đề cập đến phía bắc, nam, đông, và phía tây. Do đó, tệp "N34W119.hgt" bao gồm các vĩ độ 34 đến 35 Bắc và kinh độ 118-119 Tây (tệp này bao gồm trung tâm thành phố Los Angeles, California). Phần mở rộng tên tệp ".hgt" chỉ đơn giản là viết tắt của từ "chiều cao", có nghĩa là độ cao. Nó KHÔNG phải là một loại định dạng. Các tệp này là ở định dạng "thô" (không có tiêu đề và không được nén), số nguyên được ký 16 bit, độ cao đo bằng mét trên mực nước biển, trong phép chiếu "địa lý" (vĩ độ và kinh độ), với khoảng trống dữ liệu được chỉ định bởi -32768. Các tệp 3-arc-second quốc tế có 1201 cột và 1201 hàng dữ liệu, với tổng kích thước là 2.884,802 byte (= 1201 x 1201 x 2). United Các tệp 1-arc-second của Hoa có 3601 cột và 3601 hàng dữ liệu, với tổng số tệp là là 25.934,402 byte (= 3601 x 3601 x 2). Để biết thêm thông tin đọc các tập tin văn bản "SRTM_Topo.txt" tại http://edcftp.cr.usgs.gov/pub/data/srtm/Readme.html

Nhờ sự giúp đỡ! Tôi sẽ sử dụng dữ liệu này trong một kịch bản python, vì vậy nếu bạn không thể sử dụng bất kỳ thủ thuật ngôn ngữ cụ thể cho bất kỳ ngôn ngữ khác, đó sẽ là tuyệt vời.

+2

Các liên kết trong câu hỏi bị hỏng, nhưng tôi nghĩ đây là cùng một tệp: http://dds.cr.usgs.gov/srtm/version1/Documentation/SRTM_Topo.txt – Hubro

Trả lời

6

Kể từ khi hồ sơ được cố định chiều dài (16-bit đã ký số nguyên) và bạn biết kích thước lưới (1201 x 1201 hoặc 3601x3601), mô-đun struct Python có vẻ lý tưởng phù hợp (mã chưa được kiểm tra):

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 

Mô tả nó trong các thuật ngữ chung chung hơn, về cơ bản bạn muốn đọc các tập tin trong 2 byte tại một thời điểm, phân tích cú pháp byte đọc như một số nguyên 16-bit ký và xử lý nó. Vì bạn biết kích thước lưới đã có, bạn có thể đọc nó theo từng hàng hoặc theo bất kỳ cách nào khác thuận tiện cho ứng dụng của bạn. Nó cũng có nghĩa là bạn có thể tìm kiếm ngẫu nhiên các tọa độ cụ thể bên trong tệp dữ liệu.

+3

Bạn thực sự cần sử dụng định dạng '! h'. big-endian như mô tả trong thông số kỹ thuật SRTM – skrat

0

Tệp dữ liệu SRTM của NASA có định dạng Big-Endian, do đó tùy thuộc vào nền tảng bạn đang đọc dữ liệu, bạn có thể phải thực hiện chuyển đổi từ Big-Endian thành Little-Endian.

Có rất nhiều nguồn về cách thực hiện việc này, tôi không có kinh nghiệm với Python nên tôi không thể giúp bạn ở đó.

Nhưng nếu bạn quên điều này, giá trị của bạn sẽ bị rối tung lên.

0

Nếu bạn có photoshop, bạn có thể chơi xung quanh với việc nhập liệu thô để làm cho nó đọc những tệp này và lưu chúng vào một cái gì đó hữu ích hơn. Tôi đã có một số thành công trong việc làm điều này trong quá khứ.

4

Nếu bạn muốn có tốc độ nhanh hơn một chút so với hàng triệu cuộc gọi đến struct.unpack, hãy xem array.array. Trong khi "struct-và-cho-loop" thực hiện phải mất vài giây trên máy tính xách tay phải thừa nhận là chậm của tôi, sau đây là gần ngay lập tức:

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

Một thử nghiệm ví dụ NumPy:

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)) 
Các vấn đề liên quan