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

C++ GDAL提取多时相遥感影像中像素随时间变化的数值数组

本文介绍基于C++语言GDAL库,批量读取大量栅格遥感影像文件,并生成各像元数值的时间序列数组的方法。

  首先,我们来明确一下本文所需实现的需求。现在有一个文件夹,其中包含了很多不同格式的文件,如下图所示。

  其中,我们首先需要遍历这一文件夹,遴选出其中所有类型为.bmp格式的栅格遥感影像文件(一共有6个),并分别读取文件(已知这些遥感影像的行数、列数都是一致的);随后,将不同遥感影像同一个位置的像素的数值进行分别读取,并存储在一个数组中。例如,最终我们生成的第一个数组,其中共有6个元素,分别就是上图所示文件夹中6景遥感影像各自(0,0)位置的像元数值;生成的第二个数组,其中也是6个元素,分别就是6景遥感影像各自(1,0)位置的像元数值,以此类推。其中,显然我们得到的数组个数,就是遥感影像像元的个数。此外,这里6景遥感影像的排序,是按照文件名称的升序来进行的。

  明确了具体需求,接下来就可以开始代码的实践。其中,本文分为两部分,第一部分为代码的分段讲解,第二部分为完整代码。

  此外,本文是基于GDAL库来实现栅格数据读取的;具体GDAL库的配置方法大家可以参考文章在Visual Studio中部署GDAL库的C++版本(包括SQLite、PROJ等依赖)。

1 代码分段介绍

1.1 代码准备

这一部分主要是代码的头文件命名空间与我们自行撰写的自定义函数get_need_file()的声明;具体代码如下所示。

#include <iostream>
#include <vector>
#include <io.h>
#include "gdal_priv.h"using namespace std;void get_need_file(string path, vector<string>& file, string ext);

  其中,由于我们在接下来的代码中需要用到容器vector这一数据类型,因此首先需要添加#include <vector>;同时,我们在接下来的代码中需要用到头文件io.h中的部分函数(主要都是一些与计算机系统、文件管理相关的函数),因此需要添加#include <io.h>;此外,我们是基于GDAL库来实现栅格数据读取的,因此需要添加#include "gdal_priv.h"

  接下来,这里声明了一个自定义函数get_need_file(),具体我们在本文1.2部分介绍。

1.2 栅格文件筛选

 由于我这里几乎将全部的代码都放在了主函数中,因此这一部分就先介绍代码main()函数的第一部分,亦即栅格文件的遴选部分;具体代码如下所示。

int main() {string file_path = R"(E:\02_Project\02_ChlorophyllProduce\01_Data\00_Test)";vector<string> my_file;string need_extension = ".bmp";get_need_file(file_path, my_file, need_extension);int file_size = my_file.size();if (file_size == 0){cout << "No file can be found!" << endl;}else{cout << "Find " << file_size << " file(s).\n" << endl;}

 这一部分主要就是做好调用自定义函数get_need_file()的变量准备,并调用get_need_file()函数,得到指定文件夹下的栅格文件;随后,将栅格文件的筛选结果进行输出。这一部分的具体代码介绍,大家查看文章C++遴选出特定类型的文件或文件名符合要求的文件即可,这里就不再赘述。

1.3 栅格文件读取

 这一部分主要是基于GDAL库,循环读取前述文件夹中的每一个栅格遥感影像文件。

	int nXSize, nYSize;float** pafScanline = new float* [file_size];int pic_index = 1;for (auto x : my_file){GDALDataset* poDataset;GDALAllRegister();CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");poDataset = (GDALDataset*)GDALOpen(x.c_str(), GA_ReadOnly);if (poDataset == NULL){cout << "Open File " << x << " Error!" << endl;}else{cout << "Open File " << x << " Success!" << endl;}GDALRasterBand* poBand;poBand = poDataset->GetRasterBand(1);nXSize = poBand->GetXSize();nYSize = poBand->GetYSize();cout << nXSize << "," << nYSize << "\n" << endl;pafScanline[pic_index - 1] = new float[nXSize * nYSize];poBand->RasterIO(GF_Read, 0, 0, nXSize, nYSize, pafScanline[pic_index - 1], nXSize, nYSize, GDT_Float32, 0, 0);pic_index ++;}

 其中,nXSizenYSize分别表示栅格遥感影像的列数与行数,pafScanline是我们读取栅格遥感影像文件所需的变量,之后读取好的遥感影像数据就会存放在这里;由于我们有多个栅格文件需要读取,因此通过for循环来实现批量读取的操作,并通过pic_index这个变量作为每一次读取文件的计数。

  在这里,float** pafScanline = new float* [file_size];这句代码表示我们将pafScanline作为一个指向指针的指针的数组;在后期读取遥感影像数据后,pafScanline[0]pafScanline[1]一直到pafScanline[5],这6个数值同样分别是指针,分别指向存储6景遥感影像数据的地址。这里我们通过new实现对pafScanline内存的动态分配,因为我们在获取栅格遥感影像的景数(也就是文件夹中栅格遥感影像文件的个数)之前,也不知道具体需要给pafScanline这一变量分配多少的内存。此外,在for循环中,我们还对pafScanline[0]pafScanline[1]一直到pafScanline[5]同样进行了动态内存分配,因为我们在获取每一景栅格遥感影像的行数与列数之前,同样是不知道需要给pafScanline[x]6个数组变量分配多少内存的。

  随后,for循环中的其他部分,就是GDAL库读取遥感影像的基本代码。读取第一景遥感影像数据后,我们将数据保存至pafScanline[0],并随后进行第二次循环,读取第二景遥感影像数据,并将其数据保存至pafScanline[1]中,随后再次循环;以此类推,直至读取6景遥感影像完毕。

  如果大家只是需要实现C++批量读取栅格遥感影像数据,那么以上操作就已经实现了大家的需求。其中,显然pafScanline[0]就是第一景遥感影像数据,pafScanline[1]就是第二景遥感影像数据,pafScanline[2]就是第三景遥感影像数据,以此类推。

1.4 像元时间序列数组生成

这一部分则是基于以上获取的各景遥感影像数据读取结果,进行每一个像元数值的时间序列数组生成。

	float** pixel_paf = new float* [nXSize * nYSize];for (int pixel_num = 0; pixel_num < nXSize * nYSize; pixel_num++){pixel_paf[pixel_num] = new float[file_size];for (int time_num = 0; time_num < file_size; time_num++){pixel_paf[pixel_num][time_num] = pafScanline[time_num][pixel_num];}}

  这一部分的代码思路其实也非常简单,就是通过两个for循环,将原本一共6的、每一个表示每一景遥感影像中全部数据的数组,转变为一共X的(X表示每一景遥感影像的像元总个数)、每一个表示每一个位置的像元在6景遥感影像中的各自数值的数组。

  在这里,由于同样的原因,我们对pixel_paf亦进行了内存的动态分配。

1.5 输出测试与代码收尾

 这一部分主要是输出一个我们刚刚配置好的像元数值时间序列数组,从而检查代码运行结果是否符合我们的要求;此外,由于前面我们对很多变量进行了动态内存分配,因此需要将其delete掉;同时,这里还可以对前面我们定义的指向指针的指针赋值为NULL,这样子其就不能再指向任何地址了,即彻底将其废除。

	for (int i = 0; i < file_size; i++){cout << pixel_paf[0][i] << "," << endl;}delete[] pafScanline;delete[] pixel_paf;pafScanline = NULL;pixel_paf = NULL;return 0;
}

至此,代码的主函数部分结束。

1.6 自定义函数

这一部分是我们的自定义函数get_need_file()

void get_need_file(string path, vector<string>& file, string ext)
{intptr_t file_handle = 0;struct _finddata_t file_info;string temp;if ((file_handle = _findfirst(temp.assign(path).append("/*" + ext).c_str(), &file_info)) != -1){do{file.push_back(temp.assign(path).append("/").append(file_info.name));} while (_findnext(file_handle, &file_info) == 0);_findclose(file_handle);}
}

如前所述,这一部分的具体代码介绍,大家查看文章C++遴选出特定类型的文件或文件名符合要求的文件即可,这里就不再赘述。

2 完整代码

本文所需用到的完整代码如下所示。

#include <iostream>
#include <vector>
#include <io.h>
#include "gdal_priv.h"using namespace std;void get_need_file(string path, vector<string>& file, string ext);int main() {string file_path = R"(E:\02_Project\02_ChlorophyllProduce\01_Data\00_Test)";vector<string> my_file;string need_extension = ".bmp";get_need_file(file_path, my_file, need_extension);int file_size = my_file.size();if (file_size == 0){cout << "No file can be found!" << endl;}else{cout << "Find " << file_size << " file(s).\n" << endl;}int nXSize, nYSize;float** pafScanline = new float* [file_size];int pic_index = 1;for (auto x : my_file){GDALDataset* poDataset;GDALAllRegister();CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");poDataset = (GDALDataset*)GDALOpen(x.c_str(), GA_ReadOnly);if (poDataset == NULL){cout << "Open File " << x << " Error!" << endl;}else{cout << "Open File " << x << " Success!" << endl;}GDALRasterBand* poBand;poBand = poDataset->GetRasterBand(1);nXSize = poBand->GetXSize();nYSize = poBand->GetYSize();cout << nXSize << "," << nYSize << "\n" << endl;pafScanline[pic_index - 1] = new float[nXSize * nYSize];poBand->RasterIO(GF_Read, 0, 0, nXSize, nYSize, pafScanline[pic_index - 1], nXSize, nYSize, GDT_Float32, 0, 0);pic_index ++;}float** pixel_paf = new float* [nXSize * nYSize];for (int pixel_num = 0; pixel_num < nXSize * nYSize; pixel_num++){pixel_paf[pixel_num] = new float[file_size];for (int time_num = 0; time_num < file_size; time_num++){pixel_paf[pixel_num][time_num] = pafScanline[time_num][pixel_num];}}for (int i = 0; i < file_size; i++){cout << pixel_paf[0][i] << "," << endl;}delete[] pafScanline;delete[] pixel_paf;pafScanline = NULL;pixel_paf = NULL;return 0;
}void get_need_file(string path, vector<string>& file, string ext)
{intptr_t file_handle = 0;struct _finddata_t file_info;string temp;if ((file_handle = _findfirst(temp.assign(path).append("/*" + ext).c_str(), &file_info)) != -1){do{file.push_back(temp.assign(path).append("/").append(file_info.name));} while (_findnext(file_handle, &file_info) == 0);_findclose(file_handle);}
}

当我们运行上述代码后,将会出现如下所示的界面。

  其中,会显示栅格遥感影像文件的筛选情况、具体文件名称及其各自的行号与列号;同时,最后一部分则是本文1.5部分提及的测试输出结果,其表示本文所用的6景遥感影像各自(0,0)位置处的像元数值。

  至此,大功告成。

参考链接: https://www.cnblogs.com/fkxxgis/p/18004549

相关文章:

C++ GDAL提取多时相遥感影像中像素随时间变化的数值数组

本文介绍基于C语言GDAL库&#xff0c;批量读取大量栅格遥感影像文件&#xff0c;并生成各像元数值的时间序列数组的方法。 首先&#xff0c;我们来明确一下本文所需实现的需求。现在有一个文件夹&#xff0c;其中包含了很多不同格式的文件&#xff0c;如下图所示。 其中&#x…...

免费-华为od-C卷-javascript-动态规划-贪心歌手.js

动态规划-贪心歌手 还有很多其他题&#xff0c;链接是github, 进去可以查看对应文件夹就行...

elementui 实现一个固定位置的Pagination(分页)组件

系列文章目录 一、elementui 导航菜单栏和Breadcrumb 面包屑关联 二、elementui 左侧导航菜单栏与main区域联动 三、elementui 中设置图片的高度并支持PC和手机自适应 四、 elementui 实现一个固定位置的Pagination&#xff08;分页&#xff09;组件 文章目录 系列文章目录…...

紧急备考全攻略,如何短期通过PMP考试?

今年身边有很多同事朋友都要考PMP&#xff0c;而我属于这些人里”第一个吃螃蟹“的人&#xff0c;一次拿下5A&#xff0c;下面分享一下我自己备考PMP的经验。 我是根据自己的学习计划复习的&#xff0c;不能说这些方法适合所有人&#xff0c;但对备考的伙伴们来说&#xff0c;…...

python开发poc,fofa爬虫批量化扫洞

学习使用python做到批量化的漏洞脚本 1.通过fofa搜索结果来采集脚本 2.批量化扫描漏洞 ---glassfish存在任意文件读取在默认48484端口&#xff0c;漏洞验证的poc为: "glassfish" && port"4848" && country"CN" http://loca…...

适用于 Windows 10 的 10 大免费数据恢复软件

数据丢失可能是一场噩梦&#xff0c;尤其是在涉及重要文件和文档时。无论是由于意外删除、系统崩溃还是病毒攻击&#xff0c;找到适合 Windows 10 的文件夹恢复软件都可以在恢复丢失的数据方面发挥重要作用。在本指南中&#xff0c;我们将探索适用于 Windows 10 用户的 10 大免…...

zabbix企业级监控平台

zabbix部署 安装源 重新创建纯净环境&#xff0c;利用base克隆一台虚拟机server1 给server1做快照&#xff0c;方便下次实验恢复使用 进入zabbix官网https://www.zabbix.com rpm -Uvh https://repo.zabbix.com/zabbix/5.0/rhel/7/x86_64/zabbix-release-5.0-1.el7.noarch.rpm …...

如何关闭WordPress的自动更新功能

Wordpress为什么自动更新 WordPress自动更新是为了提供更好的安全性和稳定性。 安全性&#xff1a;WordPress是一个广泛使用的内容管理系统&#xff0c;因此成为恶意攻击的目标。WordPress的自动更新功能确保你的网站及时获得最新的安全补丁和修复程序&#xff0c;以保护你的网…...

【分析 GClog 的吞吐量和停顿时间、heapdump 内存泄漏分析】

文章目录 &#x1f50a;博主介绍&#x1f964;本文内容GClog分析以优化吞吐量和停顿时间步骤1: 收集GClog步骤2: 分析GClog步骤3: 优化建议步骤4: 实施优化 Heapdump内存泄漏分析步骤1: 获取Heapdump步骤2: 分析Heapdump步骤3: 定位泄漏对象步骤4: 分析泄漏原因步骤5: 修复泄漏…...

[STL-list]介绍、与vector的对比、模拟实现的迭代器问题

一、list使用介绍 list的底层是带头双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向其前一个元素和后一个元素。与其他的序列式容器相比(array&#xff0c;vector&#xff0c;deque)&#xff0c;list通常在任意位置进行…...

代码随想录-035期-算法训练营【博客笔记汇总表】

ヾ(◍∇◍)&#xff89;&#xff9e;加油~ 目录 00、说明 01、刷题网址 02、每日打卡任务 03、博客打卡笔记 01、数组 02、链表 03、哈希表 04、字符串 05、双指针法 06、栈与队列 07、二叉树 08、回溯算法 09、贪心算法 10、动态规划 11、单调栈 12、图论 04…...

postgresql数据库|数据整合的好工具--Oracle-fdw的部署和使用

概述 Oracle_fdw 是一种postgresql外部表插件&#xff0c;可以读取到Oracle上面的数据。是一种非常方便且常见的pg与Oracle的同步数据的方法 Oracle_fdw 适用场景&#xff1a; Oracle_fdw 是一个开源的 Foreign Data Wrapper (FDW)&#xff0c;主要用于在 PostgreSQL 数据库中…...

让php开发更优雅-Laravel篇

前言 随着开发经验的增加&#xff0c;也伴随团队开发的积累&#xff0c;规范开发显得越来越重要&#xff0c;本文给大家提供一些laravel开发的进阶思路和经验&#xff0c;让大家开发更加统一规范&#xff0c;代码看起来更加优雅。 1.更多使用第三方库。团队开发的时候&#xf…...

自动化测试之httprunner框架hook函数实操

本篇介绍httprunner中hook函数的使用&#xff0c;以及通过编程能力实现建设自动化测试更全面的场景覆盖 前置&#xff1a; 互联网时代让我们更快的学习到什么是Httprunner 正文&#xff1a; 经过上文了解到这个框架怎么使用之后&#xff0c;我们开始来探讨一下我们为什么要用…...

物联网实战--入门篇之(七)嵌入式-MQTT

目录 一、MQTT简介 二、MQTT使用方法 三、MQTT驱动设计 四、代码解析 五、使用过程 六、总结 一、MQTT简介 MQTT因为其轻量、高效和稳定的特点&#xff0c;特别适合作为物联网系统的数据传输协议&#xff0c;已经成为物联网事实上的通信标准了。关于协议的具体内容看看这…...

跑模型——labelme的json文件转成yolo使用的txt文件(语义分割)

前言 将labelme多边形标注的json文件转换成yolo使用的txt文件 import os import json import numpy as np from tqdm import tqdm#实现函数 def json2txt(path_json, path_txt): # 可修改生成格式with open(path_json, r) as path_json:jsonx json.load(path_json)with open…...

一个项目仿京东商场代码

git clone http://git.itcast.cn/heimaqianduan/erabbit-uni-app-vue3-ts.git...

计算机网络——WEB服务器编程实验

实验目的 1. 处理一个 http 请求 2. 接收并解析 http 请求 3. 从服务器文件系统中获得被请求的文件 4. 创建一个包括被请求的文件的 http 响应信息 5. 直接发送该信息到客户端 具体内容 一、C 程序来实现 web 服务器功能。 二、用 HTML 语言编写两个 HTML文件&#xff0c;并…...

蓝桥杯算法题:最大比例

题目描述&#xff1a; X星球的某个大奖赛设了 M 级奖励。 每个级别的奖金是一个正整数。 并且&#xff0c;相邻的两个级别间的比例是个固定值。 也就是说&#xff1a;所有级别的奖金数构成了一个等比数列。 比如&#xff1a;16,24,36,54&#xff0c;其等比值为&#xff1a;3/2。…...

【堡垒机】堡垒机的介绍

目前&#xff0c;常用的堡垒机有收费和开源两类。 收费的有行云管家、纽盾堡垒机&#xff1b; 开源的有jumpserver&#xff1b; 这几种各有各的优缺点&#xff0c;如何选择&#xff0c;大家可以根据实际场景来判断 什么是堡垒机 堡垒机&#xff0c;即在一个特定的网络环境下&…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

在鸿蒙HarmonyOS 5中实现抖音风格的点赞功能

下面我将详细介绍如何使用HarmonyOS SDK在HarmonyOS 5中实现类似抖音的点赞功能&#xff0c;包括动画效果、数据同步和交互优化。 1. 基础点赞功能实现 1.1 创建数据模型 // VideoModel.ets export class VideoModel {id: string "";title: string ""…...

解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八

现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet&#xff0c;点击确认后如下提示 最终上报fail 解决方法 内核升级导致&#xff0c;需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

定时器任务——若依源码分析

分析util包下面的工具类schedule utils&#xff1a; ScheduleUtils 是若依中用于与 Quartz 框架交互的工具类&#xff0c;封装了定时任务的 创建、更新、暂停、删除等核心逻辑。 createScheduleJob createScheduleJob 用于将任务注册到 Quartz&#xff0c;先构建任务的 JobD…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

MySQL用户和授权

开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务&#xff1a; test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...