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…...
uHabits习惯追踪应用完整指南:从入门到精通的5个实用技巧
uHabits习惯追踪应用完整指南:从入门到精通的5个实用技巧 【免费下载链接】uhabits Loop Habit Tracker, a mobile app for creating and maintaining long-term positive habits 项目地址: https://gitcode.com/gh_mirrors/uh/uhabits uHabits习惯追踪应用是…...
如何快速解决Funannotate数据库安装失败:终极完整指南
如何快速解决Funannotate数据库安装失败:终极完整指南 【免费下载链接】funannotate Eukaryotic Genome Annotation Pipeline 项目地址: https://gitcode.com/gh_mirrors/fu/funannotate Funannotate作为一款强大的真核生物基因组注释流程工具,其…...
别再死记硬背截止、放大、饱和了!用Arduino+面包板,5分钟直观理解NPN/PNP三极管
用Arduino实验破解三极管的三大工作状态之谜 记得第一次翻开电子学教材看到三极管章节时,那些密密麻麻的曲线图和公式让我头皮发麻。"截止区"、"放大区"、"饱和区"——这些抽象概念就像天书一样难以理解。直到有一天,我拿…...
终极指南:3分钟学会在Windows电脑上安装安卓应用
终极指南:3分钟学会在Windows电脑上安装安卓应用 【免费下载链接】APK-Installer An Android Application Installer for Windows 项目地址: https://gitcode.com/GitHub_Trending/ap/APK-Installer 你是否曾经想过在Windows电脑上直接运行手机应用ÿ…...
从零手搓CLAHE算法:用Python实现图像去雾,并与OpenCV的cv2.createCLAHE()掰掰手腕
从零实现CLAHE算法:Python实战图像去雾与OpenCV性能对决 当一张雾霾笼罩的风景照出现在眼前时,我们往往会感到遗憾——那些本应清晰的细节被一层灰蒙蒙的雾气所掩盖。传统直方图均衡化虽然能提升对比度,但往往会过度放大噪声,让图…...
MTKClient终极指南:免费解锁联发科设备的完整刷机解决方案
MTKClient终极指南:免费解锁联发科设备的完整刷机解决方案 【免费下载链接】mtkclient MTK reverse engineering and flash tool 项目地址: https://gitcode.com/gh_mirrors/mt/mtkclient MTKClient是一款专为联发科(MediaTek)芯片设备…...
从零构建开源语音AI交互中枢:EchoKit Server部署与调优指南
1. 项目概述:构建你自己的语音AI交互中枢 如果你对智能音箱、语音助手这类设备感兴趣,但又觉得市面上的产品要么功能封闭,要么隐私堪忧,那么今天聊的这个项目——EchoKit Server,可能会让你眼前一亮。简单来说&#x…...
【SITS 2026 K8s for ML合规框架】:通过CNCF AI WG审核的3层资源隔离模型(含YAML模板+准入控制器配置)
更多请点击: https://intelliparadigm.com 第一章:AI原生Kubernetes编排:SITS 2026 K8s for ML工作负载 SITS 2026 引入了专为机器学习工作负载深度优化的 AI-native Kubernetes 编排层,突破传统 K8s 在资源弹性、拓扑感知与训练…...
从“能用”到“可靠”:基于SonarQube与Jenkins的Java代码质量防线构建实战
当测试覆盖率不再只是一串数字,而是合并代码前的“一票否决权” 1. 为什么你的“质量门禁”只是个摆设? 在很多团队的CI/CD流水线中,SonarQube的集成往往停留在“能跑就行”的阶段。流水线里确实有代码扫描这一步,日志里也打印出…...
AI智能体基准测试与差异分析:从评估原理到工程实践
1. 项目概述:当AI智能体学会“自我进化”最近在开源社区里,一个名为agentdiff的项目引起了我的注意。它的名字很有意思,直译过来是“智能体差异”。乍一看,你可能会联想到代码差异对比工具diff,但它的前缀agent又明确指…...
