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];
GDALPansharpenOperation operation;
CPLErr err = operation.Initialize(&opts);
if(err != CE_None) {
return -2;
}
// 创建输出文件(和全色波段一样大)
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);
err = operation.ProcessRegion(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-->栅格-->栅格处理-->创建全色锐化的栅格数据集。

左边ArcGIS融合效果,右边原始多光谱影像

GDAL融合效果与ArcGIS融合效果对比
左边GDAL融合效果,右边ArcGIS融合效果

左边ArcGIS融合效果,右边GDAL融合效果

GDAL多光谱与全色图像融合简单使用的更多相关文章
- jetbrains公司全系列软件最简单破解教程
由于最新jetbrains发布了IntelliJ IDEA 15. PyCharm 5.PhpStorm10.WebStorm 11.RubyMine等各个版本,但是改变了注册方法.原先的注册码包括注 ...
- MEAN 全栈开发 ——实现简单博客
最近在学习MEAN全栈开发的过程中,写了一个小程序就当练练手熟悉一下怎么去组合强大的功能. 废话不多说,直接上文件预览: 整体文件结构: 其中,public文件夹存放了img,js,css文件,其中的 ...
- python全栈开发day61-django简单的出版社网站展示,添加,删除,编辑(单表的增删改查)
day61 django内容回顾: 1. 下载: pip install django==1.11.14 pip install -i 源 django==1.11.14 pycharm 2. 创建项 ...
- 有史以来功能最全,使用最简单的excel导入/导出工具
Github地址:https://github.com/xuanbg/Utility. 还有其他一些福利,请各位园友自取. 构造方法 1.用于导出Excel文件 NpoiHelper(ExcelVer ...
- yii2.0用gii自动补全代码做的简单增删改查,以及图片上传和展示
首先已经用gii根据model层生成了控制器,模型,视图层. 表结构为如图所示:表名为zhoukao1,
- window下玩转maven私服全流程,融合创建仓库、上传项目资源、下载私服资源
在互联网项目开发浪潮中,maven成为了项目管理依赖的重要工具,更多时候maven只作为拉取外部依赖的手段.但出于安全的考虑的,部门企业难免封装一些私有的工具类,或开源框架的二次开发封装,mave ...
- CAD&CG GDC 2018大会论文录用名单
Section 1 增强现实与图形学: 报告时间:2018-8-25 14:00-15:30 报告地点:会议室1 P000009 基于增强现实的产品质量信息传递方法 P000104 重彩画的风格转移 ...
- 《Web全栈工程师的自我修养》读书笔记(转载)
[声明] 欢迎转载,但请保留文章原始出处→_→ 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/5 ...
- IOS开发之小实例--创建一个简单的用于视频录制和回放的应用程序
前言:还是看了一下国外的入门IOS文章:<Create a Simple App for Video Recording and Playback>,主要涉及视频录制和回放的功能的基本实现 ...
随机推荐
- Springmvc借助SimpleUrlHandlerMapping实现接口开关功能
一.接口开关功能 1.可配置化,依赖配置中心 2.接口访问权限可控 3.springmvc不会扫描到,即不会直接的将接口暴露出去 二.接口开关使用场景 和业务没什么关系,主要方便查询系统中的一些状态信 ...
- Linux 中 Windows 中文乱码
Linux 下 Windows 源代码中文乱码 由于 windows 和 linux 对文本的编码方式不同,所以经常会有 windows 中生成的文本在 linux 中打开乱码的情况. 比如: 我面临 ...
- ubantu 执行sudo apt-get update 出现校验不符问题
一直被这个问题困扰,今天安装mongodb时,看了别人博客暂时解决了,不知道会不会出什么问题. 直接打开软件更新器: 然后点击其他软件,去掉两个独立的多选项: 再执行一遍 sudo apt-get u ...
- Ubuntu12.04系统复制速度奇慢的原因猜想
一开始到实验室,开始使用这些机器时候就是安装好的win+Ubuntu 12.04双系统,开始因为就自己用,而且文件传输并不是很多,复制的问题并没有凸显出来, 去年下半年开始,往服务器上传或下载大批量文 ...
- Android 一个Activity 里面放置多个 Fragment 实现点击切换的Tab 页面效果
// BaseActivity 是实现的一些公共的变量和方法,可以暂时为空的类 public class HomeActivity extends BaseActivity implements Vi ...
- JavaScript基础笔记(十四)最佳实践
最佳实践 一)松散耦合 1.解耦HTML/JavaScript: 1)避免html种使用js 2)避免js种创建html 2.解耦CSS/JS 操作类 3.解耦应用逻辑和事件处理 以下是要牢记的应用和 ...
- 以加密方式访问tomcat服务器
以加密方式(https)访问tomcat服务器,就要求对相应的端口配置加密连接器connector. 配置加密连接器的方法如下: 1.生成数字证书 利用jdk里的keytool生成证书,keytool ...
- 解放F5——React开启模块热更新
解放F5--React开启模块热更新 在一个正在开发的应用中,刷新页面将会降低你的生产效率:你必须得等待页面加载完毕. 一个大的应用可能会花很多秒钟才能刷新完页面.使用 HMR(模块热替换) 可以避免 ...
- JS 引用类型之Object
引用类型定义: 描述一类对象具有的属性和方法 引用类型Object ,也就是我们常说的对象类型了,这应该是JavaScript中最常见的引用类型了. 对象是某个引用类型的实例,如何创建一个实例,也就是 ...
- 最大流:Dinic算法
蒟蒻居然今天第一次写网络流 我太弱啦! 最大流问题有很多解法 虽然isap常数巨小 但是连dinic都写挂的本蒟蒻并不会orz 那么我们选用比较好实现的dinic来解决最大流问题 来一段定义: ...