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

GDAL使用(三)

admin3年前 (2021-02-09)代码相关7134

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#事件_Sample_1

事件模型的五个组成部分:1、事件的拥有者(event source,只能是对象或类)2、事件成员(event,成员)3、事件的响应者(event subscriber,对象)4、事件处理器(event handler,成员)--本质上是一个回调方法5、事件订阅--把事件...

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# 正则表达式(1)

C# 正则表达式(1)

用于匹配输入文本的模式string s = "this is a test!"; string res = Regex.Replace(s, "^",&nbs...

C# 正则表达式(2)

// pattan = @"[^ahou]"; 表示匹配除ahou之外的字符,^在表示反义 string res4 = Regex.Replace(s, @"[^ahou]",&...

C# 测量运行时间

使用Stopwatch类进行运行时间的监测要使用 System.Diagnostics 命名空间方法表 4Reset()停止时间间隔测量,并将运行时间重置为零。Restart()停止时间间隔测量,将运行时间重置为零,然后开始测量运行时间。Start()开始或继续测量某个时间间隔的运行时间。...

C# 多线程(1)

一、首先看几个词的含义:进程:进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础。线程:线程(Thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的...