GDAL学习1:初识GDAL以及读取处理保存影像信息

GDAL学习1:初识GDAL以及读取影像信息

  • 前言
  • 一、GDAL是什么?
    • 栅格数据组织
  • 二、使用C++ GDAL3读取栅格数据
    • 1.引入库
    • 2.读取影像及信息函数
    • 3.主函数
  • 三、使用python GDAL读取栅格数据
    • 1.引入包
    • 2.读取影像及信息
  • 总结


前言

随着遥感、GIS的不断发展,GDAL这个库也越来越重要,很多人都开启了学习GDAL之旅,本文就介绍了GDAL的基础知识和利用GDAL读取影像信息的c++和python代码。


一、GDAL是什么?

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。影像主要包括如下属性:

  • 坐标系统(使用OGC WKT格式表示的空间坐标系统或者投影系统)
  • 地理仿射变换(使用仿射变换表示图上坐标和地理坐标的关系)
  • GCPs(大地控制点记录了图上点及其大地坐标的关系,通过多个大地控制点可以重建图上坐标和地理坐标的关系)
  • 元数据(键值对的集合,用于记录和影像相关的元数据信息)
  • 栅格波段(使用GDALRasterBand类表示,真正用于存储影像栅格值,一个栅格数据可以有多个波段)
  • 颜色表(Color Table用于图像显示)

二、使用C++ GDAL3读取栅格数据

1.引入库

代码如下(示例):

#include                //包含输入/输出流处理的头文件,一般属于c++代码必写
#include             //有GDAL相关库函数的声明,属于引用GDAL库必写头文件
using namespace std;              //与#include 同时出现,比如cout就属于std名字空间

2.读取影像及信息函数

//仿射变换(后面会讲它的用处)
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;
}

3.主函数

int main()
{
    readRaster();
    return 0;
}

三、使用python GDAL读取栅格数据

1.引入包

代码如下:

import numpy as np
from osgeo import gdal,gdal_array
import cv2
import matplotlib.pyplot as plt

2.读取影像及信息

代码如下:

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提供了大量能使我们快速便捷地处理栅格数据的函数和方法。

你可能感兴趣的:(C++,GDAL学习之旅,python,c++,gdal,经验分享)