GDAL源码剖析(九)之GDAL体系架构

GDAL源码剖析(九)之GDAL体系架构_gdal 源码-CSDN博客

  在GDAL库中包含栅格数据的读写,矢量数据的读写,以及栅格和矢量数据的相关算法。下面主要对GDAL中栅格数据和矢量数据的体系架构做一个简单的说明。本人英文很烂,有些部分写出来的东西自己都看不懂,如果不懂,可以看英文。

一、GDAL体系架构

      参考GDAL官方文档:http://www.gdal.org/gdal_datamodel.html。

      GDAL使用抽象数据模型(abstract data model)来解析它所支持的数据格式,抽象数据模型包括数据集(dataset),坐标系统(Coordinate System),仿射地理坐标转换(Affine GeoTransform), 大地控制点(GCPs), 元数据(Metadata),子数据集域(Subdatasets Domain),图像结构域(Image_Structure Domain),RPC域(RPC Domain),XML域(XML:Domains),栅格波段(Raster Band),颜色表(Color Table)和快视图(Overviews)。


1、数据集(Dataset)

      数据集是由栅格波段和一些相关的信息共同组成的(具体参考GDALDataset类),在一个指定的数据集中所有的波段都具有相同的大小(图像行数和列数);数据集同时负责对所有的波段定义地理坐标和投影等信息;数据集中还有一些元数据信息,这些信息是由字符串组成的一系列(名称:值)的字符串列表。

      GDAL数据集是基于OpenGIS网格数据的说明来实现的。

2、坐标系统(CoordinateSystem)

数据集中的坐标系统是基于OpenGIS的WKT(WellKnown Text)字符串格式的。里面包含下面内容:

    坐标系统名称
    地理坐标系统名称
    大地水准面
    托球体名称,长半轴和扁率
    中央经线名称和与本初子午线的偏移量
    投影方式(如:横轴墨卡托)
    投影参数列表(如:中央经线)
    单位名称和与米或者弧度之间的转换系数
    名称和坐标轴顺序
    以上项对应的EPSG代码

更多关于OpenGIS的WKT坐标定义和相关信息,可以参考文档osr_tutorial。获取坐标系统可以使用函数 GDALDataset::GetProjectionRef(),如果该函数的返回值为"",说明该图像没有地理坐标系统。

1、仿射地理坐标转换(Affine GeoTransform)

GDAL数据集有两种方式来表示栅格行列号坐标和地理坐标之间的关系,第一种,也是最常用的,就是使用仿射变换来表示(另外一种是GCP点)。

仿射变换包含六个参数,可以使用函数 GDALDataset::GetGeoTransform()获取,图像行列号和地理空间之间的变换关系如下:

    Xgeo = GT(0) + Xpixel*GT(1) + Yline*GT(2)

    Ygeo = GT(3) + Xpixel*GT(4) + Yline*GT(5)

在北方向上的图像中,参数GT(2)和GT(4)的值是0,GT(1)表示象元宽度,GT(5)表示象元高度。点 (GT(0),GT(3))表示图像左上角的横纵坐标值。

值得注意的是:行列号坐标系统中,图像的(0.0,0.0)坐标在图像的左上角,坐标(象元宽个数,象元高个数)表示图像的右下角坐标。图像的左上角象元的中心点坐标是(0.5,0.5)。

2、大地控制点(GCPs)

数据集中可能会包括一系列的控制点,用来确定图像的地理参考坐标。所有的控制点都是在同一个坐标系统下的(可以使用函数GDALDataset::GetGCPProjection()来获取该坐标系),每一个GCP(使用GDAL_GCP类来表示)包括下面的内容:

    typedef struct
    {
        char    *pszId;
        char    *pszInfo;
        double  dfGCPPixel;
        double  dfGCPLine;
        double  dfGCPX;
        double  dfGCPY;
        double  dfGCPZ;
    } GDAL_GCP;


pszId字符串表示一个唯一的字符串,用来藐视在当前数据集中的GCP点中的具体的GCP点(通常情况下,可能是由数字构成,但不是所有的情况下)。pszInfo通常是一个空字符串,但是可以用来存储用户自定义用来描述GCP的文本信息。很可能包含GCP的一些状态信息,如获取时间等。

坐标(Pixel,Line)表示GCP在图像上的位置,坐标(X,Y,Z)表示在地理参考坐标系中的位置,通常Z值是0。

GDAL数据模型中不会都包含GCP点构成的转换方程,这个工作常常在应用程序中处理。通常使用1次到5次多项式进行转换。

通常数据集包括一个仿射地理坐标变换,GCP点可能会有,有时候这两个都没有。

3、元数据(Metadata)

GDAL元数据是辅助格式和应用程序指定的数据使用一个名称/值的点对列表。名称需要能够很好的表示其作用(不含有空格或者其他特殊字符)。值可以有任意长度,可以包括任何东西除了空值(ASCII的0值)。

元数据在系统中不能处理太大的数据,如果元数据超过100kb就会导致性能下降。

一些常用的的格式的元数据都可以支持,比如在TIFF驱动返回一些了标签信息作为元数据,比如日期/时间的形式如下:

TIFFTAG_DATETIME=1999:05:11 11:29:56

元数据可以按照名称组来拆分为不同的域,默认域是没有名称的,如(NULL或者"")。一些特殊的域用于特殊的目的。

下面的元数据项目定义在默认的域中:

    AREA_OR_POINT: 可以是“Area”或者“Point”,默认为Area。表明一个像素值表示中心像元的像素值或者像元中心点的采样值。但这并不影响整个区域的地理参考信息。
    NODATA_VALUES:NODATA值。这个值是使用空格隔开的一系列的像素值,个数和波段数相同。使用这种方式是为了使所有波段都有一个NODATA值相匹配。这个元数据没有广泛的用于数据驱动,算法或者工具集中。
    MATRIX_REPRESENTATION:这个值用来表示极化SAR数据集,包含矩阵表示的数据。矩阵可以用下面的值来进行表示:
        SCATTERING 散射
        SYMMETRIZED_SCATTERING 对称散射
        COVARIANCE 协方差
        SYMMETRIZED_COVARIANCE 对称协方差
        COHERENCY 相干
        SYMMETRIZED_COHERENCY 对称相干
        KENNAUGH
        SYMMETRIZED_KENNAUGH
    POLARMETRIC_INTERP:这个元数据项用来定义多波段极化SAR数据的栅格波段。指定的矩阵表示这个波段的数据。数据集就是一个散射矩阵,比如,这个元数据可接受的值有,HH、HV、VH、VV四个。当数据集是一个协方差矩阵时,这个元数据将分别是Covariance_11、Covariance_22、Covariance_33、Covariance_12、Covariance_13、Covariance_23中的一个(因为这个矩阵本身就是一个Hermitian矩阵,即所有的数据都用来表示这个矩阵)。

4、子数据集域(Subdatasets Domain)

子数据集域中含有一个子数据集的列表。通常用来存储在一个文件的多个文件(如HDF和NITF格式),例如,一个NITF格式的文件中获取子数据集的信息如下:

SUBDATASET_1_NAME=NITF_IM:0:multi_1b.ntf

SUBDATASET_1_DESC=Image 1 of multi_1b.ntf

SUBDATASET_2_NAME=NITF_IM:1:multi_1b.ntf

SUBDATASET_2_DESC=Image 2 of multi_1b.ntf

SUBDATASET_3_NAME=NITF_IM:2:multi_1b.ntf

SUBDATASET_3_DESC=Image 3 of multi_1b.ntf

SUBDATASET_4_NAME=NITF_IM:3:multi_1b.ntf

SUBDATASET_4_DESC=Image 4 of multi_1b.ntf

SUBDATASET_5_NAME=NITF_IM:4:multi_1b.ntf

SUBDATASET_5_DESC=Image 5 of multi_1b.ntf

含有_NAME的字符串,可以使用GDALOpen()函数来进行访问子文件。含有_DESC字符串是用来方便的展示给用户选择哪个文件。

5、图像结构域(Image_Structure Domain)

在默认域的元数据用来描述图像的相关信息,这些元数据并没有以特殊的方式保存在磁盘中。意思就是说,当这些元数据信息被复制到一个新的图像中的时候,会以合适的方式存在新的图像中。此外还有一些信息是和图像的格式紧密关联的。为了防止这些信息在写入新图像的时候被复制,将这些信息存储在一个叫IMAGE_STRUCTURE的特殊域中,通常这里存储的东西不会写入到新的图像中去。

目标,在IMAGE_STRUCTURE域中定义的项目主要有下面几个。

    COMPRESSION:压缩方式用来指定数据集或者波段的压缩方式,这个是没有固定的压缩类型名称,但是一个指定的格式,如果指定压缩方式,那么在创建的时候会使用这种压缩方式进行压缩。
    NBITS:当前波段或者当前数据集的波段中真实的数据存储bit数。通常只有非标准的数据类型才会使用该值,比如TIFF图像中的1bit数据,在GDAL会使用GDT_Byte来表示。
    INTERLEAVE:这个只能用在数据集中,用来表示一个像元,一行和一个波段之间的间隔,可以用来作为读取数据的一个提示。
    PIXELTYPE:这个值会出现在一个GDT_Byte类型的波段(或者相应的数据集)中,并且会使用SIGNEDBYTE值来表示无符号byte值介于128和255之间值应该转换为-128到-1之间。

6、RPC域(RPCDomain)

RPC元数据域存储的是有理函数模型的系数,该模型表示从图像行列号与空间参考位置间的变换关系,该模型具体定义如下:

·          ERR_BIAS: 偏移误差,图像上所有的点在水平轴上的偏移的中误差,-1.0表示未知。

·          ERR_RAND: 随机误差,图像上所有的点在水平轴上的随机中误差,-1.0表示未知。

·          LINE_OFF: 行偏移量

·          SAMP_OFF: 列偏移量

·          LAT_OFF: 纬度偏移量

·          LONG_OFF: 经度偏移量

·          HEIGHT_OFF: 高程偏移量

·          LINE_SCALE: 行缩放比例

·          SAMP_SCALE: 列缩放比例

·          LAT_SCALE: 纬度缩放比例

·          LONG_SCALE: 经度缩放比例

·          HEIGHT_SCALE: 高程缩放比例

·          LINE_NUM_COEFF (1-20): 行分子系数,一共20个(使用空格隔开)

·          LINE_DEN_COEFF (1-20): 行分母系数,一共20个(使用空格隔开)

·          SAMP_NUM_COEFF (1-20): 列分子系数,一共20个(使用空格隔开)

·          SAMP_DEN_COEFF (1-20): 列分母系数,一共20个(使用空格隔开)

这些内容都是来自GeoTIFF的RPC文档(http://geotiff.maptools.org/rpc_prop.html)。

7、XML域(XML:Domains)

任何前缀是“xml:”的一个字符串,但不是名称/值这种类型的,这是一个简单的XML格式的长字符串。

8、栅格波段(Raster Band)

一个栅格波段在GDAL中使用GDALRasterBand类来进行表示。他表示一个栅格波段、通道或者图层。波段不能完全用来表示整个图像,比如一个24位的RGB图像中就含有三个波段,分别是红波段,绿波段和蓝波段。

栅格波段含有下面属性:

·           图像的宽和高,这个和数据集里面的定义一样,如果这个波段是全分辨率波段的话。(这里有个说明,GDALRasterBand还可以表示金字塔的波段,如果是金字塔的波段的话,里面的宽高就和图像的宽高不一样)。

·           数据类型(GDALDataType)。应该是Byte、UInt16、Int16、UInt32、Int32、Float32、Float64以及复数类型CInt16、CInt32、CFloat32和CFloat64中的一个。

·           块大小。通过块是读取数据最高效的方式,对于分块数据,就是一个分块大小,对于大多数图像来说,一块就是一行。

·           名称/值的元数据对,格式和数据集中的一员,但是包含的信息可能是波段特有的。

·           一个可选的波段描述字符串。

·           一个可选的用来描述NODATA值的像元值。

·           一个可选的NODATA值表示的掩码波段或者在某些时候作为透明通道。

·           可选的类别名称列表(用于分类图)

·           可选的最大值和最小值。

·           可选的偏移量和缩放比例,用来对图像的像素值进行变换,比如变换高度到米等。

·           图像单位名称,可选。比如可以用来表示高程数据的海拔。

·           波段的颜色信息,是下面值中的某一个:

o   GCI_Undefined:默认值,未知

o   GCI_GrayIndex: 灰度图像

o   GCI_PaletteIndex:颜色表图像

o   GCI_RedBand: RGBA图像的R部分

o   GCI_GreenBand: RGBA图像的G部分

o   GCI_BlueBand: RGBA图像的B部分

o   GCI_AlphaBand: RGBA图像的Alpha部分

o   GCI_HueBand: HLS图像的色调部分

o   GCI_SaturationBand: HLS图像的饱和度部分

o   GCI_LightnessBand:HLS图像的亮度部分

o   GCI_CyanBand: CMYK图像的青色部分

o   GCI_MagentaBand: CMYK图像的品红部分

o   GCI_YellowBand: CMYK图像的黄色部分

o   GCI_BlackBand: CMYK图像的黑色部。

·           颜色表,下面有更详细的说明。

·           如果金字塔可用,含有一些关于金字塔的信息。

9、颜色表(Color Table)

颜色表的定义如下,使用C语言的风格定义:

    typedef struct
    {
        /- gray, red, cyan or hue-/
        short      c1;
        /- green, magenta, orlightness -/   
        short      c2;
        /- blue, yellow, orsaturation -/
        short      c3;
        /- alpha or blackband -/
        short      c4;     
    } GDALColorEntry;

颜色表通常是颜色调色板的一个值,对于c1/c2/c3/c4 四个值对应不同的调色板,其表示的含义不同,具体表示见下:

l  GPI_Gray: 使用c1表示灰度值。

l  GPI_RGB: c1表示红色,c2表示绿色,c3表示蓝色,c4表示alpha通道。

l  GPI_CMYK: c1表示青色,c2表示洋红,c3表示黄色,c4表示黑色。

l  GPI_HLS: c1表示色调,c2表示亮度,c3表示饱和度。

通过颜色表,将象元值用颜色表中的颜色来进行表示,颜色表中的值是从0开始递增。

10、快视图(Overviews)

一个波段中可能没有或者有很多个快视图。每个快视图都是一个GDALRasterBand,略缩图大小将和其下层的栅格大小不一样,但是快视图表示的区域与整个图像的区域是一致的。

快视图是用来快速显示图像用的,使用全分辨率图像进行降采样得到。

波段可以通过函数HasArbitraryOverviews,返回TRUE表示可以快速读取任何分辨率的快视图,这个主要应用在一些如FFT编码的图像(这句有点别扭,自己看英文原文吧)。

11、GDAL核心类结构设计

GDAL的核心类结构设计如图所示:

其中的类说明如下:

GDALMajorObject类:带有元数据的对象。

GDALDdataset类:通常是从一个栅格文件中提取的相关联的栅格波段集合和这些波段的元数据;GDALDdataset也负责所有栅格波段的地理坐标转换(georeferencingtransform)和坐标系定义。

GDALDriver类:文件格式驱动类,GDAL会为每一个所支持的文件格式创建一个该类的实体,来管理该文件格式。

GDALDriverManager类:文件格式驱动管理类,用来管理GDALDriver类。

二、OGR体系架构

1、OGR体系结构

OGR包括如下几部分:

Geometry:类Geometry (包括OGRGeometry等类)封装了OpenGIS的矢量数据模型,并提供了一些几何操作,WKB(Well Knows Binary)和WKT(Well Known Text)格式之间的相互转换,以及空间参考系统(投影)。

Spatial Reference:类OGRSpatialReference封装了投影和基准面的定义。

Feature:类OGRFeature封装了一个完整feature的定义,一个完整的feature包括一个geometry和geometry的一系列属性。

Feature Definition:类OGRFeatureDefn里面封装了feature的属性,类型、名称及其默认的空间参考系统等。一个OGRFeatureDefn对象通常与一个层(layer)对应。

Layer:类OGRLayer是一个抽象基类,表示数据源类OGRDataSource里面的一层要素(feature)。

Data Source:类OGRDataSource是一个抽象基类,表示含有OGRLayer对象的一个文件或一个数据库。

Drivers:类OGRSFDriver对应于每一个所支持的矢量文件格式。类OGRSFDriver由类OGRSFDriverRegistrar来注册和管理。

2、OGR的Geometry模型

OGR的Geometry模型是建立在OpenGIS的简单要素数据模型之上的。如下图所示:

                                                图-OGR的Geometry模型关系图

OpenGIS的简单要素数据模型,其关系图如下所示:

                                                图-OpenGIS的简单要素数据模型

由上面两图的对比,可以清楚的看到,OGR的Geometry模型是严格遵循OpenGIS的简单要素数据规范的。OGR的Geometry模型不仅在继承体系上与OpenGIS的简单要素数据模型一致,在函数接口上也向其靠拢,从基本的获取Geometry对象信息的方法如Dimension ()、GeometryType ()、SRID ()、Envelope()、AsText()、Boundary()等到判定空间未知关系的方法如Equals(anotherGeometry:Geometry)、Disjoint(anotherGeometry:Geometry)、

Intersects(anotherGeometry:Geometry)、Touches(anotherGeometry:Geometry)等都是符合其标准的。

对于OGR库后面会专门进行说明,这里简单说明一下就好。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/792472.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux 多线程与线程控制(程序均有详细注释)

多线程与线程控制 线程的基本概念线程的特点页表多线程 线程控制线程的创建线程传参线程id资源回收---线程等待线程id和LWP 封装一个线程库线程互斥和线程同步线程互斥基本原理线程安全VS线程不安全锁的诞生可重入VS线程安全 死锁死锁的定义 线程同步条件变量接口 生成消费者模…

使用Python获取红某书笔记详情并批量无水印下载

根据红某手最新版 请求接口必须要携带x-s x-s-c x-t,而调用官方接口又必须携带cookie,缺一不可,获取笔记详情可以通过爬取网页的形式获取,虽然也是无水印,但是一些详情信息只能获取大概,并不是详细的数值,因此既不想自己破解x-s x…

清明时节雨纷纷,AI达人用Bedrock(第一季)

今天是清明小长假第一天,没有外出踏青,在家体验Amazon Bedrock的强大能力。Amazon Bedrock是专门为创新者量身打造的平台,它提供了构建生成式人工智能应用程序所需的一切。 这次我主要尝试的是通过 Amazon Bedrock 里的 Stability AI SDXL 1…

C++理解std::move和转发(std::forward)

理解 std::move 标准库move函数是使用右值引用的模板的一个很好的例子。 幸运的是,我们不必理解move所使用的模板机制也可以直接使用它。 但是,研究move是如何工作的可以帮助我们巩固对模板的理解和使用。 我们注意到,虽然不能直接将一个…

提升工作效率:B端工作台设计基础详解

随着互联网和信息技术的快速发展,越来越多的企业开始以数字化、智能化的方式管理和运营自己的业务。B端工作台设计作为企业应用的重要组成部分,越来越受到重视。本文将从三个方面对B端工作台设计进行全面分析。让我们看看。 1. B端工作台设计原则 B端工…

攻防世界 wife_wife

在这个 JavaScript 示例中,有两个对象:baseUser 和 user。 baseUser 对象定义如下: baseUser { a: 1 } 这个对象有一个属性 a,其值为 1,没有显式指定原型对象,因此它将默认继承 Object.prototype。 …

不堪大用的pow

【题目描述】 输出100~999中的所有水仙花数。若3位数ABC满足,则称其为水仙花 数。例如,所以153是水仙花数。 【题目来源】 刘汝佳《算法竞赛入门经典 第2版》习题2-1 水仙花数(daffodil) 题目很简单,…

配置vite配置文件更改项目端口、使用@别名

一、配置vite配置文件更改项目端口 vite官方文档地址:开发服务器选项 | Vite 官方中文文档 (vitejs.dev) 使用: 二、使用别名 1. 安装 types/node types/node 包允许您在TypeScript项目中使用Node.js的核心模块和API,并提供了对它们的类型…

picGo图床搭建gitee和smms(建议使用)

picGoGitee 这个需要下载gitee插件, 因为官方频繁的检索文件类型, 有时候也会失效 如果没有特殊要求平时存个学习的要看图中文字的重要的图片建议就是smms, 免费也够用! 图片存本地不方便, 各种APP中来回传还会失帧损失画质, 所以你值得往下看 picGosmms 建议使用这个, sm…

每日面经分享(python part1)

Python中的深拷贝和浅拷贝的区别是什么? a. 浅拷贝创建一个新的对象,但其中的可变元素仍然共享引用。只有对象的第一层被复制,而更深层次的嵌套对象仍然是引用。更改其中一个对象的属性会影响到其他对象。 b. 深拷贝创建一个完全独立的新对象…

docker部署nacos,单例模式(standalone),使用内置的derby数据库,简易安装

文章目录 前言安装创建文件夹docker指令安装docker指令安装-瘦身版 制作docker-compose.yaml文件查看页面 前言 nacos作为主流的服务发现中心和配置中心,广泛应用于springcloud框架中,现在就让我们一起简易的部署一个单例模式的nacos,版本可…

【Linux】详解动态库链接和加载对可执行程序底层的理解

一、动静态库链接的几种情况 如果我们同时提供动态库和静态库,gcc默认使用的是动态库。如果我们非要使用静态库,要加-static选项。如果我们只提供静态库,那可执行程序没办法,只能对该库进行静态链接,但程序不一定整体…

python和pip中常见命令和方法

玩python的同学想必没有不用pip的吧,pip是python包管理工具,和Nodejs的npm、Java的maven类似,这些依靠开源力量建立起的庞大软件库极大提高了开发的效率,下面是整理和总结pip中的常见命令和方法。 pip更新版本 python -m pip inst…

利用Spark将Kafka数据流写入HDFS

利用Spark将Kafka数据流写入HDFS 在当今的大数据时代,实时数据处理和分析变得越来越重要。Apache Kafka作为一个分布式流处理平台,已经成为处理实时数据的事实标准。而Apache Spark则是一个强大的大数据处理框架,它提供了对数据进行复杂处理…

Echarts 自适应宽高,或指定宽高进行自适应

文章目录 需求分析 需求 有一个按钮实现对Echarts的指定缩放与拉长&#xff0c;形成自适应效果 拉长后效果图 该块元素缩短后效果图 分析 因为我习惯使用 ref 来获取组件的 DOM 元素&#xff0c;然后进行挂载 <div ref"echartsRef" id"myDiv" :sty…

OCR常用识别算法综述

参考&#xff1a;https://aistudio.baidu.com/education/lessonvideo/3279888 语种&#xff1a;常用字符36与常用汉字6623&#xff0c;区别。 标注&#xff1a;文本型位置/单字符位置&#xff0c;后者标注成本大 挑战&#xff1a;场景文字识别&#xff1a;字符大小、颜色、字体…

力扣1379---找出克隆二叉树的相同节点(Java、DFS、简单题)

目录 题目描述&#xff1a; 思路描述&#xff1a; 代码&#xff1a; &#xff08;1&#xff09;&#xff1a; &#xff08;2&#xff09;&#xff1a; 题目描述&#xff1a; 给你两棵二叉树&#xff0c;原始树 original 和克隆树 cloned&#xff0c;以及一个位于原始树 ori…

蓝牙学习九(定向广播 ADV_DIRECT_IND)

一、简介 广播类型有如下&#xff1a; 非定向可连接广播&#xff08;ADV_IND&#xff09;。可连接的非定向广播&#xff0c;表示当前设备可以接受任何设备的连接请求。 定向可连接广播&#xff08;ADV_DIRECT_IND&#xff09;。可连接的定向广播&#xff0c;设备不能被主动扫描…

Kotlin:常用标准库函数(let、run、with、apply、also)

一、let 扩展函数 Kotlin标准库函数let可用于范围确定和空检查。当调用对象时&#xff0c;let执行给定的代码块并返回其最后一个表达式的结果。对象可以通过引用(默认情况下)或自定义名称在块中访问。 let扩展函数源码 let.kt文件代码 fun main() {println("isEmpty $is…

Stable Diffusion扩散模型【详解】小白也能看懂!!

文章目录 1、Diffusion的整体过程2、加噪过程2.1 加噪的具体细节2.2 加噪过程的公式推导 3、去噪过程3.1 图像概率分布 4、损失函数5、 伪代码过程 此文涉及公式推导&#xff0c;需要参考这篇文章&#xff1a; Stable Diffusion扩散模型推导公式的基础知识 1、Diffusion的整体…