C++使用GDAL库完成tiff图像的合并
全色图
完整代码:
#include "gdal_priv.h"
#include "cpl_string.h"
#include <vector>
#include <algorithm>
#include <iostream>
#include <filesystem>using namespace std;
namespace fs = std::filesystem;
vector<pair<int, int>> imageDims; // 存储每个图像的宽和高
vector<string> fileNames;void concatenateImages(const string& folderPath, const string& outputFilePath) {GDALAllRegister();//注册驱动CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");//支持中文路径GDALDataType dataType{};// 遍历文件夹获取图像for (const auto& entry : fs::directory_iterator(folderPath)) {if (entry.is_regular_file() && entry.path().extension() == ".tiff") {fileNames.push_back(entry.path().string());GDALDataset* ds = (GDALDataset*)GDALOpen(entry.path().string().c_str(), GA_ReadOnly);if (ds) {imageDims.push_back({ ds->GetRasterXSize(), ds->GetRasterYSize() });GDALClose(ds);// 获取第一个波段的数据类型GDALRasterBand* band = ds->GetRasterBand(1);dataType = band->GetRasterDataType();}else {cerr << "无法打开文件: " << entry.path() << endl;}}}// 计算新图像的尺寸int totalWidth = 0;int maxHeight = 0;for (const auto& dim : imageDims) {totalWidth += dim.first;maxHeight = max(maxHeight, dim.second);}// 创建输出图像GDALDriver* driver = GetGDALDriverManager()->GetDriverByName("GTiff");GDALDataset* outDataset = driver->Create(outputFilePath.c_str(), totalWidth, maxHeight, 1, dataType, nullptr);if (outDataset == nullptr) {cerr << "创建输出文件失败." << endl;return;}GDALRasterBand* outBand = outDataset->GetRasterBand(1);outBand->Fill(0); // 填充黑色背景// 拼接图像int xOff = 0;vector<unsigned short> buffer; // 缓冲区for (size_t i = 0; i < fileNames.size(); ++i) {GDALDataset* dataset = (GDALDataset*)GDALOpen(fileNames[i].c_str(), GA_ReadOnly);if (dataset) {GDALRasterBand* inBand = dataset->GetRasterBand(1);int width = imageDims[i].first; // 当前处理图像的宽度int height = imageDims[i].second;// 动态调整缓冲区大小,适应当前图像宽度buffer.resize(width);// 从输入波段读取数据到缓冲区for (int j = 0; j < height; ++j) {CPLErr err = GDALRasterIO(inBand, GF_Read, 0, j, width, 1,&buffer[0], width, 1, dataType, 0, 0);if (err != CE_None) {cerr << "从输入波段读取数据时出错." << endl;break;}// 再从缓冲区写入到输出波段err = GDALRasterIO(outBand, GF_Write, xOff, j, width, 1,&buffer[0], width, 1, dataType, 0, 0);if (err != CE_None) {cerr << "将数据写入输出波段时出错." << endl;break;}}GDALClose(dataset);xOff += width; // 更新x偏移量,准备拼接下一幅图像}}// 写入并关闭输出文件outDataset->FlushCache();GDALClose(outDataset);
}int main() {string folderPath = "C:\\Users\\WHU\\Desktop\\PAN"; // 文件夹路径string outputFilePath = "C:\\Users\\WHU\\Desktop\\PAN\\image.tiff"; // 输出文件路径concatenateImages(folderPath, outputFilePath);return 0;
}
多光谱:
完整代码:
#include "gdal_priv.h"
#include <vector>
#include <algorithm>//计算图像宽度和高度
#include <filesystem>//读文件
#include <numeric> //数值操作
#include <iostream>
#include <memory>//智能指针using namespace std;// 初始化GDAL
void InitializeGDAL()
{GDALAllRegister();CPLSetConfigOption("GDAL_FILENAME_IS_UTF8", "NO");//支持中文路径
}// 获取图像的宽度、高度和波段数
bool GetImageSizeAndBands(const string& filePath, int& width, int& height, int& bands)
{GDALDataset* dataset = (GDALDataset*)GDALOpen(filePath.c_str(), GA_ReadOnly);if (!dataset){printf("打开失败 %s\n", filePath.c_str());return false;}width = dataset->GetRasterXSize();height = dataset->GetRasterYSize();bands = dataset->GetRasterCount();GDALClose(dataset);return true;
}// 拼接多波段图像
void StitchMultiBandImages(const vector<string>& fileNames, const string& outputFilePath)
{InitializeGDAL();vector<int> widths, heights, bandCounts;for (const auto& fileName : fileNames){int width, height, bands;if (GetImageSizeAndBands(fileName, width, height, bands)){widths.push_back(width);heights.push_back(height);bandCounts.push_back(bands);}else{printf("获取失败 %s\n", fileName.c_str());}}int totalWidth = accumulate(widths.begin(), widths.end(), 0);int maxHeight = *max_element(heights.begin(), heights.end());int maxBands = *max_element(bandCounts.begin(), bandCounts.end());GDALDriver* driver = GetGDALDriverManager()->GetDriverByName("GTiff");char** options = nullptr; //创建输出图像GDALDataset* dstDataset = driver->Create(outputFilePath.c_str(), totalWidth, maxHeight, maxBands, GDT_UInt16, options);for (int band = 1; band <= maxBands; ++band){// 初始化输出波段为黑色GDALRasterBand* dstBand = dstDataset->GetRasterBand(band);//智能管理缓冲区内存unique_ptr<float[]> buffer(new float[totalWidth * maxHeight]);fill_n(buffer.get(), totalWidth * maxHeight, 0); // 填充黑色dstBand->RasterIO(GF_Write, 0, 0, totalWidth, maxHeight, buffer.get(), totalWidth, maxHeight, GDT_UInt16, 0, 0);}// 逐个读取并写入图像数据int xOffset = 0;for (size_t i = 0; i < fileNames.size(); ++i){GDALDataset* srcDataset = (GDALDataset*)GDALOpen(fileNames[i].c_str(), GA_ReadOnly);if (srcDataset){for (int band = 1; band <= bandCounts[i]; ++band){GDALRasterBand* srcBand = srcDataset->GetRasterBand(band);GDALRasterBand* dstBand = dstDataset->GetRasterBand(band);unique_ptr<float[]> buffer(new float[widths[i] * heights[i]]);CPLErr readErr = srcBand->RasterIO(GF_Read, 0, 0, widths[i], heights[i], buffer.get(), widths[i], heights[i], GDT_UInt16, 0, 0);if (readErr == CE_None){dstBand->RasterIO(GF_Write, xOffset, 0, widths[i], heights[i], buffer.get(), widths[i], heights[i], GDT_UInt16, 0, 0);}}GDALClose(srcDataset);}xOffset += widths[i];}GDALClose(dstDataset);
}
// 从指定目录获取所有.tiff文件路径
vector<string> GetTiffFilesFromDirectory(const string& directoryPath)
{vector<string> tiffFiles;for (const auto& entry : filesystem::directory_iterator(directoryPath)){if (entry.is_regular_file() && entry.path().extension() == ".tiff"){tiffFiles.push_back(entry.path().string());}}return tiffFiles;
}
int main() {string folderPath = "C:\\Users\\WHU\\Desktop\\MSS"; // 文件夹路径string outputFilePath = "C:\\Users\\WHU\\Desktop\\MSS\\stitched_image.tiff"; // 输出文件路径// 获取指定文件夹内的所有.tiff文件路径vector<string> tiffFiles = GetTiffFilesFromDirectory(folderPath);if (!tiffFiles.empty()) {// 使用获取到的文件列表进行图像拼接StitchMultiBandImages(tiffFiles, outputFilePath);cout << "图像成功生成" << endl;}else {cerr << "没有找到该路径: " << folderPath << endl;}return 0;
}
相关文章:
C++使用GDAL库完成tiff图像的合并
全色图 完整代码: #include "gdal_priv.h" #include "cpl_string.h" #include <vector> #include <algorithm> #include <iostream> #include <filesystem>using namespace std; namespace fs std::filesystem; vec…...
深入理解AQS:Java并发编程中的核心组件
目录 AQS简介AQS的设计思路AQS的核心组成部分 状态(State)同步队列(Sync Queue)条件队列(Condition Queue) AQS的内部实现 节点(Node)锁的获取与释放 独占锁共享锁 条件变量 AQS的应…...
集合进阶:List集合
一.List集合的特有方法 1.Collection的方法List都继承了 2.List集合因为有索引,所以多了很多索引操作的方法。 3.add // 1.创建一个集合List<String> list new ArrayList<>(); // 2.添加元素list.add("aaa");list.add("bbb"…...
el-table表头修改文字或者背景颜色,通过header-row-style设置样式
方式一 <el-table :header-cell-style"{text-align: center}" />方式二 <template><el-table :header-cell-style"tableHeaderColor" /> </template> <script> export default {methods: {tableHeaderColor ({row, column…...
web前端-CSS
CSS CSS概述: CSS是Cascading Style Sheets(级联样式表),是一种样式表语言,用于控制网页布局,外观(比如背景图片,图片高度,文本颜色,文本字体,高级定位等等) 可将页面的内容与样式分离开,样式放于单独的.css文件或者HTML某处 CSS是网页样式,HTML是网页…...
u8g2 使用IIC驱动uc1617 lcd 字符显示只显示上半部分,不显示下半部
使用u8g2 使用硬件iic驱动某些page为4个字节 带灰度的lcd显示屏幕的时候有时候只显示上半部,下半部不显示,例如uc1617等。 原因: 以uc1617为例,链接https://github.com/olikraus/u8g2/blob/master/csrc/u8x8_d_uc1617.c 在u8x8_d_uc1617_common方法中的case U8X8_MSG_DI…...
单片机第五季-第八课:STM32CubeMx和FreeRTOS
1,FreeRTOS背景介绍 RTOS简介: 实时操作系统,本用于追求实时性的嵌入式系统,典型:ucos/uclinux/vxworks; 特点:中断响应快、一般可嵌套中断、使用实地址、多任务; (实…...
【Linux】进程控制1——进程创建和进程终止
1.进程创建 1.1.再谈fork 在linux中fork函数时非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。 #include <unistd.h> pid_t fork(void);//pid_t为整形 返回值:子进程中的fork()返回0ÿ…...
计算机图形学入门16:曲线
1.曲线 曲线(Curves)在图形学中应用非常广泛,比如:相机的拍摄路径、物体的移动路径、动画曲线、矢量字体等。如下图所示,是使用曲线到矢量字体的应用,通过移动一些控制点来改变字体。 2.贝塞尔曲线 2.1 贝…...
【Ruby基础01】windows和termux中搭建Ruby开发环境
windows下环境搭建 railsinstaller官方git地址 按照文档安装git、nodejs、yarn,安装教程百度一下。railsinstall可以从release页面下载最新版本4.1.0。 安装完成如下 安装RubyMine 下载RubyMine RubyMine下载地址 安装激活 下载文件,按照里面的流程…...
2406c++,iguana动态反射
原文 iguana是一个基于编译期反射的序化库,支持从结构序化到不同数据格式. iguana可序化一个C结构到json,xml,yaml和protobuf格式.这都是通过编译期反射实现的. 现在iguana也支持了动态反射,主要特征: 1,通过对象名创建对象实例 2,取对象所有字段名 3,根据字段名取字段值 4,根…...
干货分享——AB站帮你解决独立站收款难题
目前,国内已经有抖音、拼多多和淘宝平台推出“仅退款”售后服务,无疑是加剧了原本就在疯狂打价格战的国内电商的严峻现状,使得商家不得不担心被顾客“薅羊毛”。在国内电商环境严重“内卷”的情况下,拓宽海外市场不失为一大妙计。…...
C++继承与派生
1.基本知识 类的继承是新类从已有类那里获得特性,从已有的类产生新类的过程称为类的派生; 已有类称为基类或父类,派生出的新类则称为派生类或子类; 继承的功能: (1)使得基类与派生类之间建立…...
Survival Animations
一套生存游戏的动画集,包括采集、建造、捕鱼、剥皮/鞣制、篝火等更多内容。 总动画数:89 建造/制作 30 篝火 28 饮水 3 水壶 3 觅食 2 治疗 3 空闲 1 原始捕鱼 7 剥皮 1 矛捕鱼 4 伐木 5 下载:Unity资源商店链接资源下载链接 效果图:...
Cargo 教程
Cargo 教程 1. 引言 Cargo 是 Rust 编程语言的包管理器和构建工具。它为 Rust 项目提供了依赖管理、编译和打包等功能。本教程将详细介绍 Cargo 的基本用法,帮助您快速上手 Rust 项目开发。 2. 安装 Cargo 在开始使用 Cargo 之前,您需要确保已经安装了 Rust 编程语言。Ru…...
linux中“PXE高效批量装机”
在大规模的 Linux 应用环境中,如 Web 群集、分布式计算等,服务器往往并不配备光驱设备,在这种情况下,如何为数十乃至上百台服务器裸机快速安装系统呢?传统的 USB光驱、移动硬盘等安装方法显然已经难以满足需求。 PXE …...
emm, ComfyUI的作者从Stability.AI离职了
🍖背景 今天在更新ComfyUI的过程中,看到Manager中有这样一段描述: 嗯?做了新的官方网站?然后开始新篇章? 难道说ComfyUI的作者从Stability.AI离职了? 赶紧点开链接看了下,emm&…...
Redis-五种数据结构之列表(ziplist、quicklist)
列表 文章目录 列表压缩列表-ziplistziplist 定义级联更新 快速列表-quicklistquicklistNode 定义quicklist 定义quicklist常用操作其他操作quicklist 相对于普通链表优点quick应用场景在redis 中使用quicklist 列表数据类型可以存储一组按插入顺序排序的字符串,他很…...
记一次全设备通杀未授权RCE的挖掘经历
想来上一次挖洞还在一年前的大一下,然后就一直在忙活写论文,感觉挺枯燥的(可能是自己不太适合弄学术吧QAQ),所以年初1~2月的时候,有空的时候就又会挖一挖国内外各大知名厂商的设备,拿了几份思科…...
【数据库编程-SQLite3(一)】sqlite3数据库在Windows下的配置及测试
学习分析 1、资源准备2、环境配置2.1、将资源包下载解压缩保存。2.2、在QT中创建工程,配置环境 3、测试配置3.1、 sqlite3_open函数3.2、sqlite3_close函数3.3、代码测试 1、资源准备 资源包 2、环境配置 2.1、将资源包下载解压缩保存。 解压缩得到以下文件 2.2、在QT中创建…...
YOLOv10改进 | 主干篇 | YOLOv10引入华为VanillaNet替换Backbone
1. VanillaNet介绍 1.1 摘要: 基础模型的核心是“越多越好”的理念,计算机视觉和自然语言处理领域取得的惊人成功就是例证。 然而,优化的挑战和变压器模型固有的复杂性要求范式向简单性转变。 在这项研究中,我们介绍了 VanillaNet,一种设计优雅的神经网络架构。 通过避免…...
C++ 迷宫问题
描述 定义一个二维数组 N*M ,如 5 5 数组下所示: int maze[5][5] { 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, }; 它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走…...
【Linux】Linux文件系统中主要文件夹列举_作用说明
在Linux系统中,文件夹(或称为目录)的组织结构是系统功能和用户数据的重要组成部分。以下是Linux系统中一些主要文件夹的列举及其作用说明: / (根目录): 是Linux文件系统的起点。通常只包含其他目录,不建议直接在其中存…...
移植案例与原理 - HDF驱动框架-驱动配置(1)
HCS(HDF Configuration Source)是HDF驱动框架的配置描述源码,内容以Key-Value为主要形式。它实现了配置代码与驱动代码解耦,便于开发者进行配置管理。应该,类似Linux DTS(Device Tree Source)设备树。 HC-GEN(HDF Configuration Generator)是…...
坚持刷题|反转链表
文章目录 题目思考实现1. 迭代方式实现链表翻转2. 递归方式实现链表翻转 Hello,大家好,我是阿月。坚持刷题,老年痴呆追不上我,今天继续链表:反转链表 题目 LCR 024. 反转链表 思考 翻转链表是一个常见的算法问题&a…...
升级和维护老旧LabVIEW程序
在升级老旧LabVIEW程序至64位环境时,需要解决兼容性、性能和稳定性等问题。本文从软件升级、硬件兼容性、程序优化、故障修复等多个角度详细分析。具体包括64位迁移注意事项、修复页面跳转崩溃、解决关闭程序后残留进程的问题,确保程序在新环境中的平稳运…...
sqlite数据库整体迁移进mysql整个流程并解决中文异常问题
咨询【QQ】 sqlite轻量数据还行,随着数据量增大,不得不迁移进mysql 首先 电脑执行 sqlite3 db.sqlite3 .dump > dump.sql 会把整个sqlite的数据导出进 dump.sql中 紧接着我们把sqlite的sql转换成mysql的sql语句,因为mysql语句和 sq…...
Hadoop3:MapReduce中的Partition原理及自定义Partition
一、默认Partition分区配置 以WC案例来进行验证。 1、设置setNumReduceTasks 修改的代码 这行代码,确定了reduceTask的数量,也确定了分区逻辑 在mapper文件中,打上断点 计算分区的代码 这里会对每一个kv进行计算,然后&#…...
就因为没在大屏项目加全屏按钮,早上在地铁挨了领导一顿骂
“嗯嗯”,“嗯嗯”,“那产品也没说加呀”,“按F11不行吗?”,“嗯嗯”,“好的”。 早上在4号线上,我正坐在地铁里,边上站着的妹子,我看他背着双肩包,打着电话…...
STM32学习记录(八)————定时器输出PWM及舵机的控制
文章目录 前言一、PWM1.工作原理2.内部运作机制3. PWM工作模式4.PWM结构体及库函数 二、PWM控制舵机 前言 一个学习STM32的小白~ 有错误评论区或私信指出提示:以下是本篇文章正文内容,下面案例可供参考 一、PWM 1.工作原理 以向上计数为例࿰…...
农业部工程建设服务中心网站/百度搜索流量查询
A、 B 、 C 是 3 个字符串。把 A 中包含的所有 B 都替换为 C ,如果替换以后还有 B 就继续替换,直到 A 不包含 B 为止。 1、请编写程序实现以上功能。不允许使用系统提供的字符串比较、查找和替换函数。 js版代码实现let a1 aaabbbcccbbbffbbb; let b1 …...
网站css初始化/平台如何做推广
Lighting Box2源码分析(一):整体功能Lighting Box2源码分析(二):Sun ShaftsLighting Box2源码分析(三):Depth Of Field景深Lighting Box2源码分析(四):Global Fog全局雾...
成都建设银行官方网站/百度问答平台
http://codeforces.com/problemset/problem/1213/E 题目大意:给两个字符串SSS和TTT,它们的长度均为222,且只包含字符a,b,ca,b,ca,b,c。对于给定的nnn,问能否找到一个长为3∗n3*n3∗n的字符串resresres,使得resresres恰…...
电子网站建设考试/手机广告推广软件
本文主要讲如何自定义NSOperation,以及自定义NSOperation的一些注意事项,以下载图片为例。 新建一个类,继承于NSOperation。 CustomOperation.h 代码 #import <Foundation/Foundation.h> #import <UIKit/UIKit.h>interface Custo…...
门户网站建站方案/抖音seo搜索优化
模型实例方法 str():在将对象转换成字符串时会被调用。save():将模型对象保存到数据表中,ORM框架会转换成对应的insert或update语句。delete():将模型对象从数据表中删除,ORM框架会转换成对应的delete语句。模型类的属…...
福建省建设厅网站劳保核定卡/it行业培训机构一般多少钱
BrowserModule,CommonModule的选择: BrowserModule提供了启动和运行浏览器应用的那些基本的服务提供商。BrowserModule还从angular/common中重新导出了CommonModule,这意味着AppModule中的组件也同样可以访问那些每个应用都需要的Angular指令…...