GDAL多光谱与全色图像融合简单使用
简述
最近在GDAL的代码中看见了gdalpansharpen.cpp
,于是简单的尝试了一下。
融合后的效果比较差,这应该是我对这个算法的使用还不熟悉,还有些地方没有弄清楚。这个代码比较新,是2.1版本才加上的,我在看的时候,代码还有一些小问题,已经在github上提交了issuse了。
融合使用的数据是我在网上找到的高分一号的一景数据,先做了校正,形成全色波段TIFF(单波段)和多光谱波段TIFF(4波段)。
相关知识参考:
- 遥感影像的“全色”与“多光谱”
- 高分一号(GF-1)卫星影像数据介绍
- 国内遥感卫星资源综述
- 高分一号影像处理流程
- 遥感影像融合方法(英文)
- ENVI 遥感图像融合
- 为何全色影像分辨率高于多光谱影像分辨率
- 全色锐化的基础知识
C++代码
代码基于当前https://github.com/OSGeo/gdal仓库的master分支构建。
// g++ gdal_pansharpen.cpp -o gdal_pansharpen -I../include -L../lib -lgdal #include <gdalpansharpen.h> #include <cpl_auto_close.h> #include <cpl_error.h> int main() { GDALAllRegister(); // 打开全色波段(高分辨率)文件 GDALDatasetH hPanDset = GDALOpen("/mnt/data/GF1_PMS2_E116.5_N39.6_20130501_L1A0000127213-PAN2_rpc.tiff",GA_ReadOnly); CPL_AUTO_CLOSE_WARP(hPanDset,GDALClose); VALIDATE_POINTER1(hPanDset,"Open Pansharpen file failed",1); // 打开多光谱(低分辨率)文件 GDALDatasetH hMssDset = GDALOpen("/mnt/data/GF1_PMS2_E116.5_N39.6_20130501_L1A0000127213-MSS2_rpc.tiff",GA_ReadOnly); CPL_AUTO_CLOSE_WARP(hMssDset,GDALClose); VALIDATE_POINTER1(hPanDset,"Open Spectral Band file failed",1); int nSpectralBands = GDALGetRasterCount(hMssDset); GDALPansharpenOptions opts; opts.ePansharpenAlg = GDAL_PSH_WEIGHTED_BROVEY; // 超分辨率贝叶斯法,当前仅支持brovery加权 opts.eResampleAlg = GRIORA_Cubic; // 重采样至全色光谱波段分辨率的算法 opts.nBitDepth = 0; // 多光谱波段位深度,0表示默认 opts.nWeightCount = nSpectralBands; // 权重系数数组元素个数(与输入多光谱波段数一致) double* pWeightCount= static_cast<double*>( CPLMalloc(opts.nWeightCount * sizeof(double))); // 权重系数数组 CPL_AUTO_CLOSE_WARP(pWeightCount,CPLFree); opts.padfWeights = pWeightCount; opts.padfWeights[0] = 0.334; // 蓝 opts.padfWeights[1] = 0.333; // 绿 opts.padfWeights[2] = 0.333; // 红 opts.padfWeights[3] = 0.0; // 近红外 // 设置全色波段(高分辨率) opts.hPanchroBand = GDALGetRasterBand(hPanDset,1); // 设置多光谱波段 opts.nInputSpectralBands = nSpectralBands; GDALRasterBandH* pInputSpectralBands = static_cast<GDALRasterBandH*>( CPLMalloc(sizeof(GDALRasterBandH) * nSpectralBands)); CPL_AUTO_CLOSE_WARP(pInputSpectralBands,CPLFree); opts.pahInputSpectralBands = pInputSpectralBands; // std::generatr for(int i=0;i< nSpectralBands;++i) { opts.pahInputSpectralBands[i] = GDALGetRasterBand(hMssDset,i+1); } // 设置需要输出到全色波段分辨率的波段 opts.nOutPansharpenedBands = 4; // 这个数组里面存的是pahInputSpectralBands里波段的索引值 int panOutPansharpenedBands[4] = { 2, 1, 0, 3}; // 红、绿、蓝、近红外 opts.panOutPansharpenedBands = panOutPansharpenedBands; opts.bHasNoData = FALSE; // 全色和多光谱波段是否具有无效值(NoData值) opts.dfNoData = 0.0; // 全色和多光谱波段的无效值,也将作为输出的NoData值 opts.nThreads = -1; // 使用的线程数,-1表示使用CPU线程数 // 设置多光谱波段与全色波段在像素上的移位(保证地理空间位置对齐) // 都是相对于全色波段的0,0像素的像素(全色波段像素大小)偏移 // 也就是两者的0,0像素的地理空间上的偏移量在全色波段分辨率相应的像素数 double adfGTPan[6]; GDALGetGeoTransform(hPanDset,adfGTPan); double adfGTMss[6]; GDALGetGeoTransform(hPanDset,adfGTMss); opts.dfMSShiftX = (adfGTPan[0] - adfGTMss[0]) / adfGTPan[1]; opts.dfMSShiftY = (adfGTPan[3] - adfGTMss[3]) / adfGTPan[5]; // 2023年6月16日 修改,使用 C 接口形式 // GDALPansharpenOperation operation; // CPLErr err = operation.Initialize(&opts); // if(err != CE_None) { // return -2; // } GDALPansharpenOperationH hOperation= GDALCreatePansharpenOperation(&opts); if(hOperation== nullptr) { return -2; } CPL_AUTO_CLOSE_WARP(hOperation, GDALDestroyPansharpenOperation); // 创建输出文件(和全色波段一样大) int nOutXSize, nOutYSize; nOutXSize = GDALGetRasterBandXSize(opts.hPanchroBand); nOutYSize = GDALGetRasterBandYSize(opts.hPanchroBand); GDALDataType eBufDataType = GDALGetRasterDataType(opts.pahInputSpectralBands[0]); eBufDataType = GDT_Float64; GDALDriverH hDriver = GDALGetDriverByName("GTiff"); CPLStringList CreateOption; CreateOption.AddNameValue("TILED", "YES"); CreateOption.AddNameValue("BIGTIFF", "YES"); CreateOption.AddNameValue("INTERLEAVE", "BAND"); CreateOption.AddNameValue("COMPRESS", "LZW"); // 中度压缩 CreateOption.AddNameValue("ZLEVEL", "6"); GDALDatasetH hOutDset = GDALCreate(hDriver, "/mnt/data/GF1_PMS2_E116.5_N39.6_20130501_L1A0000127213.tif", nOutXSize, nOutYSize, nSpectralBands, GDT_UInt16, CreateOption); CPL_AUTO_CLOSE_WARP(hOutDset,GDALClose); VALIDATE_POINTER1(hOutDset,"Create Output file error", -3); GDALSetGeoTransform(hOutDset, adfGTPan); GDALSetProjection(hOutDset,GDALGetProjectionRef(hPanDset)); void* pData = CPLMalloc(256*256*GDALGetDataTypeSizeBytes(eBufDataType)*nSpectralBands); CPL_AUTO_CLOSE_WARP(pData,CPLFree); for(int nYOff = 0; nYOff < nOutYSize; nYOff += 256) { for(int nXOff = 0; nXOff < nOutXSize; nXOff += 256) { int nXSize = std::min(nOutXSize - nXOff,256); int nYSize = std::min(nOutYSize - nYOff,256); printf("Process[%6d,%6d,%6d,%6d]\r",nXOff,nYOff,nXOff+nXSize,nYOff+nYSize); // 2023年6月16日 修改,使用 C 接口形式 // err = operation.ProcessRegion(nXOff,nYOff,nXSize,nYSize,pData,eBufDataType); err = GDALPansharpenProcessRegion(hOperation, nXOff,nYOff,nXSize,nYSize,pData,eBufDataType); if(err == CE_Failure) { CPLError(err,CPLE_AppDefined,"operation.ProcessRegion"); return -4; } int panBandMap[4] = { 1, 2, 3, 4}; err = GDALDatasetRasterIO(hOutDset, GF_Write, nXOff,nYOff,nXSize,nYSize, pData,nXSize,nYSize, eBufDataType, 4,panBandMap, 0,0,nXSize*nYSize*GDALGetDataTypeSizeBytes(eBufDataType)); } } puts("\nPansharpen finished"); return 0; }
效果对比
GDAL融合效果和原始多光谱波段对比#
GDAL融合效果和原始全色波段对比#
ARCGIS融合效果与原始全色和多光谱对比#
ArcGIS融合过程使用工具箱-->系统工具箱-->Data Management Tools-->栅格-->栅格处理-->创建全色锐化的栅格数据集
。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· winform 绘制太阳,地球,月球 运作规律
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
2016-11-23 Qt拖拽界面 (*.ui) 缩放问题及解决办法