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

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图像的合并

全色图 完整代码&#xff1a; #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的核心组成部分 状态&#xff08;State&#xff09;同步队列&#xff08;Sync Queue&#xff09;条件队列&#xff08;Condition Queue&#xff09; AQS的内部实现 节点&#xff08;Node&#xff09;锁的获取与释放 独占锁共享锁 条件变量 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&#xff08;级联样式表&#xff09;,是一种样式表语言,用于控制网页布局,外观(比如背景图片,图片高度,文本颜色,文本字体,高级定位等等) 可将页面的内容与样式分离开,样式放于单独的.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&#xff0c;FreeRTOS背景介绍 RTOS简介&#xff1a; 实时操作系统&#xff0c;本用于追求实时性的嵌入式系统&#xff0c;典型&#xff1a;ucos/uclinux/vxworks&#xff1b; 特点&#xff1a;中断响应快、一般可嵌套中断、使用实地址、多任务&#xff1b; &#xff08;实…...

【Linux】进程控制1——进程创建和进程终止

1.进程创建 1.1.再谈fork 在linux中fork函数时非常重要的函数&#xff0c;它从已存在进程中创建一个新进程。新进程为子进程&#xff0c;而原进程为父进程。 #include <unistd.h> pid_t fork(void);//pid_t为整形 返回值&#xff1a;子进程中的fork()返回0&#xff…...

计算机图形学入门16:曲线

1.曲线 曲线&#xff08;Curves&#xff09;在图形学中应用非常广泛&#xff0c;比如&#xff1a;相机的拍摄路径、物体的移动路径、动画曲线、矢量字体等。如下图所示&#xff0c;是使用曲线到矢量字体的应用&#xff0c;通过移动一些控制点来改变字体。 2.贝塞尔曲线 2.1 贝…...

【Ruby基础01】windows和termux中搭建Ruby开发环境

windows下环境搭建 railsinstaller官方git地址 按照文档安装git、nodejs、yarn&#xff0c;安装教程百度一下。railsinstall可以从release页面下载最新版本4.1.0。 安装完成如下 安装RubyMine 下载RubyMine RubyMine下载地址 安装激活 下载文件&#xff0c;按照里面的流程…...

2406c++,iguana动态反射

原文 iguana是一个基于编译期反射的序化库,支持从结构序化到不同数据格式. iguana可序化一个C结构到json,xml,yaml和protobuf格式.这都是通过编译期反射实现的. 现在iguana也支持了动态反射,主要特征: 1,通过对象名创建对象实例 2,取对象所有字段名 3,根据字段名取字段值 4,根…...

干货分享——AB站帮你解决独立站收款难题

目前&#xff0c;国内已经有抖音、拼多多和淘宝平台推出“仅退款”售后服务&#xff0c;无疑是加剧了原本就在疯狂打价格战的国内电商的严峻现状&#xff0c;使得商家不得不担心被顾客“薅羊毛”。在国内电商环境严重“内卷”的情况下&#xff0c;拓宽海外市场不失为一大妙计。…...

C++继承与派生

1.基本知识 类的继承是新类从已有类那里获得特性&#xff0c;从已有的类产生新类的过程称为类的派生&#xff1b; 已有类称为基类或父类&#xff0c;派生出的新类则称为派生类或子类&#xff1b; 继承的功能&#xff1a; &#xff08;1&#xff09;使得基类与派生类之间建立…...

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 应用环境中&#xff0c;如 Web 群集、分布式计算等&#xff0c;服务器往往并不配备光驱设备&#xff0c;在这种情况下&#xff0c;如何为数十乃至上百台服务器裸机快速安装系统呢&#xff1f;传统的 USB光驱、移动硬盘等安装方法显然已经难以满足需求。 PXE …...

emm, ComfyUI的作者从Stability.AI离职了

&#x1f356;背景 今天在更新ComfyUI的过程中&#xff0c;看到Manager中有这样一段描述&#xff1a; 嗯&#xff1f;做了新的官方网站&#xff1f;然后开始新篇章&#xff1f; 难道说ComfyUI的作者从Stability.AI离职了&#xff1f; 赶紧点开链接看了下&#xff0c;emm&…...

Redis-五种数据结构之列表(ziplist、quicklist)

列表 文章目录 列表压缩列表-ziplistziplist 定义级联更新 快速列表-quicklistquicklistNode 定义quicklist 定义quicklist常用操作其他操作quicklist 相对于普通链表优点quick应用场景在redis 中使用quicklist 列表数据类型可以存储一组按插入顺序排序的字符串&#xff0c;他很…...

记一次全设备通杀未授权RCE的挖掘经历

想来上一次挖洞还在一年前的大一下&#xff0c;然后就一直在忙活写论文&#xff0c;感觉挺枯燥的&#xff08;可能是自己不太适合弄学术吧QAQ&#xff09;&#xff0c;所以年初1~2月的时候&#xff0c;有空的时候就又会挖一挖国内外各大知名厂商的设备&#xff0c;拿了几份思科…...

【数据库编程-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 &#xff0c;如 5 5 数组下所示&#xff1a; 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, }; 它表示一个迷宫&#xff0c;其中的1表示墙壁&#xff0c;0表示可以走的路&#xff0c;只能横着走…...

【Linux】Linux文件系统中主要文件夹列举_作用说明

在Linux系统中&#xff0c;文件夹&#xff08;或称为目录&#xff09;的组织结构是系统功能和用户数据的重要组成部分。以下是Linux系统中一些主要文件夹的列举及其作用说明&#xff1a; / (根目录): 是Linux文件系统的起点。通常只包含其他目录&#xff0c;不建议直接在其中存…...

移植案例与原理 - HDF驱动框架-驱动配置(1)

HCS(HDF Configuration Source)是HDF驱动框架的配置描述源码&#xff0c;内容以Key-Value为主要形式。它实现了配置代码与驱动代码解耦&#xff0c;便于开发者进行配置管理。应该&#xff0c;类似Linux DTS(Device Tree Source)设备树。 HC-GEN(HDF Configuration Generator)是…...

坚持刷题|反转链表

文章目录 题目思考实现1. 迭代方式实现链表翻转2. 递归方式实现链表翻转 Hello&#xff0c;大家好&#xff0c;我是阿月。坚持刷题&#xff0c;老年痴呆追不上我&#xff0c;今天继续链表&#xff1a;反转链表 题目 LCR 024. 反转链表 思考 翻转链表是一个常见的算法问题&a…...

升级和维护老旧LabVIEW程序

在升级老旧LabVIEW程序至64位环境时&#xff0c;需要解决兼容性、性能和稳定性等问题。本文从软件升级、硬件兼容性、程序优化、故障修复等多个角度详细分析。具体包括64位迁移注意事项、修复页面跳转崩溃、解决关闭程序后残留进程的问题&#xff0c;确保程序在新环境中的平稳运…...

sqlite数据库整体迁移进mysql整个流程并解决中文异常问题

咨询【QQ】 sqlite轻量数据还行&#xff0c;随着数据量增大&#xff0c;不得不迁移进mysql 首先 电脑执行 sqlite3 db.sqlite3 .dump > dump.sql 会把整个sqlite的数据导出进 dump.sql中 紧接着我们把sqlite的sql转换成mysql的sql语句&#xff0c;因为mysql语句和 sq…...

Hadoop3:MapReduce中的Partition原理及自定义Partition

一、默认Partition分区配置 以WC案例来进行验证。 1、设置setNumReduceTasks 修改的代码 这行代码&#xff0c;确定了reduceTask的数量&#xff0c;也确定了分区逻辑 在mapper文件中&#xff0c;打上断点 计算分区的代码 这里会对每一个kv进行计算&#xff0c;然后&#…...

就因为没在大屏项目加全屏按钮,早上在地铁挨了领导一顿骂

“嗯嗯”&#xff0c;“嗯嗯”&#xff0c;“那产品也没说加呀”&#xff0c;“按F11不行吗&#xff1f;”&#xff0c;“嗯嗯”&#xff0c;“好的”。 早上在4号线上&#xff0c;我正坐在地铁里&#xff0c;边上站着的妹子&#xff0c;我看他背着双肩包&#xff0c;打着电话…...

STM32学习记录(八)————定时器输出PWM及舵机的控制

文章目录 前言一、PWM1.工作原理2.内部运作机制3. PWM工作模式4.PWM结构体及库函数 二、PWM控制舵机 前言 一个学习STM32的小白~ 有错误评论区或私信指出提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、PWM 1.工作原理 以向上计数为例&#xff0…...

wordpress设置网站首页/百度推广客户端官方下载

转载于:https://www.cnblogs.com/lexiaofei/p/6732137.html...

网上赚钱平台无需投资/成都网站seo

沛纳海手表在我们心中的印象大概就是大表径、基本实用、手上链款式多等&#xff0c;然而若提起手表的功能性&#xff0c;这似乎就不是沛纳海重点强调的项目。小沛当然不是都只出一些二针、三针的手表&#xff0c;也会有像是两地时间或计时功能等复杂度更高一阶的作品&#xff0…...

wordpress百度云盘/合肥网络推广有限公司

为方便有些老师提前备课&#xff0c;1&#xff0d;10章所有章节已发布到本博客中。 欢迎大家下载使用&#xff0c;也欢迎大家给我们的新书反馈与意见&#xff0c;谢谢&#xff01; 转载于:https://www.cnblogs.com/opengl/p/3880892.html...

建立网站的详细步骤知乎/外贸建站平台

效果图 为什么有伽马校正 你可能不知道一件事 —— 50% 的亮度(或 0.5 RGB)不会以 50% 的亮度在你的显示器上显示。相反,它以大约 73% 的亮度显示,因为输出不是线性的。 顶部是线性梯度,底部是伽马校正。注意顶部,中间部分看起来太亮了。 GLSL代码 算法比较简单,不再…...

网站策划需要具备什么/1688黄页大全进口

TileList点击到选项都是event.target TileListItemRenderer 点击到最后一个空白处的时候都是 ListBaseContentHolder 类型的。 附上一篇文章&#xff1a; Flex编程注意之如何得到itemRenderer里面的内容 前几天在写ViSR的时候&#xff0c;碰到了一个问题&#xff0c;问题如下…...

wordpress百万数据/网址

http://acm.hdu.edu.cn/showproblem.php?pid1176 免费馅饼 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 25157 Accepted Submission(s): 8529Problem Description都说天上不会掉馅饼&#xff0c;但有一天g…...