美文网首页
学习GDAL

学习GDAL

作者: 该用户丶不存在 | 来源:发表于2017-09-18 11:29 被阅读0次

    出入摄影测量与三维重建的大门,不免要接触对图像数据的处理。虽然现如今OpenCV3以其强大的算法和广泛的支持率傲视群雄,但谈到对图像的支持我们不得不提一提GDAL,这个老牌的图像处理的开源库。这篇学习笔记主要跟着这篇博文走(head first GDAL)可能需要科学上网,边看边学习吧。

    环境配置

    我之前已经写了用Clion配置GDAL的相关内容,因为暂时没有考虑到进行GDAL源码的调试和修改,我没有进行编译,只是下载的二进制库文件。这里也需要补充补充库的相关知识静态库和动态库

    影像

    GDAL中也叫做数据集,可以分为多波段影像个多数据集影像。数据集(Dataset)包含了元数据投影信息和波段等等信息。其中使用了WTK来表示投影:


    通过GetProjectionRef()获取数据集投影信息

    对于数据集内部。有两种方式可以表示栅格数据中像元的位置(图像中的某个点在影像中的序列号)和投影坐标系(不是经纬度,是投影到二维平面的地图坐标,二者可以通过地图投影进行相互转换)间的关系:一是放射变换,二是gcp点;放射变化由6参数实现, 可以通过GDALDataset::GetGeoTransform()获得放射变换参数数组。像元位置转换为投影坐标的公式为:

    六参数数组进行放射变换

    波段

    波段是真正存储数据的结构,GDAL中用GDALRasterBand类来表示单个波段。波段具有一些特殊的性质。

    栅格数据的读写

    项目可能暂时用不到矢量格式的读写,但是不涉及OGR的内容,但需要对栅格数据的读写做进一步的学习:
    GDAL为每种格式提供了一个驱动GDALDriver,他对每种对应的格式进行管理(读取创建删除重命名复制从已有数据创建数据集等)。因此需要在所有程序开头添加GDALAllRegister()函数以注册所有GDAL支持的数据驱动。

    数据读取

    数据读取步骤如下:打开数据集—>打开数据集下所需的波段—>读取数据。

    打开数据集

    使用 GDALOpen()GDALOpenShared()函数(同一线程中多个GDALOpenShared打开的是同一个dataset的引用,而在不同线程中返回的是不同的对象)。

    #include "gdal_priv.h"
    #include "cpl_conv.h"
    
    //...中间的程序
    
    //所有程序前先加上
    GDALAllRegister();
    //pszFilename代表文件名,GA_ReadOnly表示以只读方式打开
    //也可以使用GA_Update
    //GDALOpenShared和GDALOpen可以互换
    GDALDataset  *poDataset= (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );
    if( poDataset == NULL )
    {
        ...;//打开失败处理
    }
    

    打开波段

    需要注意GDAL波段起始索引为1(非0!)使用GDALDataset->GetRasterBand(int BandIndex)获取波段.

    #include "gdal_priv.h"
    #include "cpl_conv.h"
    //...中间的程序
    
    //所有程序前先加上
    GDALAllRegister();
    GDALDataset  *poDataset= (GDALDataset *) GDALOpen( pszFilename, GA_ReadOnly );//打开文件
    if( poDataset == NULL )
    {
        //...//打开失败处理
    }
    //打开数据集同上
    //获取影像相关信息
    int i,j,width,height,bandNum;
    width = inDS->GetRasterXSize();//影像宽度
    height = inDS->GetRasterYSize();//影像高度
    bandNum = inDS->GetRasterCount();//影像波段数量
    
    //将第一波段读入
    double *data = new double[width*height];
    GDALRasterBand *band = ds1->GetRasterBand(1);//获取第一波段,波段从1开始
    //如果是在循环内,需要注意,波段从1开始;
    //for(i=0;i < bandNum;i++){
    // GDALRasterBand *band = ds1->GetRasterBand(i+1);//这里注意下
    // ......对波段处理
    //}
    

    读取内容

    使用RasterIO函数获取波段中的具体内容,示例代码:

    ///CPLErr GDALRasterBand::RasterIO (
    ///@param eRWFlag,     //读取或者写入,GF_Read或GF_Write
    ///@param nXOff,       //起始点x坐标
    ///@param nYOff,       //起始点y坐标
    ///@param nXSize,      //所需读取(写入)块宽度
    ///@param nYSize,      //所读(写)块高度
    ///@param * pData,     //所读(写)数据,指针,
    ///@param nBufXSize,   //一般跟nXSize一致,用于缩放图像,
    ///                      图像将按nBufXSize/nXsize在x尺度缩放(会自动重采样)
    ///                     ,一般不需要调整
    ///@param nBufYSize,   //一般跟nYSize一致
    ///@param eBufType,    //与pData的实际类型一致,GDT_Float64
    ///                      代表double,其他的可以跳到定义查看
    ///@param nPixelSpace,
    ///                      设置为0为自动判断,一般设为0
    ///                      表示的是当前像素值和下一个像素值之间的间隔,单位是字节
    ///                      例:byte类型,就是1,double类型,就是8
    ///@param nLineSpace
    ///                      设置为0为自动判断,一般设为0
    ///                      表示的是当前行和下一行的间隔,,单位是字节
    ///                      例如,一行300像素,类型为int,此时就是300*4 = 1200
    ///@return             //是否成功,成功返回CE_None ,失败返回 CE_Failure
    CPLErr GDALRasterBand::RasterIO (
        GDALRWFlag eRWFlag,
        int     nXOff,
        int     nYOff,
        int     nXSize,
        int     nYSize,
        void * pData,
        int     nBufXSize,
        int     nBufYSize,
        GDALDataType    eBufType,
        int     nPixelSpace,
        int     nLineSpace
    )
    

    相关文章

      网友评论

          本文标题:学习GDAL

          本文链接:https://www.haomeiwen.com/subject/jfvvsxtx.html