出入摄影测量与三维重建的大门,不免要接触对图像数据的处理。虽然现如今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
)