学习过程中,用到重采样,感觉不错,转载过来供大家学习,原文地址:http://blog.csdn.net/giselite/article/details/7792620
#include "gdal_priv.h"
#include "ogrsf_frmts.h"
#include "gdalwarper.h"/***
* 遥感影像重采样(要求影像必须有投影,否则走不通)
* @param pszSrcFile输入文件的路径
* @param pszOutFile写入的结果图像的路径
* @param eResample采样模式,有五种,具体参见GDALResampleAlg定义,默认为双线性内插
* @param fResXX转换采样比,默认大小为1.0,大于1图像变大,小于1表示图像缩小。数值上等于采样后图像的宽度和采样前图像宽度的比
* @param fResYY转换采样比,默认大小为1.0,大于1图像变大,小于1表示图像缩小。数值上等于采样后图像的高度和采样前图像高度的比
* @retrieve0成功
* @retrieve-1打开源文件失败
* @retrieve-2创建新文件失败
* @retrieve-3处理过程中出错
*/
int ResampleGDAL(const char* pszSrcFile, const char* pszOutFile, float fResX = 1.0 ,float fResY= 1.0,GDALResampleAlg eResample = GRA_Bilinear)
{
GDALAllRegister();
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO");
GDALDataset *pDSrc = https://www.it610.com/article/(GDALDataset *)GDALOpen(pszSrcFile, GA_ReadOnly);
if (pDSrc == NULL)
{
return -1;
}GDALDriver *pDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
if (pDriver == NULL)
{
GDALClose((GDALDatasetH) pDSrc);
return -2;
}
int width=pDSrc->GetRasterXSize();
int height=pDSrc->GetRasterYSize();
int nBandCount = pDSrc->GetRasterCount();
GDALDataType dataType = pDSrc->GetRasterBand(1)->GetRasterDataType();
char *pszSrcWKT = NULL;
pszSrcWKT = const_cast(pDSrc->GetProjectionRef());
//如果没有投影,人为设置一个
if(strlen(pszSrcWKT)<=0)
{
OGRSpatialReference oSRS;
oSRS.SetUTM(50,true);
//北半球东经120度
oSRS.SetWellKnownGeogCS("WGS84");
oSRS.exportToWkt(&pszSrcWKT);
}void *hTransformArg;
hTransformArg = GDALCreateGenImgProjTransformer((GDALDatasetH) pDSrc,pszSrcWKT,NULL,pszSrcWKT,FALSE,0.0,1);
//(没有投影的影像到这里就走不通了)
if (hTransformArg == NULL)
{
GDALClose((GDALDatasetH) pDSrc);
return -3;
}double dGeoTrans[6] = {0};
int nNewWidth=0,nNewHeight=0;
if(GDALSuggestedWarpOutput((GDALDatasetH)pDSrc,GDALGenImgProjTransform,hTransformArg,dGeoTrans,&nNewWidth,&nNewHeight)!=CE_None)
{
GDALClose((GDALDatasetH) pDSrc);
return -3;
}GDALDestroyGenImgProjTransformer(hTransformArg);
//adfGeoTransform[0] /* top left x */
//adfGeoTransform[1] /* w-e pixel resolution */
//adfGeoTransform[2] /* rotation, 0 if image is "north up" */
//adfGeoTransform[3] /* top left y */
//adfGeoTransform[4] /* rotation, 0 if image is "north up" */
//adfGeoTransform[5] /* n-s pixel resolution */dGeoTrans[1] = dGeoTrans[1] / fResX;
dGeoTrans[5] = dGeoTrans[5] / fResY;
nNewWidth = static_cast(nNewWidth*fResX+0.5);
nNewHeight = static_cast(nNewHeight*fResY+0.5);
//创建结果数据集
GDALDataset *pDDst = pDriver->Create(pszOutFile, nNewWidth, nNewHeight, nBandCount, dataType, NULL);
if (pDDst == NULL)
{
GDALClose((GDALDatasetH) pDSrc);
return -2;
}pDDst->SetProjection(pszSrcWKT);
pDDst->SetGeoTransform(dGeoTrans);
GDALWarpOptions *psWo = GDALCreateWarpOptions();
//psWo->papszWarpOptions = CSLDuplicate(NULL);
psWo->eWorkingDataType = dataType;
psWo->eResampleAlg = eResample;
psWo->hSrcDS = (GDALDatasetH) pDSrc;
psWo->hDstDS = (GDALDatasetH) pDDst;
psWo->pfnTransformer = GDALGenImgProjTransform;
psWo->pTransformerArg = GDALCreateGenImgProjTransformer((GDALDatasetH) pDSrc,pszSrcWKT,(GDALDatasetH) pDDst,pszSrcWKT,FALSE,0.0,1);
;
psWo->nBandCount = nBandCount;
psWo->panSrcBands = (int *) CPLMalloc(nBandCount*sizeof(int));
psWo->panDstBands = (int *) CPLMalloc(nBandCount*sizeof(int));
for (int i=0;
ipanSrcBands[i] = i+1;
psWo->panDstBands[i] = i+1;
}GDALWarpOperation oWo;
if (oWo.Initialize(psWo) != CE_None)
{
GDALClose((GDALDatasetH) pDSrc);
GDALClose((GDALDatasetH) pDDst);
return -3;
}oWo.ChunkAndWarpImage(0, 0, nNewWidth, nNewHeight);
GDALFlushCache( pDDst );
GDALDestroyGenImgProjTransformer(psWo->pTransformerArg);
GDALDestroyWarpOptions( psWo );
GDALClose((GDALDatasetH) pDSrc);
GDALClose((GDALDatasetH) pDDst);
return 0;
}
用法示例:
ResampleGDAL("F:\\Work\\\\数据\\spline.tif",
"F:\\Work\\数据\\Resample_Lanczos.tif",GRA_Lanczos,10,10);
ResampleGDAL("F:\\Work\\数据\\test.tif",
"F:\\Work\\数据\\Resample3.tif",GRA_Lanczos,3,3);
缺陷:没有投影就不能重采样,关键点在于:GDALCreateGenImgProjTransformer取到的是null,根据gdal源代码,如果没有投影,dGeoTrans[] = {0,1,0,0,0,1},这个时候GDALCreateGenImgProjTransformer就返回null,因此可以将dGeoTrans[0]或dGeoTrans[3]设置为非0,这样GDALCreateGenImgProjTransformer就不返回null了。
改进: 【GDAL|GDAL影像重采样】
/***
* 遥感影像重采样
* @param pszSrcFile输入文件的路径
* @param pszOutFile写入的结果图像的路径
* @param eResample采样模式,有五种,具体参见GDALResampleAlg定义,默认为双线性内插
GRA_NearestNeighbour=0最近邻法,算法简单并能保持原光谱信息不变;缺点是几何精度差,灰度不连续,边缘会出现锯齿状
GRA_Bilinear=1双线性法,计算简单,图像灰度具有连续性且采样精度比较精确;缺点是会丧失细节;
GRA_Cubic=2三次卷积法,计算量大,图像灰度具有连续性且采样精度高;
GRA_CubicSpline=3三次样条法,灰度连续性和采样精度最佳;
GRA_Lanczos=4分块兰索斯法,由匈牙利数学家、物理学家兰索斯法创立,实验发现效果和双线性接近;
* @param fResXX转换采样比,默认大小为1.0,大于1图像变大,小于1表示图像缩小。数值上等于采样后图像的宽度和采样前图像宽度的比
* @param fResYY转换采样比,默认大小为1.0,大于1图像变大,小于1表示图像缩小。数值上等于采样后图像的高度和采样前图像高度的比
* @retrieve0成功
* @retrieve-1打开源文件失败
* @retrieve-2创建新文件失败
* @retrieve-3处理过程中出错
*/
int ResampleGDAL(const char* pszSrcFile, const char* pszOutFile, float fResX = 1.0 ,float fResY= 1.0,GDALResampleAlg eResample = GRA_Bilinear)
{
GDALAllRegister();
CPLSetConfigOption("GDAL_FILENAME_IS_UTF8","NO");
GDALDataset *pDSrc = https://www.it610.com/article/(GDALDataset *)GDALOpen(pszSrcFile, GA_ReadOnly);
if (pDSrc == NULL)
{
return -1;
}GDALDriver *pDriver = GetGDALDriverManager()->GetDriverByName("GTiff");
if (pDriver == NULL)
{
GDALClose((GDALDatasetH) pDSrc);
return -2;
}
int width=pDSrc->GetRasterXSize();
int height=pDSrc->GetRasterYSize();
int nBandCount = pDSrc->GetRasterCount();
GDALDataType dataType = pDSrc->GetRasterBand(1)->GetRasterDataType();
char *pszSrcWKT = NULL;
pszSrcWKT = const_cast(pDSrc->GetProjectionRef());
double dGeoTrans[6] = {0};
int nNewWidth=width,nNewHeight=height;
pDSrc->GetGeoTransform(dGeoTrans);
bool bNoGeoRef = false;
double dOldGeoTrans0 = dGeoTrans[0];
//如果没有投影,人为设置一个
if(strlen(pszSrcWKT)<=0)
{
//OGRSpatialReference oSRS;
//oSRS.SetUTM(50,true);
//北半球东经120度
//oSRS.SetWellKnownGeogCS("WGS84");
//oSRS.exportToWkt(&pszSrcWKT);
//pDSrc->SetProjection(pszSrcWKT);
//
dGeoTrans[0]=1.0;
pDSrc->SetGeoTransform(dGeoTrans);
//bNoGeoRef = true;
}//adfGeoTransform[0] /* top left x */
//adfGeoTransform[1] /* w-e pixel resolution */
//adfGeoTransform[2] /* rotation, 0 if image is "north up" */
//adfGeoTransform[3] /* top left y */
//adfGeoTransform[4] /* rotation, 0 if image is "north up" */
//adfGeoTransform[5] /* n-s pixel resolution */dGeoTrans[1] = dGeoTrans[1] / fResX;
dGeoTrans[5] = dGeoTrans[5] / fResY;
nNewWidth = static_cast(nNewWidth*fResX+0.5);
nNewHeight = static_cast(nNewHeight*fResY+0.5);
//创建结果数据集
GDALDataset *pDDst = pDriver->Create(pszOutFile, nNewWidth, nNewHeight, nBandCount, dataType, NULL);
if (pDDst == NULL)
{
GDALClose((GDALDatasetH) pDSrc);
return -2;
}pDDst->SetProjection(pszSrcWKT);
pDDst->SetGeoTransform(dGeoTrans);
void *hTransformArg = NULL;
hTransformArg = GDALCreateGenImgProjTransformer2((GDALDatasetH) pDSrc, (GDALDatasetH) pDDst, NULL);
//GDALCreateGenImgProjTransformer((GDALDatasetH) pDSrc,pszSrcWKT,(GDALDatasetH) pDDst,pszSrcWKT,FALSE,0.0,1);
if (hTransformArg == NULL)
{
GDALClose((GDALDatasetH) pDSrc);
GDALClose((GDALDatasetH) pDDst);
return -3;
}GDALWarpOptions *psWo = GDALCreateWarpOptions();
psWo->papszWarpOptions = CSLDuplicate(NULL);
psWo->eWorkingDataType = dataType;
psWo->eResampleAlg = eResample;
psWo->hSrcDS = (GDALDatasetH) pDSrc;
psWo->hDstDS = (GDALDatasetH) pDDst;
psWo->pfnTransformer = GDALGenImgProjTransform;
psWo->pTransformerArg = hTransformArg;
psWo->nBandCount = nBandCount;
psWo->panSrcBands = (int *) CPLMalloc(nBandCount*sizeof(int));
psWo->panDstBands = (int *) CPLMalloc(nBandCount*sizeof(int));
for (int i=0;
ipanSrcBands[i] = i+1;
psWo->panDstBands[i] = i+1;
}GDALWarpOperation oWo;
if (oWo.Initialize(psWo) != CE_None)
{
GDALClose((GDALDatasetH) pDSrc);
GDALClose((GDALDatasetH) pDDst);
return -3;
}oWo.ChunkAndWarpImage(0, 0, nNewWidth, nNewHeight);
GDALDestroyGenImgProjTransformer(hTransformArg);
GDALDestroyWarpOptions( psWo );
if(bNoGeoRef)
{
dGeoTrans[0]=dOldGeoTrans0;
pDDst->SetGeoTransform(dGeoTrans);
//pDDst->SetProjection("");
}
GDALFlushCache( pDDst );
GDALClose((GDALDatasetH) pDSrc);
GDALClose((GDALDatasetH) pDDst);
return 0;
}
改进后:没有投影也可以过去,但是如果没有投影,输出结果会自动带上一个投影,并且这个投影信息去不掉。
推荐阅读
- C++入门十题
- MFC|gdal 图像金字塔
- GDAL功能模块列表
- 深入解析GDAL库的RasterIO()函数
- GDAL关于圆形,多边形的创建以及如何判断点位是否与图形相交
- c++|gdal2.2.3关闭数据集失败的问题
- 初学者的领悟|百分比截断方法增加图像对比度的原理
- 初学者的领悟|c++实现使用GDAL实现大幅影像的快速读取
- c++编程|最小子串覆盖