随着遥感、GIS的不断发展,GDAL这个库也越来越重要,很多人都开启了学习GDAL之旅,本文就介绍了GDAL的基础知识和利用GDAL读取影像信息的c++和python代码。
GDAL(Geospatial Data Abstraction Library)是一个在X/MIT许可协议下的开源栅格空间数据转换库。它利用抽象数据模型来表达所支持的各种文件格式。它还有一系列命令行工具来进行数据转换和处理。OGR是GDAL项目的一个分支,功能与GDAL类似,只不过它提供对矢量数据的支持。有很多著名的GIS类产品都使用了GDAL/OGR库,包括ESRI的ARCGIS 9.3,Google Earth和跨平台的GRASS GIS系统。利用GDAL/OGR库,可以使基于Linux的地理空间数据管理系统提供对矢量和栅格文件数据的支持。
实际上就是说,GDAL是一个我们用来在代码端读取、处理和操纵栅格数据的库,OGR是一个我们用来在代码端读取、处理和操纵矢量数据的库。
GDAL提供了C/C++接口,并且通过SWIG提供了Python,Java,C#等的调用接口。当我们在Python中调用GDAL的API函数时,其实底层执行的是C/C++编译的二进制文件。
GDAL中使用dataset表示一个栅格数据(使用抽象类GDALDataset表示),一个dataset包含了对于栅格数据的波段,空间参考以及元数据等信息。一张GeoTIFF遥感影像,一张DEM影像,或者一张土地利用图,在GDAL中都是一个GDALDataset。影像主要包括如下属性:
代码如下(示例):
#include //包含输入/输出流处理的头文件,一般属于c++代码必写
#include //有GDAL相关库函数的声明,属于引用GDAL库必写头文件
using namespace std; //与#include 同时出现,比如cout就属于std名字空间
//仿射变换(后面会讲它的用处)
void toGeoCoord(int x, int y, double* coords, double* transform)
{
coords[0] = transform[0] + x * transform[1] + y * transform[2];
coords[1] = transform[3] + x * transform[4] + y * transform[5];
}
int readRaster()
{
GDALAllRegister(); // 注册所有支持的数据格式驱动
//定义GDAL数据集,并以只读模式打开给定的数据文件
GDALDataset* dataset;
dataset = (GDALDataset*)GDALOpen("./xiayou_2014.tif", GA_ReadOnly);//修改你的文件路径
//设置读取影像不存在时的反馈
if (!dataset)
{
cout << "影像读取失败!" << '\n';
return EXIT_FAILURE;
}
// 获取影像行列数和波段数
int nRows = dataset->GetRasterYSize();//影像的高度(像元数目),行数
int nCols = dataset->GetRasterXSize();//影像的宽度(像元数目),列数
int nBandCount = dataset->GetRasterCount(); // 影像波段数
cout << "图像大小:(" << nCols << ", " << nRows << ")" << endl;//arcgis中列在前
cout << "波段数:" << nBandCount << endl;
//获取仿射变换六参数信息
/*
六参数其实是图像行列号坐标和地理坐标转换的一组转换系数。下面是用GT来表示六参数,
图像行列号与图像的地理坐标之间的数学关系式如下:
Xgeo = GT(0) + Xpixel*GT(1) + Yline*GT(2)
Ygeo = GT(3) + Xpixel*GT(4) + Yline*GT(5)
上式中,Xgeo和Ygeo表示的图像的地理坐标,Xpixel表示图像的列号,Yline表示图像的行号,
GT(i)就是上面所说的六参数,一共是六个值:
GT(0)和GT(3)是第一组,表示图像左上角的地理坐标;
GT(1)和GT(5)是第二组,表示图像横向和纵向的分辨率(一般这两者的值相等,符号相反,
横向分辨率为正数,纵向分辨率为负数);
GT(2)和GT(4)是第三组,表示图像旋转系数,对于一般图像来说,这两个值都为0。
*/
double adfGeoTransform[6];
dataset->GetGeoTransform(adfGeoTransform);
//通过仿射变换将影像左上角和右下角行列号坐标转化为地理坐标
double adfULCoord[2];
double adfLRCoord[2];
toGeoCoord(0, 0, adfULCoord, adfGeoTransform);
toGeoCoord(nCols - 1, nRows - 1, adfLRCoord, adfGeoTransform);
cout << std::fixed; // 对于double类型的数据可以使其正常输入,阻止默认的科学计数法输出
cout << "左上角坐标:(" << adfULCoord[0] << ", " << adfULCoord[1] << ")" <<endl;
cout << "右下角坐标:(" << adfLRCoord[0] << ", " << adfLRCoord[1] << ")" <<endl;
//获取投影信息
const char* pszProj = dataset->GetProjectionRef(); // 获得WKT形式的投影信息
cout << "投影信息:" << pszProj << endl;
//关闭数据集
GDALClose(dataset);
return EXIT_SUCCESS;
}
int main()
{
readRaster();
return 0;
}
代码如下:
import numpy as np
from osgeo import gdal,gdal_array
import cv2
import matplotlib.pyplot as plt
代码如下:
data = gdal.Open(r"E:/sentinel2_2020.tif")
print(data.GetDescription) #数据描述
print(data.RasterCount) #波段数
print(data.GetGeoTransform()) #获取仿射矩阵信息
print(data.GetProjection()) #获取投影信息
cols=data.RasterXSize #cols
rows=data.RasterYSize #rows
#RGB显示数据、:以numpy形式
band4=data.GetRasterBand(4) #从1开始计数,取第四波段
band3=data.GetRasterBand(3)
band2=data.GetRasterBand(2)
r = band4.ReadAsArray(0,0,cols,rows)
g = band3.ReadAsArray(0,0,cols,rows)
b = band2.ReadAsArray(0,0,cols,rows)
# r=band4.ReadAsArray(xoffset,yoffset,1000,1000) #从数据的中心位置开始,取1000行1000列数据
# g=band3.ReadAsArray(xoffset,yoffset,1000,1000)
# b=band2.ReadAsArray(xoffset,yoffset,1000,1000)
img2=cv2.merge([r,g,b])
plt.imshow(img2)
plt.xticks([]),plt.yticks([]) #不显示坐标轴
plt.show()
以上就是今天要讲的内容,本文仅仅简单介绍了GDAL的使用,而GDAL提供了大量能使我们快速便捷地处理栅格数据的函数和方法。