ENVI IDL:如何解析XML文件(以Landsat9-MTL.xml文件为例)

01 前言

我们原本是打算对Landsat9文件进行辐射定标,但是辐射定标的参数在MTL文件中,从文件中查看参数直接复制到IDL中固然可行,但是当我们对Landsat9文件进行批量辐射定标时,这种方法就将失效了。因此我们需要自动从MTL文件中读取相关参数,这里的相关参数实际上只包含两个参数(对于一个波段),一个是比例系数,一个是偏置量。

对于Landsat9,给出三种MTL形式:
在这里插入图片描述
这里我们只讨论txt文本文件和XML文件的解析和提取。

02 通过XML文件获取定标参数

需要使用到IDL的IDLffXMLDOMDocument类,以及类的方法getelementsbytagname,getfirstchild,GetNodeValue

getelementsbytagname方法通过指定标签名得到满足要求的所有标签(类似列表形式返回:IDLffXMLDOMNodeList);
getfirstchild获取节点的第一个子节点;
GetNodeValue获取节点的值;

由于getelementsbytagname方法获取返回的值是一个类似列表的形式,当我们指定的标签名在XML文件中唯一时,那么实际上列表元素仅有一个元素,需要通过.item(0)取出第一个元素(其依旧是一个对象)。

由于我们的定标参数类似下方:
在这里插入图片描述

但是需要注意,在另外一个标签也有相同节点名称:

在这里插入图片描述

上面有两个辐射定标的参数,第一个是Level2级别的辐射定标,最终获取的是地表反射率或者地表温度(我们使用这个);而第二个是用于级别 1(L1)的辐射定标,即将传感器捕获的原始数字数据转换为辐射亮度值。因此,我们需要进行两次getelementsbytagname方法,第一次是获取到节点LEVEL2_SURFACE_REFLECTANCE_PARAMETERS,再用一次该方法从该节点下检索各个满足要求的子节点(各个波段的比例系数和偏置量节点)。

接着从获取的指定子节点中得到所有值。

所以我们的代码应该这么写:

pro L9_C2_calibration
    ; 准备
    xml_path = 'D:\Objects\JuniorFallTerm\IDLProgram\Experiments\ExperimentalData\Week8\LC09_L2SP_130039_20220311_20220314_02_T1_MTL.xml'
    xml = IDLffXMLDOMDocument(filename=xml_path)
    
    ; 获取level2
    level2 = xml.getelementsbytagname('LEVEL2_SURFACE_REFLECTANCE_PARAMETERS')
    level2 = level2.item(0)
    b1 = level2.getelementsbytagname('REFLECTANCE_MULT_BAND_1')
    b1 = b1.item(0)
    print, double((b1.getfirstchild()).getnodevalue())
    
    ; 销毁对象
    obj_destroy, b1
    obj_destroy, level2
    obj_destroy, xml
end

输出结果:

在这里插入图片描述

(PS:说实话,IDL的XML对象真的不好用,太底层了,不如python,但是好处就是你可以更自由的自己写一些高级函数进行封装得到自己想要的方法)

封装了一下,函数如下:

;+
;   函数用途:
;       用于获取指定路径节点的值
;   函数参数:
;       xml_path: xml文件的路径
;       tags_name: 各个节点的名称(数组形式), 按父-子顺序排列
;-
function xml_get_value, xml_path, tags_name
    xml = idlffxmldomdocument(filename=xml_path)  ; 实例化一个XML对象
    
    cur_tag = xml
    foreach tag_name, tags_name do begin
        cur_tag = cur_tag.getelementsbytagname(tag_name)
        cur_tag = cur_tag.item(0)
    endforeach
    
    return, (cur_tag.getfirstchild()).getnodevalue()
end

如果你的节点相对路径如下:

LEVEL2_SURFACE_REFLECTANCE_PARAMETERS\REFLECTANCE_MAXIMUM_BAND_1
即:
在这里插入图片描述
那么获取值如下:

a = xml_get_value(xml_path, ['LEVEL2_SURFACE_REFLECTANCE_PARAMETERS', 'REFLECTANCE_MULT_BAND_1'])
print, a

在这里插入图片描述

但是需要注意,我并没有设置任何错误机制,如果你的路径错误或者不正确等问题会导致返回值为NULL甚至直接报错;另外需要注意,我这里假定所有节点在其父节点中唯一,也就是不考虑父节点下存在多个相同名称的子节点。另外确保你的相对路径唯一,如果你仅仅传入[REFLECTANCE_MAXIMUM_BAND_1]而非上述形式,那么通过前文知,多个标签Tag下存在该节点名称,那么函数会自动取第一个匹配的值。

03 通过文本文件获取定标参数

这就是通过字符串截取等方式去取值,这里就是拿各种字符串操作函数来回折腾,总体思路还是前面如此。这里给出代码:

    ; 准备
    txt_path = 'D:\Objects\JuniorFallTerm\IDLProgram\Experiments\ExperimentalData\Week8\LC09_L2SP_130039_20220311_20220314_02_T1_MTL.txt'
    
    openr, 1, txt_path
    txt_content = strarr(file_lines(txt_path))
    readf, 1, txt_content
    level2_pos = where(strmatch(txt_content, '*LEVEL2_SURFACE_REFLECTANCE_PARAMETERS*'))
    calibration_content = txt_content[level2_pos[0]:level2_pos[1]]
    band_sc_pos = where(strmatch(calibration_content, '*REFLECTANCE_MULT_BAND_1*'))
    band_sc = (strsplit(calibration_content[band_sc_pos], '=', /extract))[-1]
    print, band_sc
    free_lun, 1

运行结果如下:

在这里插入图片描述
在这里插入图片描述

注意,上述两种方法得到的结果均为字符串,需要转化为double等数值类型。

当然,其实还有其他方法,例如在IDL中调用python模块(XML内置模块),前提是你安装python解释器。这里也贴出代码:

ET = python.import('xml.etree.ElementTree')
tree = ET.parse(xml_path)
root = tree.getroot()
finds = root.find('./LEVEL2_SURFACE_REFLECTANCE_PARAMETERS/REFLECTANCE_MULT_BAND_1')
print, finds.text

输出结果:

在这里插入图片描述

最后贴一个对Landsat9各个波段辐射定标的完整代码(取定标参数使用方法1):

; @Author	: ChaoQiezi
; @Time		: 20231111-上午10:24:06
; @Email	: chaoqiezi.one@qq.com

; 该程序用于 对Landsat9 C2(第二版次算法)的一级产品进行辐射定标并输出为TIFF文件

;+
;   函数用途:
;       用于获取指定路径节点的值
;   函数参数:
;       xml_path: xml文件的路径
;       tags_name: 各个节点的名称(数组形式), 按父-子顺序排列
;-
function xml_get_value, xml_path, tags_name, double=double
    xml = idlffxmldomdocument(filename=xml_path)  ; 实例化一个XML对象
    
    cur_tag = xml
    foreach tag_name, tags_name do begin
        cur_tag = cur_tag.getelementsbytagname(tag_name)
        cur_tag = cur_tag.item(0)
    endforeach
    
    value = (cur_tag.getfirstchild()).getnodevalue()
    if keyword_set(double) then return, double(value)
    
    return, value
end

pro L9_C2_calibration
    ; 准备
    in_dir = 'D:\Objects\JuniorFallTerm\IDLProgram\Experiments\ExperimentalData\Week8\'
    out_dir = in_dir + 'out_me\'
    if ~file_test(out_dir, /directory) then file_mkdir, out_dir
    xml_path = in_dir + 'LC09_L2SP_130039_20220311_20220314_02_T1_MTL.xml'
    level2_name = 'LEVEL2_SURFACE_REFLECTANCE_PARAMETERS'
    mult_name = 'REFLECTANCE_MULT_BAND_'
    add_name = 'REFLECTANCE_ADD_BAND_'
    img_wildcard = '*T1_SR_B'
    
    for band_ix = 1, 7 do begin
        cur_mult_name = mult_name + strtrim(band_ix, 1)
        cur_add_name = add_name + strtrim(band_ix, 1)
        cur_img_name = img_wildcard + strtrim(band_ix, 1) + '.tif'
        scale = xml_get_value(xml_path, [level2_name, cur_mult_name], /double)
        add = xml_get_value(xml_path, [level2_name, cur_add_name], /double)
        
        ; 读取影像文件和定标
        cur_img_path = (file_search(in_dir+cur_img_name))[0]
        cur_img = double(read_tiff(cur_img_path, geotiff=geo_info, dot_range=range))
        cur_img[where(cur_img eq 0.0, /null)] = !values.F_NAN
        cur_img = cur_img * scale + add
        
        ; 输出
        cur_out_path = out_dir + file_basename(cur_img_path)
        write_tiff, cur_out_path, cur_img, geotiff=geo_info, /double
    endfor    
end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/133017.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

一个轻量级 Java 权限认证框架——Sa-Token

一、框架介绍 Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证、权限认证、单点登录、OAuth2.0、分布式Session会话、微服务网关鉴权 等一系列权限相关问题。 官网文档: https://sa-token.cc/doc.html 二、Spring Boot 集成Sa-Token 2.1、…

keil仿真错误:*** error 65: access violation at 0x40021000 : no ‘write‘ permission

按下图打开: 进行修改: 我用的芯片是:STM32F103C8T6 开始仿真: 成功解决不能仿真问题

mongodb导出聚合查询的数据

❗️❗️❗️在正文之前先要讲一个坑,就是mongoexport这个命令工具不支持导出聚合查询的数据,比如通过某某字段来分组 我查了一天关于mongoexport怎么来导出聚合查询的结果集,最终还是gpt给了我答案 😭 既然mongoexport不支持&…

1.微服务与SpringCloud

微服务和SpringCloud 文章目录 微服务和SpringCloud1.什么是微服务2.SpringCloud3. 微服务 VS SpringCloud4. SpringCloud 组件5.参考文档6.版本要求 1.什么是微服务 微服务是将一个大型的、单一的应用程序拆分成多个小型服务,每个服务实现特定的业务功能&#xff…

redis主从复制+哨兵

1.主从复制 redis配置文件redis.conf master机器:IP 192.168.1.5 ,端口 6379 设置配置参数 daemonize yes #bind 127.0.0.1 -::1 protected-mode no port 6379 dbfilename "dump.rdb" dir "/root/redis/my_redis_conf/dumpdir" l…

leetcode刷题日记:110. Balanced Binary Tree(平衡二叉树)

题目给了我们一个二叉树要让我们来判断这一个二叉树是不是平衡二叉树。 要想判断一棵树是不是平衡二叉树,我们得首先知道平衡二叉树的定义是什么,平衡二叉树指的是这样的树它的左子树的高度与右子树高度的差的绝对值不能超过1,而且它的左子树…

酷柚易汛ERP-客户管理操作指南

1、应用场景 对客户信息进行管理,可新增客户、设置客户等级、联系人信息、银行账户和销售人员等信息,方便开单时自动匹配销售信息。 2、主要操作 2.1 新增客户 打开【资料】-【客户管理】,点击【新增】。 在页面输入客户信息、联系人地址…

Servlet作业小练习

一.题目 利用JavaBean实现用户类,包含姓名、性别、爱好,爱好需要用多选框 实现表单1进行获取数据,表单2显示获取结果。 利用Servlet实现逻辑代码 二.实现效果 三.具体实现 1.User实体类 package com.hjj.pojo;/*** author:嘉佳 Date:20…

Auto-Encoder学习笔记

写在前面 本篇博客是本人在学习李宏毅老师的《机器学习》课程中的Auto-Encoder时,记录的相关笔记,由于只记录了我认为相对重要的部分,所以可能有未记录的部分。博客中的图片来自于教学视频中的截图,视频资源地址为:传…

【面试经典150 | 位运算】位1的个数

文章目录 写在前面Tag题目来源题目解读解题思路方法一:循环检查二进制位方法二:位运算优化方法三:__builtin_popcount() 写在最后 写在前面 本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更…

基于SSM的汽车租赁系统业务管理子系统设计实现

末尾获取源码 开发语言:Java Java开发工具:JDK1.8 后端框架:SSM 前端:Vue 数据库:MySQL5.7和Navicat管理工具结合 服务器:Tomcat8.5 开发软件:IDEA / Eclipse 是否Maven项目:是 目录…

SQL必知会(二)-SQL查询篇(7)-使用函数处理数据

第8课、使用函数处理数据 表8-1 DBMS 函数的差异 函数语法提取字符串的组成DB2、Oracle、PostgreSQL 和 SQLite 使用 SUBSTR();MariaDB、Mysql 和 SQL Server 使用 SUBSTRING()数据类型转换Oracle 使用多个函数,每种类型的转换有一个函数;D…

在ubuntu sudo apt-get update 更新报错

sudo apt-get update 更新报错 解决办法: 用你自己的key 根据上图自己找 sudo gpg --keyserver keyserver.ubuntu.com --recv-keys **********运行完成有一个ok 见下图 运行命令,中间的还是上面的key复制下来即可 sudo gpg --export --armor **********…

开源跨平台绘图软件draw.io Mac/Win免费下载:让创意无限飞

你是否曾经遇到过在创作时,因为缺乏合适的绘图工具而无法充分表达你的想法?或者在团队项目中,因为沟通障碍而无法有效地进行视觉呈现?现在,让我们一起探索一个全新的开源跨平台绘图软件 - draw.io。 draw.io是一款完全…

logistic回归 目的、方程、损失函数

logistic回归多用于二分类问题。 文章目录 目的:给出x,当x满足条件时,y1的概率是多少。方程: y ^ σ ( ω T x b ) \hat y \sigma(\omega^Txb) y^​σ(ωTxb)损失函数: J ( ω , b ) 1 m ∑ i 1 m L ( y ^ ( i ) …

本地编译安装 Minkowski Engine 报错 Cuda 版本 与 Pytorch 版本不匹配

编译 Cuda 版本 C 插件 Cuda 版本 与 Pytorch 版本不匹配解决方案 报错详情环境报错分析 报错详情 RuntimeError: The detected CUDA version (12.2) mismatches the version that was used to compile PyTorch (11.8). Please make sure to use the same CUDA versions.环境 …

环境变量小节

这是写的第二篇环境变量博客,写了一年多了,第一次出现把自己博客删了的情况,不知道为什么明明发表了,然后就把草稿箱和回收站的删了,结果晚上发现没发表,回收站删除是无法找回的,以后还是要慎重…

git基础知识

1.git的必要配置 所有的配置文件,其实都保存在本地! 查看所有配置 git config -l 即把 系统配置(system)和当前用户(global)配置都 列出来 以直接编辑配置文件,通过命令设置后会响应到这里。 注意: 如果…

传统测试将被取代?AI测试现状及发展之思

近年来,我一直关注AI相关的测试,并积极参与多个全国性测试社区和社群。在这些社区中,我与不同公司和领域的测试专家交流探讨AI测试相关话题,包括业界顶尖公司的专家和国内知名测试学者。我也参加了多个大会,聆听了许多…

B087-人力资源项目-文件上传课程分类

目录 背景控制台操作开通OSS服务创建存储空间 项目工程准备概述新建文件管理模块把文件上传到OSS的三种方案 通过官方文档完成demo上传官方文档找JavaSDK文件上传思路代码 背景 为什么要交给第三方文件管理服务管理? 最传统的的文件管理方案是把文件存储到项目中本…