C++语言GDAL批量裁剪多波段栅格图像:基于像元个数裁剪
本文介绍基于C++ 语言的GDAL
模块,按照给定的像元行数与列数,批量裁剪大量多波段栅格遥感影像文件,并将所得到的裁剪后新的多波段遥感影像文件保存在指定路径中的方法。
在之前的文章中,我们多次介绍了在不同平台,或基于不同代码语言,对栅格遥感影像加以裁剪、批量裁剪的方法,主要包括Python中ArcPy基于矢量范围批量裁剪大量栅格遥感影像(https://blog.csdn.net/zhebushibiaoshifu/article/details/128307676)、Google Earth Engine谷歌地球引擎GEE矢量数据裁剪栅格数据(https://blog.csdn.net/zhebushibiaoshifu/article/details/117390431)、基于ENVI实现栅格遥感影像按图层行列号与像元数量划定矩形研究区域并裁剪(https://blog.csdn.net/zhebushibiaoshifu/article/details/118978851)等;而本文,我们就介绍一下基于**C++**语言的GDAL
模块,实现批量裁剪需求的方法。
首先,来看一下本文的需求。现在有一个文件夹,如下图所示,其中具有多个.tiff
格式的多波段遥感影像文件(为了方便,我们这里文件夹内就只有2
个文件,但实际上一般我们批量处理的需求肯定远远大于这个数量)。
我们希望实现的,就是基于这个文件夹内每一景遥感影像,将其左上角100 * 100
像元的这一部分给裁剪下来(如下图所示),并分别保存为新的遥感影像文件(其中,新的文件名称就在原有文件名称后加一个_C
后缀即可),并存放在另一个指定的结果文件夹中。我们希望裁剪后的遥感影像,和原有的遥感影像对比起来,呈现如下图所示的情况。
本文所用代码如下。
#include <iostream>
#include <string>
#include <gdal/gdal.h>
#include <gdal/gdal_priv.h>
using namespace std;int main()
{GDALAllRegister();string inputFolder = "/home/cppGDAL/TIF/WFV1_2021_STB/test";string outputFolder = "/home/cppGDAL/TIF/WFV1_2021_STB_C";CPLStringList fileList;fileList = VSIReadDir(inputFolder.c_str());for (int i = 0; i < fileList.size(); i++){string inputImagePath = fileList[i];if (!EQUAL(CPLGetExtension(inputImagePath.c_str()), "tiff")){continue;}string full_path = inputFolder + "/" + inputImagePath;GDALDataset *poDataset = (GDALDataset *)GDALOpen(full_path.c_str(), GA_ReadOnly);int width = poDataset->GetRasterXSize();int height = poDataset->GetRasterYSize();int xOffset = 0;int yOffset = 0;int xSize = 100;int ySize = 100;cout << full_path;string outputImageName = (outputFolder + "/" + inputImagePath.substr(0, inputImagePath.size() - 5) + "_C.tiff");cout << outputImageName;GDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName("GTiff");GDALDataset *poOutputDataset = poDriver->Create(outputImageName.c_str(), xSize, ySize, 4, GDT_Float32, NULL);poOutputDataset->SetProjection(poDataset->GetProjectionRef());double adfGeoTransform[6];poDataset->GetGeoTransform(adfGeoTransform);// adfGeoTransform[1] = adfGeoTransform[1] / (width / xSize);// adfGeoTransform[5] = adfGeoTransform[5] / (height / ySize);poOutputDataset->SetGeoTransform(adfGeoTransform);for (int bandIndex = 1; bandIndex <= 4; bandIndex++){float *buffer = new float[xSize * ySize];GDALRasterBand *poBand = poDataset->GetRasterBand(bandIndex);GDALRasterBand *poOutputBand = poOutputDataset->GetRasterBand(bandIndex);poBand->RasterIO(GF_Read, xOffset, yOffset, xSize, ySize, buffer, xSize, ySize, GDT_Float32, 0, 0, NULL);poOutputBand->RasterIO(GF_Write, 0, 0, xSize, ySize, buffer, xSize, ySize, GDT_Float32, 0, 0, NULL);delete[] buffer;}GDALClose(poOutputDataset);GDALClose(poDataset);}GDALDestroyDriverManager();return 0;
}
我们来介绍一下上述代码的具体内容。
首先,我们需要通过GDALAllRegister();
,来注册所有的GDAL
驱动器。同时,我们定义了输入和输出文件夹路径——inputFolder
就是存储输入遥感影像(待裁剪的遥感影像)的文件夹路径,outputFolder
则是存储结果遥感影像的文件夹路径。
其次,我们通过CPLStringList fileList;
定义一个字符串列表,用于存储文件夹中的文件列表;并使用VSIReadDir
函数读取输入文件夹中的所有文件,并将结果存储在fileList
中。
接下来,我们使用循环迭代处理每个文件。首先,通过string inputImagePath = fileList[i];
获取当前文件的路径;如果文件的扩展名不是tiff
,则跳过该文件。接下来,对于文件的扩展名是tiff
的,我们构建完整的输入文件路径,并使用GDALOpen
函数打开输入文件,返回一个GDALDataset
对象,存储在poDataset
中。
接下来,我们即可获取输入文件的宽度和高度,并定义裁剪区域的偏移量(左上角像元的位置)、宽度和高度。前面提到了,我这里就是需要在原本遥感影像的最左上角(所以偏移量均为0
),裁剪下来100 * 100
像元的这一部分。其次,构建输出文件的路径,并使用GetGDALDriverManager()->GetDriverByName
函数获取GTiff
驱动器对象,存储在poDriver
中。随后,我们使用poDriver->Create
函数创建输出文件,返回一个GDALDataset
对象,存储在poOutputDataset
中。
接下来这个部分需要稍微注意一下。首先,我们使用poOutputDataset->SetProjection
设置输出文件的投影信息,即与输入文件相同的投影;其次,使用poDataset->GetGeoTransform
获取输入文件的地理变换参数,存储在adfGeoTransform
数组中。由于在我这里,裁剪后遥感影像的像元大小(即单个像元的长度与宽度)没有改变,且裁剪前后栅格遥感影像的左上角像元没有发生变化,所以新的栅格遥感影像的地理变换参数和老的栅格遥感影像比起来,无需有任何改变;但是如果大家的裁剪需求不是这样的话(比如像元大小发生变化了,或者是裁剪并不是从左上角像元开始的),那么就需要调整这6
个地理变换参数——至于怎么变,这就比较复杂了,我也还没完全搞清楚,大家就结合自己的实际需求,到GDAL
官网查阅即可。最后,我们使用poOutputDataset->SetGeoTransform
,设置输出文件的地理变换参数,在我这里就是与输入文件完全相同的地理变换参数。
代码最后,我们使用循环迭代处理每个波段(我这里每一个遥感影像都是共4
个波段)。首先,创建一个大小为xSize * ySize
的浮点型缓冲区,并使用poBand->RasterIO
从输入文件中读取对应波段的像元数据到缓冲区;接下来,使用poOutputBand->RasterIO
将缓冲区中的数据写入到输出文件对应波段中。随后,即可释放缓冲区内存,并关闭输出文件和输入文件。
运行上述代码,我们即可在结果文件夹中看到已经裁剪好的遥感影像文件,且新的文件的文件名称也符合我们的要求;如下图所示。
至此,大功告成。
欢迎关注:疯狂学习GIS
相关文章:

C++语言GDAL批量裁剪多波段栅格图像:基于像元个数裁剪
本文介绍基于C 语言的GDAL模块,按照给定的像元行数与列数,批量裁剪大量多波段栅格遥感影像文件,并将所得到的裁剪后新的多波段遥感影像文件保存在指定路径中的方法。 在之前的文章中,我们多次介绍了在不同平台,或基于不…...

简单丝的tab切换栏(html/CSS)
#html <!DOCTYPE html> <html lang"en" > <head><meta charset"UTF-8"><title>CSS实现左右滑动选项卡效果</title><link rel"stylesheet" href"https://cdnjs.cloudflare.com/ajax/libs/meyer-res…...

LabVIEW开发带式谱感测技术
LabVIEW开发带式谱感测技术 如今,通过无线网络传输的数据量正在迅速增加,并导致频谱稀缺。超过数十亿的无线设备将被连接起来,并需要互联网接入。因此,无线电频谱管理方案的效率不足以授予对所有设备的访问权限。在频谱分配中&am…...

认识柔性数组
在C99中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员 限制条件是: 结构体中最后一个成员未知大小的数组 1.柔性数组的形式 那么我们怎样写一个柔性数组呢 typedef struct st_type {int i;int a[0];//柔性数组成员 }ty…...

熔断、限流、降级 —— SpringCloud Alibaba Sentinel
Sentinel 简介 Sentinel 是阿里中间件团队开源的,面向分布式服务架构的高可用流量防护组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来帮助开发者保障微服务的稳定性 Sentinel 提供了两个服务组件…...
python经典百题之反向输出数字
题目:输入一个整数,并将其反转后输出。 程序分析 我们需要对输入的整数进行反转,即将整数的数字反向排列。 方法1:使用字符串反转 解题思路 将整数转换为字符串,然后对字符串进行反转。 代码实现 def reverse_integer_usin…...
复习Day08:哈希表part01:242.有效的字母异位词、349. 两个数组的交集、1. 两数之和、160. 相交链表
之前的blog:https://blog.csdn.net/weixin_43303286/article/details/131765317 我用的方法是在leetcode再过一遍例题,明显会的就复制粘贴,之前没写出来就重写,然后从拓展题目中找题目来写。辅以Labuladong的文章看。然后刷题不用…...

用 Pytest+Allure 生成漂亮的 HTML 图形化测试报告
本篇文章将介绍如何使用开源的测试报告生成框架 Allure 生成规范、格式统一、美观的测试报告。 通过这篇文章的介绍,你将能够: 将 Allure 与 Pytest 测试框架相结合; 如何定制化测试报告内容 执行测试之后,生成 Allure 格式的测…...

Python字符串索引解码乱码谜题
输入数行“数字字母”字符组成的乱码字符串,根据谜题规则解码出乱码字符串中隐藏的单词信息。 (本笔记适合熟悉python字符串索引操作的 coder 翻阅) 【学习的细节是欢悦的历程】 Python 官网:https://www.python.org/ Free:大咖免费“圣经”…...

协议栈——收发数据(拼接网络包,自动重发,滑动窗口机制)
目录 协议栈何时发送数据~ 数据长度 IP模块的分片功能 发送频率 网络包序号~利用syn拼接网络包ack确认网络包完整 确定偏移量 服务器ack确定收到数据总长度 序号作用 双端告知各自序号 协议栈自动重发机制 大致流程 ack等待时间如何调整 是…...

传输层协议——TCP、UDP
目录 1、UDP 协议(用户数据报协议) 协议特点 报文首部格式 2、TCP 协议(传输控制协议) 协议特点 报文首部格式 TCP连接建立时的三次握手 TCP拆除连接的四次挥手 TCP的流量控制 TCP的拥塞控制 3、传输层端口号 三类端口…...
优化您的Spring应用程序:缓存注解的精要指南
优化您的Spring应用程序:缓存注解的精要指南 前言详细说明1. Cacheable:2. CacheEvict:3. CachePut:4. Caching:5. CacheConfig: 项目中的实现前提使用 前言 当我们构建和运行Spring应用程序时,…...
Java之原子性问题的解决
2. 原子性 2.1 volatile-问题 代码分析 : package com.itheima.myvolatile; public class Demo {public static void main(String[] args) {MyThread1 t1 new MyThread1();t1.setName("小路同学");t1.start(); MyThread2 t2 new MyThread2();t2.setName(&q…...

实时目标检测:基于YOLOv3和OpenCV的摄像头应用
一、前言 随着人工智能和计算机视觉技术的不断发展,目标检测成为了智能监控、自动驾驶、机器人等领域的关键技术之一。实时目标检测更是对系统的反应速度和准确度提出了更高的要求。本文介绍使用OpenCV和YOLOv3实现实时目标检测的方法,演示如何使用OpenCV调用YOLOv3模型进行…...

【软考】4.2 关系代数
《 关系代数 》 表和表之间的逻辑运算 笛卡尔积:S1 x S2 投影:π;选择某一列(属性);一个关系R的投影操作结果也是一个关系,记作Πa,它由从关系R中选出的A列元素构成;选择…...

STM32F4学习笔记读取芯片UID和MAC地址
一、简介 在嵌入式设备开发过程中有时会需要为设备设置唯一的ID用以标识设备唯一,比如要求同一总线上的所有设备ID不能重复,要求设备具体唯一的MAC地址等等。每个STM32微控制器都自带一个96位的唯一ID,这个ID在任何情况下都是唯一且不允许修…...
webpack优化策略
这三点是webpack优化策略的一部分,具体解释如下: 优化正则匹配(Test):在webpack的配置中,test属性是一个正则表达式,用于匹配需要应用该loader的文件的扩展名。在您提供的代码中,te…...

讲讲项目里的仪表盘编辑器(三)布局组件
布局容器处理 看完前面两章的讲解,我们对仪表盘系统有了一个大概的理解。接着我们讲讲更深入的应用。 上文讲解的编辑器只是局限于平铺的组件集。而在编辑器中,还会有一种组件是布局容器。它允许其他组件拖拽进入在里面形成自己的一套布局。典型的有分页…...
Linux- 后台运行符、nohup、disown
& &在Unix-like的操作系统(如Linux和macOS)的shell中,特别是在Bash这样的shell中,经常用作后台运行符号。让我们深入了解一下其功能和用法。 &作为后台运行符号: 基本用法: 当我们在一个命令或者一组命令…...

开发过程教学——交友小程序
交友小程序 1. 我的基本信息2. 我的人脉2.1 我的关注2.2 我的粉丝 3. 我的视频4. 我的相册 特别注意:由于小程序分包限制2M以内,所以要注意图片和视频的处理。 1. 我的基本信息 数据库表: 我的基本信息我的登录退出记录我的登录状态&#x…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

【入坑系列】TiDB 强制索引在不同库下不生效问题
文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

遍历 Map 类型集合的方法汇总
1 方法一 先用方法 keySet() 获取集合中的所有键。再通过 gey(key) 方法用对应键获取值 import java.util.HashMap; import java.util.Set;public class Test {public static void main(String[] args) {HashMap hashMap new HashMap();hashMap.put("语文",99);has…...
《Playwright:微软的自动化测试工具详解》
Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...
1688商品列表API与其他数据源的对接思路
将1688商品列表API与其他数据源对接时,需结合业务场景设计数据流转链路,重点关注数据格式兼容性、接口调用频率控制及数据一致性维护。以下是具体对接思路及关键技术点: 一、核心对接场景与目标 商品数据同步 场景:将1688商品信息…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...

Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

基于SpringBoot在线拍卖系统的设计和实现
摘 要 随着社会的发展,社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统,主要的模块包括管理员;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

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是一个异步的、基于事件驱动的网络应用框架,用于…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...