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

GDAL使用(三)

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

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发布,如需转载请注明出处。

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

标签: GDAL
分享给朋友:

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

C# 使用不安全的代码

首先需要在 项目->属性->生成 中勾选允许不安全代码下面的代码使用了指针,通过指针修改结构体的成员namespace _20200320 {     class Program   &nbs...

C# try-catch处理异常

使用try-catch进行异常处理,下面是两个小例子:两个例子中没有写finally语句finally的作用是无论有无异常,finally下的语句都会执行。//简单的处理异常namespace _20200323 {     class ...

C# 委托

C# 委托

Action和Func是.NET类库的内置委托,以简便使用。Func有17个重载还可以使用delegate关键字创建委托下面的代码展示了这三种使用委托的方法namespace _20200327 {     public delegat...

C# 使用FileStream进行文件复制操作

使用文件流进行操作,如下,其中注释部分是和非注释部分一样的,但是使用using语句是执行完后自动释放内存,而注释部分是手动释放。CopyFile方法中,缓冲区大小设为1024*1024字节,也就是1MB,Read方法和Write方法中,第一个参数都是缓冲区数组,第二个参数都是偏移量,这个量是在缓冲区...

C#(或者Java)反转数组

将原数组反转,如[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]反转后变为[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]因为数组是引用类型,所以直接在方法中处理即可,C#和Java写法一样,如下:      &nb...

C# 抽象类与接口的比较

相同:都不能被实例化都包含未实现的方法派生类必须实现未实现的方法不同:抽象类可以包含抽象成员,也可以包含非抽象成员,即抽象类可以是完全实现的,也可以是部分实现的,或者是完全不实现的。接口更像是只包含抽象成员的抽象类,或者说接口内的成员都是未被实现的。一个类只能继承一个抽象类(当然其它类也一样),但是...