当前位置: 首页 > 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中创建…...

浅谈 React Hooks

React Hooks 是 React 16.8 引入的一组 API&#xff0c;用于在函数组件中使用 state 和其他 React 特性&#xff08;例如生命周期方法、context 等&#xff09;。Hooks 通过简洁的函数接口&#xff0c;解决了状态与 UI 的高度解耦&#xff0c;通过函数式编程范式实现更灵活 Rea…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

YSYX学习记录(八)

C语言&#xff0c;练习0&#xff1a; 先创建一个文件夹&#xff0c;我用的是物理机&#xff1a; 安装build-essential 练习1&#xff1a; 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件&#xff0c;随机修改或删除一部分&#xff0c;之后…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

C++ 求圆面积的程序(Program to find area of a circle)

给定半径r&#xff0c;求圆的面积。圆的面积应精确到小数点后5位。 例子&#xff1a; 输入&#xff1a;r 5 输出&#xff1a;78.53982 解释&#xff1a;由于面积 PI * r * r 3.14159265358979323846 * 5 * 5 78.53982&#xff0c;因为我们只保留小数点后 5 位数字。 输…...

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 -…...

Selenium常用函数介绍

目录 一&#xff0c;元素定位 1.1 cssSeector 1.2 xpath 二&#xff0c;操作测试对象 三&#xff0c;窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四&#xff0c;弹窗 五&#xff0c;等待 六&#xff0c;导航 七&#xff0c;文件上传 …...

五子棋测试用例

一.项目背景 1.1 项目简介 传统棋类文化的推广 五子棋是一种古老的棋类游戏&#xff0c;有着深厚的文化底蕴。通过将五子棋制作成网页游戏&#xff0c;可以让更多的人了解和接触到这一传统棋类文化。无论是国内还是国外的玩家&#xff0c;都可以通过网页五子棋感受到东方棋类…...

Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践

前言&#xff1a;本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中&#xff0c;跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南&#xff0c;你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案&#xff0c;并结合内网…...

yaml读取写入常见错误 (‘cannot represent an object‘, 117)

错误一&#xff1a;yaml.representer.RepresenterError: (‘cannot represent an object’, 117) 出现这个问题一直没找到原因&#xff0c;后面把yaml.safe_dump直接替换成yaml.dump&#xff0c;确实能保存&#xff0c;但出现乱码&#xff1a; 放弃yaml.dump&#xff0c;又切…...