当前位置: 首页 > news >正文

从GDAL中 读取遥感影像的信息

从GDAL提供的实用程序来看,很多程序的后缀都是 .py ,这充分地说明了Python语言在GDAL的开发中得到了广泛的应用。

1. 打开已有的GeoTIF文件

下面我们试着读取一个GeoTiff文件的信息。第一步就是打开一个数据集。

>>> from osgeo import gdal
>>> dataset = gdal.Open("/gdata/geotiff_file.tif")

既然已经将一个GeoTIFF文件打开为一个GDAL可操作的对象, 下面来看一下都能对其进行怎样的操作。

Python提供了 dir() 内省函数, 可以快速查看一下当前对象可用的操作:

dir() 函数可能是 Python 自省机制中最著名的部分了。它可以返回传递给它的任何对象的属性名称经过排序的列表。 如果不指定对象,则 dir() 返回当前作用域中的名称。

>>> dir(dataset)[:3] + ['... ...'] + dir(dataset)[-3:]
['AbortSQL','AddBand','AddFieldDomain','... ...','__weakref__','this','thisown']

下面看一下如何获取文件的一些基本信息,需要用到下面的一些函数与属性。

  • dataset.GetDescription() 获得栅格的描述信息

  • dataset.RasterCount 获得栅格数据集的波段数

  • dataset.RasterXSize 栅格数据的宽度(X方向上的像素个数)

  • dataset.RasterYSize 栅格数据的高度(Y方向上的像素个数)

  • dataset.GetGeoTransform() 栅格数据的六参数。

  • GetProjection() 栅格数据的投影

通过下面小节我们逐一解释一下。

2. 读取影像的元数据

从元数据的作用来看,它更多地是为工程服务的。 客观地说,GDAL对元数据的支持并不好, 它并没有直接的元数据处理接口, 更没有实现元数据的相关标准。 但是,GDAL已经提供了足够方便的函数,可以读取影像的一些信息, 从而方便对数据进行处理。 GDAL一般是以字典的形式对元数据进行组织的, 但是对于不同的栅格数据类型,元数据的类型与键值可能都不一样。

目前, 国际上对空间元数据标准内容进行研究的组织主要有三个,分别是欧洲标准化委员会(CEN/TC 287)、 美国联邦地理数据委员会(FGDC)和国际标准化组织地理信息/地球信息技术委员会(ISO/TC 211)。

如果要进行元数据处理,可以考虑将元数据信息写入到XML文件中。 这个问题扩展开来就不是本书关心的内容的,在此就不再多说了。

我们先来看一下最常用的GeoTIFF文件的元数据信息。 GDAL可以作为数据集级别的元数据来处理下面的基本的TIFF标志。

  • TIFFTAG_DOCUMENTNAME

  • TIFFTAG_IMAGEDESCRIPTION

  • TIFFTAG_SOFTWARE

  • TIFFTAG_DATETIME

  • TIFFTAG_ARTIST

  • TIFFTAG_HOSTCOMPUTER

  • TIFFTAG_COPYRIGHT

  • TIFFTAG_XRESOLUTION

  • TIFFTAG_YRESOLUTION

  • TIFFTAG_RESOLUTIONUNIT

  • TIFFTAG_MINSAMPLEVALUE (read only)

  • TIFFTAG_MAXSAMPLEVALUE (read only)

使用Python 打开数据来读取一下数据的信息:

>>> from osgeo import gdal
>>> dataset = gdal.Open("/gdata/geotiff_file.tif")
>>> dataset.GetMetadata()
{'AREA_OR_POINT': 'Area', 'PyramidResamplingType': 'NEAREST'}
>>> dir(dataset)[:10]
['AbortSQL','AddBand','AddFieldDomain','AddRelationship','AdviseRead','BeginAsyncReader','BuildOverviews','ClearStatistics','CommitTransaction','CopyLayer']

GetMetadata() 方法可以访问数据的元数据信息,元数据信息对于每个数据都是不一样的。 比如再打开另外一个文件:

>>> ds = gdal.Open('/gdata/lu75c.tif')
>>> ds.GetMetadata()
{'AREA_OR_POINT': 'Area','TIFFTAG_XRESOLUTION': '1','TIFFTAG_YRESOLUTION': '1'}

这个文件只对两个TIFF标志进行了定义,还有一个并不是TIFF标志定义的。

GetDescription() 获得栅格的描述信息

>>> dataset.GetDescription()
'/gdata/geotiff_file.tif'

看来这里的图像描述是图像的路径名, 但是这是和各种不同数据集相关的, 不同数据集有不同的描述。

获取栅格数目

栅格数据集是由多个数据构成的,在GDAL中,每一个波段,都是一个数据集; 不仅如此,栅格数据集还可能包含有子数据集,每子数据集又可能包含有波段。

先来看一下刚才打开的数据的RasterCount

>>> dataset.RasterCount
3

这是一个由7个波段构成的Landsat遥感影像。

再看一个MODIS L1B数据:

>>> mds = gdal.Open("/gdata/MOD09A1.A2009193.h28v06.005.2009203125525.hdf")
>>> mds.RasterCount
0

运行结果居然是 0 。这意味着当前的数据集 dataset 中的栅格数目是 0 。 实际上,MODISL1B的数据格式是HDF格式的,它的数据是以子数据集组织的,要获取其相关的数据的信息,需要继续访问其子数据集。

影像大小

栅格数据的大小指出了影像以像元为单位的宽度与高度。

>>> dataset.RasterXSize,dataset.RasterYSize
(1500, 900)

可以看出我们的影像大小。

获得空间参考

下面看一下如果从栅格数据集中获取其投影与空间参考信息。 更多的关于投影与空间参考的讨论,会在后面章节介绍。

GetGeoTransform() 地理仿射变换参数。

对于遥感影像来说,它需要在地理空间中进行定位。 在GDAL中,这有两种方式,其中一种是使用六个参数坐标转换模型。 这个模型的具体实现在不同的软件中是不一样的。 在GDAL中,这六个参数包括 左上角坐标 , 像元X、Y方向大小 , 旋转 等信息。 要注意, Y 方向的像元大小为负值。

>>> ds.GetGeoTransform()
(1852951.7603168152, 30.0, 0.0, 5309350.360150607, 0.0, -30.0)

获得投影信息

使用 GetProjection() 函数,可以比较容易地获取数据集的投影信息。 但是对于什么是地图投影,以及如何在GDAL中实现,就不是这么容易了。 此处我们只是简单地运行一下,更详细的解释,会在后面章节中展开。

>>> ds.GetProjection()
'PROJCS["unnamed",GEOGCS["unknown",DATUM["unnamed",SPHEROID["unretrievable - using WGS84",6378137,298.257223563]],PRIMEM["Greenwich",0],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]]],PROJECTION["Albers_Conic_Equal_Area"],PARAMETER["latitude_of_center",0],PARAMETER["longitude_of_center",105],PARAMETER["standard_parallel_1",25],PARAMETER["standard_parallel_2",47],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["Easting",EAST],AXIS["Northing",NORTH]]'

3. 使用GDAL获取栅格数据波段信息

上面我们介绍了针对数据集操作的主要函数。 但是如果需要了解栅格数据的更多信息,我们就需要看一下遥感图像处理中更常用到的波段操作的函数。

获取数据集的波段

GetRasterBand() 函数,可以获得栅格数据集的波段。这是函数的参数使用波段的索引值。

>>> from osgeo import gdal
>>> dataset = gdal.Open('/gdata/lu75c.tif')
>>> dataset.RasterCount
1
>>> band = dataset.GetRasterBand(1)

这里我们获取了第一个波段(红色值组成的表)。

注意!这里的波段获取和一般编程语言中数组下标的索引方式不一样,开始是 1 不是 0 。

查看波段的基本信息

下面我们现在来看看刚才读取出来的 band 有些什么东西可以供我们操作。

与操作数据集一样,GDAL同样提供了查看波段基本信息的函数。

>>> band = dataset.GetRasterBand(1)
>>> dir(band)[:6] + ['... ...'] + dir(band)[-3:]
['AdviseRead','AsMDArray','Checksum','ComputeBandStats','ComputeRasterMinMax','ComputeStatistics','... ...','__weakref__','this','thisown']

看一下常用的操作。这些也是用来获取波段的属性信息。

获取波段大小

>>> band.XSize, band.YSize, band.DataType
(6122, 4669, 3)

执行以上代码得到了波段图像的宽和高(像元为单位)。 对于我们所使用的影像, 这个与 dataset 中使用 RasterXSize() 与 RasterYSize() 获取的值一致。 DataType 是图像中实际数值的数据类型,表示 8 位无符整型。

获取波段数据的属性

>>> band.GetNoDataValue()
>>> band.GetMaximum()
>>> print(band.GetMinimum())
None
>>> band.ComputeRasterMinMax()
(-1.0, 66.0)

Maximum 是表示在本波段数值中最大的值,当然 Minimum 就是表示本波段中最小的值。 通过运行结果,我们可以看到在一开始RasterXSize()RasterYSize()都没有值。 因为对于文件格式不会有固有的最大最小值。 所以我们可以通过函数 ComputeRasterMinMax() 计算得到。 注意!这里的最大最小值不包括“无意义值”! 也就是上面显示的 NoDataValue 。

4. 其他数据格式格式

使用GDAL读取ENVI数据格式

ENVI栅格文件格式

ENVI使用的是通用栅格数据格式,包含一个简单的二进制文件(a simple flat binary)和一个相关的ASCII(文本)的头文件。这也保证了单个ENVI栅格文件没有大小上限。

(1)头文件

ENVI头文件包含用于读取图像数据文件的信息,它通常创建于一个数据文件第一次被ENVI读取时。单独的ENVI头文本文件提供关于图像尺寸、 嵌入的头文件(若存在)、数据格式及其它相关信息。所需信息通过交互式输入,或自动地用“文件吸取”创建,并且以后可以编辑修改。 使用者可以在ENVI之外使用一个文本编辑器生成一个ENVI头文件。

(2)数据文件

通用栅格数据都会存储为二进制的字节流,通常它将以BSQ(band sequential,按波段顺序储存)、BIP(band interleaved by pixel,按波段像元交叉储存)或者BIL(band interleaved by line,按波段行交叉储存)的方式进行存储。

ENVI栅格文件必须包含着两个文件,其中头文件的后缀名为:.hdr,数据文件的后缀随意,甚至可以不带后缀名。 这两个文件是通过文件名来关联,即数据文件和头文件名称一致。

GDAL读取HDF数据格式

由于modis卫星数据跟我们经常遇到的geotif数据组织方式不一样,读取的时候一定要特别注意。geotif数据,一般是一个文件,包含了多个波段的数据; 而modis呢,一个文件包含了多各SUBDATASETSGDAL, 每个SUBDATASETS又包含多个波段数据。 另外默认编译的GDAL并不包含对MODIS数据支持, 需要单独下载针对HDF4,HDF5的源码,再修改下make.opt文件, 这时再编译GDAL,就支持modis数据的读写了。

相关文章:

从GDAL中 读取遥感影像的信息

从GDAL提供的实用程序来看,很多程序的后缀都是 .py ,这充分地说明了Python语言在GDAL的开发中得到了广泛的应用。 1. 打开已有的GeoTIF文件 下面我们试着读取一个GeoTiff文件的信息。第一步就是打开一个数据集。 >>> from osgeo import gdal…...

算法闭关修炼百题计划(一)

多看优秀的代码一定没有错,此篇博客属于个人学习记录 1.两数之和2.前k个高频元素3.只出现一次的数字4.数组的度5.最佳观光组合6.整数反转7.缺失的第一个正数8.字符串中最多数目的子序列9.k个一组翻转链表10.反转链表II11. 公司命名12.合并区间13.快速排序14.数字中的…...

vue3实现打字机的效果,可以换行

之前看了很多文章,效果是实现了,就是没有自动换行的效果,参考了文章写了一个,先上个效果图,卡顿是因为模仿了卡顿的效果,还是很丝滑的 目录 效果图:代码如下 效果图: ![请添加图片描述](https://i-blog.csdnimg.cn/direct/d8ef33d83dd3441a87d6d033d9e7cafa.gif 代码如下 原…...

【如何学习操作系统】——学会学习的艺术

🐟作者简介:一名大三在校生,喜欢编程🪴 🐡🐙个人主页🥇:Aic山鱼 🐠WeChat:z7010cyy 🦈系列专栏:🏞️ 前端-JS基础专栏✨前…...

stm32 flash无法擦除

通过bushound调试代码发现,当上位机发送命令到模组后flash将不能擦除,通过 HAL_FLASH_GetError()函数查找原因是FLASH Programming Sequence error(编程顺序错误),解决办法是在解锁后清零标志位…...

Android—ANR日志分析

获取ANR日志: ANR路径:/data/anrADB指令:adb bugreport D:\bugrep.zip ANR日志分析步骤: “main” prio:主线程状态beginning of crash:搜索 crash 相关信息CPU usage from:搜索 cpu 使用信息…...

9.29 LeetCode 3304、3300、3301

思路: ⭐进行无限次操作,但是 k 的取值小于 500 ,所以当 word 的长度大于 500 时就可以停止操作进行取值了 如果字符为 ‘z’ ,单独处理使其变为 ‘a’ 得到得到操作后的新字符串,和原字符串拼接 class Solution { …...

近万字深入讲解iOS常见锁及线程安全

什么是锁? 在程序中,当多个任务(或线程)同时访问同一个资源时,比如多个操作同时修改一份数据,可能会导致数据不一致。这时候,我们需要“锁”来确保同一时间只有一个任务能够操作这个数据&#…...

linux创建固定大小的文件夹用于测试

在linux上创建固定大小的文件夹用于测试磁盘空间不足时的应用故障。 实验环境为centos7,有两种简易方法: 一、使用ramdisk 1、创建文件夹 mkdir /var/mytest 2、创建一个1m大小的临时文件 mount none /var/mytest -t tmpfs -o size1m size也可以写…...

大模型学习路线:这会是你见过最全最新的大模型学习路线【2024最新】

大模型学习路线 建议先从主流的Llama开始,然后选用中文的Qwen/Baichuan/ChatGLM,先快速上手体验prompt工程,然后再学习其架构,跑微调脚本 如果要深入学习,建议再按以下步骤,从更基础的GPT和BERT学起&…...

了解云计算工作负载保护的重要性,确保数据和应用程序安全

云计算de小白 云计算技术的快速发展使数据和应用程序安全成为一种关键需求,而不仅仅是一种偏好。随着越来越多的客户公司将业务迁移到云端,保护他们的云工作负载(指所有部署的应用程序和服务)变得越来越重要。云工作负载保护&…...

Swagger3基本使用

Swagger 课程目标 Swagger简介【了解】 Springboot整合swagger【掌握】 Swagger 常用注解【掌握】 knife4j-Swagger【会用】 一、Swagger3简介 Swagger 是一系列 RESTful API 的工具,通过 Swagger 可以获得项目的⼀种交互式文档,客户端 SDK 的自 动…...

如何借助Java批量操作Excel文件?

最新技术资源(建议收藏) https://www.grapecity.com.cn/resources/ 前言 | 问题背景 在操作Excel的场景中,通常会有一些针对Excel的批量操作,批量的意思一般有两种: 对批量的Excel文件进行操作。如导入多个Excel文件…...

JUC并发编程_Lock锁

JUC并发编程_Lock锁 1、Lock锁介绍2、主要方法3、与 synchronized 的区别4、Condition 使用示例 1、Lock锁介绍 Java中的 Lock 锁是 java.util.concurrent.locks 包下的一个接口,它提供了比 synchronized 关键字更灵活的锁定机制。 2、主要方法 lock()&#xff1a…...

Unity中的功能解释(数学位置相关和事件)

向量计算 Vector3.Slerp(起点坐标,终点坐标,t),可是从起点坐标以一个圆形轨迹到终点坐标,有那么多条轨迹,那怎么办 Vector3.Slerp 进行的是沿球面插值,因此并不是沿着严格的“圆形…...

ElementPlus---Timeline 时间线组件使用示例

介绍 使用ElementPlus时间线组件在后台首页实现通知公告列表展示&#xff0c;使用Vue3开发。 实现代码 Vue3代码 <el-timeline><el-timeline-itemstyle"max-width: 600px"v-for"(activity, index) in activities":key"index":times…...

推荐4款2024年大家都在用的高质量翻译器。

翻译器在我们的生活中有着很重要的作用&#xff0c;不管是我们在学习还是工作&#xff0c;生活娱乐&#xff0c;出国旅游等场合都会派上用场&#xff0c;它是我们解决沟通的障碍&#xff0c;提高阅读效率的好帮手。我自己使用的翻译器有很多&#xff0c;可以给大家列举几款特别…...

Mybatis 返回 Map 对象

一、场景介绍 假设有如下一张学生表&#xff1a; CREATE TABLE student (id int NOT NULL AUTO_INCREMENT COMMENT 主键,name varchar(100) NOT NULL COMMENT 姓名,gender varchar(10) NOT NULL COMMENT 性别,grade int NOT NULL COMMENT 年级,PRIMARY KEY (id) ) ENGINEInnoD…...

Vue3(三)路由基本使用、工作模式(history,hash)、query传参和param传参、props配置、编程式路由导航

文章目录 一、路由的基本使用二、路由器的工作模式三、RouterLink中to的两种写法四、嵌套路由五、路由传参1. query传参2. params传参 六、路由的propos配置七、编程式路由导航 一、路由的基本使用 安装&#xff1a;npm i vue-router 在src/pages文件下&#xff0c;创建三个路…...

TypeScript概念讲解

简单来说&#xff0c;TypeScript 是 JavaScript 的一个超集&#xff0c;支持 ECMAScript 6 标准&#xff1b; TypeScript 由微软开发的自由和开源的编程语言&#xff1b; TypeScript 设计目标是开发大型应用&#xff0c;它可以编译成纯 JavaScript&#xff0c;编译出来的 Jav…...

C++初阶-list的底层

目录 1.std::list实现的所有代码 2.list的简单介绍 2.1实现list的类 2.2_list_iterator的实现 2.2.1_list_iterator实现的原因和好处 2.2.2_list_iterator实现 2.3_list_node的实现 2.3.1. 避免递归的模板依赖 2.3.2. 内存布局一致性 2.3.3. 类型安全的替代方案 2.3.…...

2024年赣州旅游投资集团社会招聘笔试真

2024年赣州旅游投资集团社会招聘笔试真 题 ( 满 分 1 0 0 分 时 间 1 2 0 分 钟 ) 一、单选题(每题只有一个正确答案,答错、不答或多答均不得分) 1.纪要的特点不包括()。 A.概括重点 B.指导传达 C. 客观纪实 D.有言必录 【答案】: D 2.1864年,()预言了电磁波的存在,并指出…...

现代密码学 | 椭圆曲线密码学—附py代码

Elliptic Curve Cryptography 椭圆曲线密码学&#xff08;ECC&#xff09;是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础&#xff0c;例如椭圆曲线数字签…...

让AI看见世界:MCP协议与服务器的工作原理

让AI看见世界&#xff1a;MCP协议与服务器的工作原理 MCP&#xff08;Model Context Protocol&#xff09;是一种创新的通信协议&#xff0c;旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天&#xff0c;MCP正成为连接AI与现实世界的重要桥梁。…...

浪潮交换机配置track检测实现高速公路收费网络主备切换NQA

浪潮交换机track配置 项目背景高速网络拓扑网络情况分析通信线路收费网络路由 收费汇聚交换机相应配置收费汇聚track配置 项目背景 在实施省内一条高速公路时遇到的需求&#xff0c;本次涉及的主要是收费汇聚交换机的配置&#xff0c;浪潮网络设备在高速项目很少&#xff0c;通…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

【JavaSE】多线程基础学习笔记

多线程基础 -线程相关概念 程序&#xff08;Program&#xff09; 是为完成特定任务、用某种语言编写的一组指令的集合简单的说:就是我们写的代码 进程 进程是指运行中的程序&#xff0c;比如我们使用QQ&#xff0c;就启动了一个进程&#xff0c;操作系统就会为该进程分配内存…...

Rust 开发环境搭建

环境搭建 1、开发工具RustRover 或者vs code 2、Cygwin64 安装 https://cygwin.com/install.html 在工具终端执行&#xff1a; rustup toolchain install stable-x86_64-pc-windows-gnu rustup default stable-x86_64-pc-windows-gnu ​ 2、Hello World fn main() { println…...

从面试角度回答Android中ContentProvider启动原理

Android中ContentProvider原理的面试角度解析&#xff0c;分为​​已启动​​和​​未启动​​两种场景&#xff1a; 一、ContentProvider已启动的情况 1. ​​核心流程​​ ​​触发条件​​&#xff1a;当其他组件&#xff08;如Activity、Service&#xff09;通过ContentR…...