当前位置:首页 > 代码相关 > 正文内容

GDAL使用(三)

admin4年前 (2021-02-09)代码相关8440

GDALWarp的功能比较强大,可用于影像投影/重投影、图像镶嵌、重采样、规则裁切、图像校正等。

GDALWarp API定义在头文件gdalwarper.h中。主要有两部分构成:

GDALWarpOptionsGDALWarpOperation

如字面意思,GDALWarpOperation主要用来执行变换操作,GDALWarpOptions主要是对变换的一些选项进行设置。

1、GDALWarpOptions

这是个结构体,在头文件中的定义如下:

点击查看结构体
/************************************************************************/
/*                           GDALWarpOptions                            */
/************************************************************************/

/** Warp control options for use with GDALWarpOperation::Initialize()  */
typedef struct {

    char              **papszWarpOptions;

    /*! In bytes, 0.0 for internal default */
    double              dfWarpMemoryLimit;

    /*! Resampling algorithm to use */
    GDALResampleAlg     eResampleAlg;

    /*! data type to use during warp operation, GDT_Unknown lets the algorithm
        select the type */
    GDALDataType        eWorkingDataType;

    /*! Source image dataset. */
    GDALDatasetH        hSrcDS;

    /*! Destination image dataset - may be NULL if only using GDALWarpOperation::WarpRegionToBuffer(). */
    GDALDatasetH        hDstDS;

    /*! Number of bands to process, may be 0 to select all bands. */
    int                 nBandCount;

    /*! The band numbers for the source bands to process (1 based) */
    int                *panSrcBands;

    /*! The band numbers for the destination bands to process (1 based) */
    int                *panDstBands;

    /*! The source band so use as an alpha (transparency) value, 0=disabled */
    int                nSrcAlphaBand;

    /*! The dest. band so use as an alpha (transparency) value, 0=disabled */
    int                nDstAlphaBand;

    /*! The "nodata" value real component for each input band, if NULL there isn't one */
    double             *padfSrcNoDataReal;
    /*! The "nodata" value imaginary component - may be NULL even if real
      component is provided. This value is not used to flag invalid values.
      Only the real component is used. */
    double             *padfSrcNoDataImag;

    /*! The "nodata" value real component for each output band, if NULL there isn't one */
    double             *padfDstNoDataReal;
    /*! The "nodata" value imaginary component - may be NULL even if real
      component is provided. Note that warp operations only use real component
      for flagging invalid data.*/
    double             *padfDstNoDataImag;

    /*! GDALProgressFunc() compatible progress reporting function, or NULL
      if there isn't one. */
    GDALProgressFunc    pfnProgress;

    /*! Callback argument to be passed to pfnProgress. */
    void               *pProgressArg;

    /*! Type of spatial point transformer function */
    GDALTransformerFunc pfnTransformer;

    /*! Handle to image transformer setup structure */
    void                *pTransformerArg;

    /** Unused. Must be NULL */
    GDALMaskFunc       *papfnSrcPerBandValidityMaskFunc;
    /** Unused. Must be NULL */
    void              **papSrcPerBandValidityMaskFuncArg;

    /** Unused. Must be NULL */
    GDALMaskFunc        pfnSrcValidityMaskFunc;
    /** Unused. Must be NULL */
    void               *pSrcValidityMaskFuncArg;

    /** Unused. Must be NULL */
    GDALMaskFunc        pfnSrcDensityMaskFunc;
    /** Unused. Must be NULL */
    void               *pSrcDensityMaskFuncArg;

    /** Unused. Must be NULL */
    GDALMaskFunc        pfnDstDensityMaskFunc;
    /** Unused. Must be NULL */
    void               *pDstDensityMaskFuncArg;

    /** Unused. Must be NULL */
    GDALMaskFunc        pfnDstValidityMaskFunc;
    /** Unused. Must be NULL */
    void               *pDstValidityMaskFuncArg;

    /** Unused. Must be NULL */
    CPLErr              (*pfnPreWarpChunkProcessor)( void *pKern, void *pArg );
    /** Unused. Must be NULL */
    void               *pPreWarpProcessorArg;

    /** Unused. Must be NULL */
    CPLErr              (*pfnPostWarpChunkProcessor)( void *pKern, void *pArg);
    /** Unused. Must be NULL */
    void               *pPostWarpProcessorArg;

    /*! Optional OGRPolygonH for a masking cutline. */
    void               *hCutline;

    /*! Optional blending distance to apply across cutline in pixels, default is zero. */
    double              dfCutlineBlendDist;

} GDALWarpOptions;

下面对结构体的成员进行说明:

  1. papszWarpOptions

    char** 类型,控制warp操作,是格式为“name=value”的字符串数组,可以使用CSLSetNameValue()来构造该字符数组。选项的具体说明见如下链接:https://www.osgeo.cn/gdal/api/gdalwarp_cpp.html#_CPPv4N15GDALWarpOptions16papszWarpOptionsE

  2. dfMemoryLimit 

    double 类型,用于指定图像变换时使用的内存大小,单位为字节,为0.0时系统内部自动分配

  3. eResampleAlg 

    GDALResampleAlg 类型,指示变换时的重采样方法,包含了大部分常用的重采样方法,具体方法见以下链接:

    https://www.osgeo.cn/gdal/api/gdalwarp_cpp.html?highlight=gdalwarpoptions#_CPPv415GDALResampleAlg

  4. eWorkingDataType 

    GDALDataType 类型,指示在图像变换时使用的数据类型。设置为GDT_Unknown时算法自动选择数据类型。类型的具体说明见以下链接:

    https://www.osgeo.cn/gdal/api/raster_c_api.html#_CPPv412GDALDataType

  5. hSrcDS 

    GDALDatasetH 格式,原始影像数据集。

  6. hDstDS 

    GDALDatasetH格式,目标数据集。

  7. nBandCount 

    int 类型,要处理的波段数目,如果为0,将处理所有波段。

  8. panSrcBands 

    int* 类型,指定要处理的原始图像的波段序号,序号从1开始。

  9. panDstBands 

    int* 类型,指定要处理的原结果图像的波段序号,序号从1开始。

  10. nSrcAlphaBand 

    int 类型,指定原始图像所 使用的Alpha 通道( 透明 通道)序号, 默认值为0,表示 没有。

  11. nDstAlphaBand 

    int 类型,指定结果图像所使用的 Alpha 通道( 透明 通道)序号,默认值 为 0,表示没有。

  12. padfSrcNoDataReal 

    double* 类型,该变量指定原始图像中实部的NoData值,NULL表示没有(对于复数图像来说)。

  13. padfSrcNoDataImag 

    double* 类型,该变量指定原始图像中虚部的NoData值,NULL表示没有(对于复数图像来说)。

  14. padfDstNoDataReal 

    double* 类型,该变量指定结果图像中实部的NoData值,NULL表示没有(对于复数图像来说)。

  15. padfDstNoDataImag 

    double* 类型,该变量指定结果图像中虚部的NoData值,NULL表示没有(对于复数图像来说)。

  16. pfnProgress 

    GDALProgressFunc 类型,进度条信息函数指针

  17. pProgressArg 

    void* 类型,进度条函数的参数指针。

  18. pfnTransformer 

    GDALTransformerFunc 类型,图像坐标变换函数指针,这是核心函数,用来确定图像变换的方式。

  19. pTransformerArg 

    void* 类型,图像坐标变换函数所需要的结构体指针参数。

  20. hCutline 

    void* 类型,该变量使用OGRPolygonH指定 一个裁切范围,作为掩码区域。默认为 NULL,表示 处理全图。

  21. dfCutlineBlendDist 

    double 类型,该变量指定在使用hCutline作为掩码区域时的羽化距离。默认为0。

最后,这个结构体指针可以使用GDALCreateWarpOption()函数进行创建,这个函数的返回值直接就是GDALWarpOptions*类型。

2、GDALWarpOperation

是负责对图像进行读取、分块和写入操作的

  1. 函数:Initialize

    原型:CPLErr Initialize(constGDALWarpOptions *psNewOptions)

    参数:psNewOptions:constGDALWarpOptions *类型,就是上面一节说的结构体指针。

    返回值:是否初始化成功

  2. 函数:GetOptions 

    原型:const GDALWarpOptions *GetOptions()

    返回值:返回上一节说的结构体指针

  3. 函数:ChunkAndWarpImage 

    原型:CPLErr ChunkAndWarpImage(int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize)

    参数:nDstXOff:结果数据X起始坐标,字面意思就是X方向的偏移量,nDstYOff:结果数据Y起始坐标,nDstXSize:结果数据宽度,nDstYSize:结果数据高度

    返回值:是否执行成功

  4. 函数:ChunkAndWarpMulti 

    原型:CPLErr ChunkAndWarpMulti(int nDstXOff, int nDstYOff, int nDstXSize, int nDstYSize)

    参数与返回值与第三条中的一样,功能也相同,不过内部是多线程操作的

其它函数参考下面链接:

https://www.osgeo.cn/gdal/api/gdalwarp_cpp.html#classGDALWarpOperation

3、重投影代码

这里的例子是将一幅未投影影像投影到投影坐标下。

原始数据:海洋一号C卫星(HY-1C)L1C数据,此原始数据为WGS84坐标系,一共4个波段。

目标数据:这里目标是将原始数据投影到投影坐标系下,目标空间参考为 Asia North Albers Equal Area Conic,此坐标系为WGS84椭球下的等积圆锥投影,且数据的分辨率约为50m,这里让GDAL自己计算合适的分辨率。

#include <iostream>
#include "gdal_priv.h"
#include "cpl_conv.h" 
#include <cpl_string.h>
#include <gdalwarper.h>

int main()
{
	clock_t start = clock();
	GDALAllRegister();
	GDALDriverH hDriver;
	GDALDataType eDT;
	GDALDatasetH hDstDS;
	GDALDatasetH hSrcDS;
	// 打开源文件
	hSrcDS = GDALOpen("E:\testdata\CZIOrigin.tiff", GA_ReadOnly);
	CPLAssert(hSrcDS != NULL);
	// 获取数据类型
	eDT = GDALGetRasterDataType(GDALGetRasterBand(hSrcDS, 1));
	// 获取输入数据的栅格驱动 (GeoTIFF格式)
	hDriver = GDALGetDriverByName("GTiff");
	CPLAssert(hDriver != NULL);
	// 获取源数据坐标系统
	const char* pszSrcWKT;
	char* pszDstWKT = NULL;
	pszSrcWKT = GDALGetProjectionRef(hSrcDS);
	CPLAssert(pszSrcWKT != NULL && strlen(pszSrcWKT) > 0);
	// 设置输出坐标系为
	OGRSpatialReference oSRS;
	oSRS.importFromProj4("+proj=aea +lat_1=15 +lat_2=65 +lat_0=30 +lon_0=95 +x_0=0 +y_0=0 +datum=WGS84 +units=m +no_defs");
	oSRS.exportToWkt(&pszDstWKT);
	printf("%s
", pszDstWKT);
	// Create a transformer that maps from source pixel/line coordinates
	// to destination georeferenced coordinates (not destination
	// pixel line). We do that by omitting the destination dataset
	// handle (setting it to NULL).
	void* hTransformArg = GDALCreateGenImgProjTransformer(hSrcDS, pszSrcWKT, NULL, pszDstWKT, FALSE, 0, 1);
	CPLAssert(hTransformArg != NULL);
	//计算大概的范围和分辨率
	double adfDstGeoTransform[6];
	int nPixels = 0, nLines = 0;
	CPLErr eErr;
	eErr = GDALSuggestedWarpOutput(hSrcDS, GDALGenImgProjTransform, hTransformArg, adfDstGeoTransform, &nPixels, &nLines);
	CPLAssert(eErr == CE_None);
	// 创建输出文件
	hDstDS = GDALCreate(hDriver, "O:\CZIproject.tif", nPixels, nLines, GDALGetRasterCount(hSrcDS), eDT, NULL);
	CPLAssert(hDstDS != NULL);
	//设置投影
	GDALSetProjection(hDstDS, pszDstWKT);
    //设置地理变换参数
	GDALSetGeoTransform(hDstDS, adfDstGeoTransform);
	//如果需要的话,复制颜色表
	GDALColorTableH hCT;
	hCT = GDALGetRasterColorTable(GDALGetRasterBand(hSrcDS, 1));
	if (hCT != NULL)
		GDALSetRasterColorTable(GDALGetRasterBand(hDstDS, 1), hCT);

	//设置warp选项
	GDALWarpOptions* psWarpOptions = GDALCreateWarpOptions();
	psWarpOptions->hSrcDS = hSrcDS;//设置源数据集
	psWarpOptions->hDstDS = hDstDS;//设置目的数据集
	psWarpOptions->nBandCount = 0;//要处理的波段数,0的话是选择所有波段
	psWarpOptions->pfnProgress = GDALTermProgress;//控制台进度条函数
	//建立重投影变换
	psWarpOptions->pTransformerArg = GDALCreateGenImgProjTransformer(hSrcDS, GDALGetProjectionRef(hSrcDS), hDstDS, GDALGetProjectionRef(hDstDS), FALSE, 0.0, 1);
	psWarpOptions->pfnTransformer = GDALGenImgProjTransform;
	//初始化并执行warp操作
	GDALWarpOperation oOperation;
	oOperation.Initialize(psWarpOptions);
	oOperation.ChunkAndWarpImage(0, 0, GDALGetRasterXSize(hDstDS), GDALGetRasterYSize(hDstDS));//这是实际执行warp的函数
    //释放资源
	GDALDestroyGenImgProjTransformer(hTransformArg);
	GDALClose(hDstDS);
	GDALClose(hSrcDS);

	clock_t end = clock();
	double endtime = (double)(end - start) / CLOCKS_PER_SEC;
	printf("time elapse: %f
", endtime);
	system("pause");
	return 0;
}

下面的是投影前后的空间参考信息,可以看到GDAL自己计算出的像元大小约为46.2250m

image.pngimage.png



以上部分内容参考:

[1] 李民录. GDAL源码剖析与开发指南(异步图书). 人民邮电出版社. Kindle 版本. 

[2] https://www.osgeo.cn/gdal/index.html

扫描二维码推送至手机访问。

版权声明:本文由lovedm.club发布,如需转载请注明出处。

本文链接:https://lovedm.club/?id=118

标签: GDAL
分享给朋友:

“GDAL使用(三)” 的相关文章

C# Lambda表达式

简单用法,一句一句来,便于理解 Func<int, int, int> func = new Func<int, int, int>((int a, int b) => { return a * b; });(int a, int b) => { ret...

C语言scanf一个容易出错的地方

今天用scanf()写一个数组循环输入,运行时很奇怪,明明只需要输入三个数,但是实际上要多输入一个,瞅了好一会才看到我是这么写的scanf("%d ",&p[i]);问题就出在这个 上,写printf()写习惯了,顺手就加上了 ,注意不要加!不要加!...

C语言 异或运算符 ^

C语言中异或运算符^表示参见运算的二进制运算符相同为0,不同为1,如下:1 ^ 1 = 01 ^ 0 = 10 ^ 1 = 10 ^ 0 = 0下面举例说明∧运算符的应用:  (1)使特定位翻转  假设有01111010,想使其低4位翻转,即1变为0,0变为1。可以将它与00001111进行∧运算,...

C语言结构体

C语言的结构(struct)是一种复杂的数据类型,可以包含多种数据类型,基本类型都能包含,但是不能包含函数,这是和C++中的结构不同的地方,但是可以包含函数指针,但是这也并不矛盾,因为本身指针指向的是一个地址,也是一个变量。下面是结构的定义的示例:struct Name {  ...

C# 多线程(2)

C# 多线程(2)

Thread类中的join方法:微软官方解释:Join 一个同步方法,该方法阻止调用线程 (即,调用方法的线程) ,直到 Join 调用方法的线程完成。 使用此方法可以确保线程已终止。using System; using System....

C#解析JSON

C#解析JSON

首先使用nuget搜索json,如下图选择第一个包安装。然后引用命名空间 using Newtonsoft.Json;以下面的JSON文件为例子解析:{"page":1,"results":[ {   "adult&qu...