本文为转载http://www.cnblogs.com/rib06/category/56544.html
ESRI的ArcSDE是个性能比较强劲的空间数据引擎,它在管理矢量数据是采用的策略和方法效率都还是很不错的。我前一段做了一个基于ArcSDE的影像数据包装器,其作为一项WebGIS项目后端的一部分,功能就是完成前端对影像数据的任意范围查询,将通过ArcSDE存于Oracle Spatial中的影像数据实时提取出来并生成图片。基础影像数据的数据量为13GB。这里对影像数据做一下说明。影像数据一般有两种——航拍照片和卫星照片,以航片为例(也就是本文所处理的对象),在入库前一般是若干张大小相同的已经数字化(也就是扫描好的)的带坐标信息的(
好多定语啊…)栅格图像文件,它们是彼此相邻的,是由飞机在一个区域进行“地毯式”拍照得到的。这种图像文件的数据量大约每个在几十兆左右,像素大小一般为几千点×几千点。
在做的过程中我发现ArcSDE在管理影像数据方面就没有矢量数据那么强大了。我们项目的矢量部分是基于MO做的,但是MO明确不支持影像数据。所以我只能求助于SDE API(我们这里没有AO,不知道AO对影像支持的怎么样)。SDE API分成C-API和Java-API两种,其中又只有C-API支持影像(ESRI在搞什么飞机?),所以这就是我唯一的选择。
而使用C-API又是一件十分令人头疼的事情,因为文档非常有限,只有随软件的一份Developer Help,而这份文档用粗制滥造来形容一点都不冤枉它,其中信息量小,例子混乱,甚至还有错别字,实在是给ESRI砸牌子
。这份文档在ESRI官方有下载,有兴趣的朋友可以去翻翻。
这份文档说明了SDE管理影像数据的方法,简而言之就是“两种方式,分层分块”。“两种方式”是指:栅格地图(Raster Map)和栅格目录(Raster Catalog)。
栅格地图比较适合带有标准坐标系的航片或卫片,当以这种方式导入影像文件的时候,SDE(实际上是ArcToolBox干的)会将它们拼接(mosaic)成一张完整的大地图,但这种方式对各个图幅的要求就非常严格,要实现拼接必须满足几个条件:相邻图幅的相邻边不能有一丁点重叠错位;图幅必须带坐标系等等。但这种把图幅全拼起来的管理方式也有问题,就是如果将来要更新其中的某一小块区域的图像怎么办呢?比如纽约的影像图,世贸大厦被撞没了,其实只需要更新一下曼哈顿那一点地方的数据就可以了,可要是以Raster Map方式管理全纽约的影像地图的话那么就意味着要全部删掉原来的数据,再重新导入一遍全城的航片,几十个G,不是小数目啊,如果是1:10000的话估计纽约的影像数据量应该在300个G左右,怎么也得导几天才能导完吧。
那么另一种方式呢?Raster Catalog说白了就是个相册。可以把风驴羊不相及的东西的照片都存进去,SDE只管存储和为它们维护一个目录,这一点可以从观察Raster Catalog对应的Oracle Spatial表看出来,感觉就像一个被肢解了的图片的集中营。当然ArcSDE毕竟是GIS软件,如果用它来存一些花花草草或者MM图片也确实划不来,因为它实在太~~~慢了。但是如果存进去的是我前面说的相邻的若干航片,那么效果会有所不同。就体现在如果用ESRI的桌面工具(比如ArcMap,ArcCatalog)来预览这个Raster Catalog的时候,你将看到一张经过拼接的美图!我一直想知道这些工具背后实现拼接的算法,但未果。使用这种方式管理航片就没有前面Raster Map方式最后说的那种问题,比如世贸大厦没了,那么我们就重新在那里拍一张,再更新原来Raster Catalog中对应的那一个图幅就可以了,其它的则没必要去动。
前面说的“两种方式”是在比较高的尺度上讨论,在我所做的这个项目中,客户的基础数据采用了第二种方式,即Raster Catalog方式进行存储和管理。现在我们深入一点,进入图幅内部,看看它的存储和管理方式,这就是“分层分块”。
“分层”是指:影像金字塔(pyramid)索引。这个东西我不想多说,搞这方面的应该都知道,其基本思想就是利用采样自底向上生成金字塔,根据需求直接取其中某一级作为操作对象,以提高整体效率。当然就像这个世界中的其它事物一样,效率的提高是有代价的,这就是建塔带来的额外空间开销,建的级越多,越方便查询,当然数据冗余也越大。SDE可以为导入的影像建立金字塔索引。据我观察一般为6级。
“分块”是指每个图幅是按图块(block/tile)存储的,并使用格网索引。这里就又隐藏了一个巨大的问题,但还是听我说分块先。在将图幅存储于数据库中时,SDE不是傻乎乎的一行一行的存进去,而是将图幅划分成若干个大小相同的图块,每块大小不能超过16K,一般就取128×128。划分的顺序是从上到下,从左至右的,分块的好处在于可以减少磁盘I/O。但是哪有那么好的图幅,长宽都是128的整数倍啊?而事实上就几乎没有这么好的图幅,那么图幅的长宽一般都是什么数呢?我手里的这些应该都是3500×2800的,但是它们的实际大小一般为356x×285x,出现这种误差是很正常的,也是允许的。那这图幅的长和宽都除不开128怎么办呢?SDE的策略就是——补零。在图幅的右侧和下侧补上若干零元(RGB:000000),也就是黑点,这样处理过的图幅就可以进行划分了,如图所示。
切下来的每一块作为一条记录再存入数据库。这样的策略导致问题随之而来:Raster Catalog中的每个图幅都有“黑边”,那又如何实现跨图幅的无缝拼接?前面我说了,ESRI的桌面工具可以做到,这就是我非常想知道它使用的算法的原因。那么我呢?目前唯一的希望就是SDE C-API能够提供读取这些“黑边”信息的接口,为此我给ESRI中国的技术支持发了E-mail。但结果是令人极度失望的,可爱的工程师在回信中热情的告诉我:C-API没有提供读取补零信息的接口,而且没有关于补零信息的任何文档。
至此,我的工作就停下了,我只能开始想别的出路。不过最终我手工实现了图幅去零和无缝拼接,这是后话了,具体方法将另文所述。
本文的目的就在于简单介绍一下ArcSDE管理影像数据的基本方法及其缺陷,在本文应用背景下,它的这种缺陷给我带来了很大的麻烦,虽然最终解决了问题,但还是感觉SDE自身应该可以采用更高明的影像管理方案,提供更方便的接口。单看影像这块,似乎不像ESRI这种公司做出来的东西,也许他压根就没想好好做这块。不知道同样领域有没有类似ArcSDE的替代品,更加好用,更方便做二次开发,还请各位指点,我指的是影像。
ESRI的ArcSDE是个性能比较强劲的空间数据引擎,它在管理矢量数据是采用的策略和方法效率都还是很不错的。我前一段做了一个基于ArcSDE的影像数据包装器,其作为一项WebGIS项目后端的一部分,功能就是完成前端对影像数据的任意范围查询,将通过ArcSDE存于Oracle Spatial中的影像数据实时提取出来并生成图片。基础影像数据的数据量为13GB。这里对影像数据做一下说明。影像数据一般有两种——航拍照片和卫星照片,以航片为例(也就是本文所处理的对象),在入库前一般是若干张大小相同的已经数字化(也就是扫描好的)的带坐标信息的(
![](https://www.cnblogs.com/Emoticons/emcrook.gif)
在做的过程中我发现ArcSDE在管理影像数据方面就没有矢量数据那么强大了。我们项目的矢量部分是基于MO做的,但是MO明确不支持影像数据。所以我只能求助于SDE API(我们这里没有AO,不知道AO对影像支持的怎么样)。SDE API分成C-API和Java-API两种,其中又只有C-API支持影像(ESRI在搞什么飞机?),所以这就是我唯一的选择。
而使用C-API又是一件十分令人头疼的事情,因为文档非常有限,只有随软件的一份Developer Help,而这份文档用粗制滥造来形容一点都不冤枉它,其中信息量小,例子混乱,甚至还有错别字,实在是给ESRI砸牌子
![](https://www.cnblogs.com/Emoticons/emthdown.gif)
这份文档说明了SDE管理影像数据的方法,简而言之就是“两种方式,分层分块”。“两种方式”是指:栅格地图(Raster Map)和栅格目录(Raster Catalog)。
栅格地图比较适合带有标准坐标系的航片或卫片,当以这种方式导入影像文件的时候,SDE(实际上是ArcToolBox干的)会将它们拼接(mosaic)成一张完整的大地图,但这种方式对各个图幅的要求就非常严格,要实现拼接必须满足几个条件:相邻图幅的相邻边不能有一丁点重叠错位;图幅必须带坐标系等等。但这种把图幅全拼起来的管理方式也有问题,就是如果将来要更新其中的某一小块区域的图像怎么办呢?比如纽约的影像图,世贸大厦被撞没了,其实只需要更新一下曼哈顿那一点地方的数据就可以了,可要是以Raster Map方式管理全纽约的影像地图的话那么就意味着要全部删掉原来的数据,再重新导入一遍全城的航片,几十个G,不是小数目啊,如果是1:10000的话估计纽约的影像数据量应该在300个G左右,怎么也得导几天才能导完吧。
那么另一种方式呢?Raster Catalog说白了就是个相册。可以把风驴羊不相及的东西的照片都存进去,SDE只管存储和为它们维护一个目录,这一点可以从观察Raster Catalog对应的Oracle Spatial表看出来,感觉就像一个被肢解了的图片的集中营。当然ArcSDE毕竟是GIS软件,如果用它来存一些花花草草或者MM图片也确实划不来,因为它实在太~~~慢了。但是如果存进去的是我前面说的相邻的若干航片,那么效果会有所不同。就体现在如果用ESRI的桌面工具(比如ArcMap,ArcCatalog)来预览这个Raster Catalog的时候,你将看到一张经过拼接的美图!我一直想知道这些工具背后实现拼接的算法,但未果。使用这种方式管理航片就没有前面Raster Map方式最后说的那种问题,比如世贸大厦没了,那么我们就重新在那里拍一张,再更新原来Raster Catalog中对应的那一个图幅就可以了,其它的则没必要去动。
前面说的“两种方式”是在比较高的尺度上讨论,在我所做的这个项目中,客户的基础数据采用了第二种方式,即Raster Catalog方式进行存储和管理。现在我们深入一点,进入图幅内部,看看它的存储和管理方式,这就是“分层分块”。
“分层”是指:影像金字塔(pyramid)索引。这个东西我不想多说,搞这方面的应该都知道,其基本思想就是利用采样自底向上生成金字塔,根据需求直接取其中某一级作为操作对象,以提高整体效率。当然就像这个世界中的其它事物一样,效率的提高是有代价的,这就是建塔带来的额外空间开销,建的级越多,越方便查询,当然数据冗余也越大。SDE可以为导入的影像建立金字塔索引。据我观察一般为6级。
“分块”是指每个图幅是按图块(block/tile)存储的,并使用格网索引。这里就又隐藏了一个巨大的问题,但还是听我说分块先。在将图幅存储于数据库中时,SDE不是傻乎乎的一行一行的存进去,而是将图幅划分成若干个大小相同的图块,每块大小不能超过16K,一般就取128×128。划分的顺序是从上到下,从左至右的,分块的好处在于可以减少磁盘I/O。但是哪有那么好的图幅,长宽都是128的整数倍啊?而事实上就几乎没有这么好的图幅,那么图幅的长宽一般都是什么数呢?我手里的这些应该都是3500×2800的,但是它们的实际大小一般为356x×285x,出现这种误差是很正常的,也是允许的。那这图幅的长和宽都除不开128怎么办呢?SDE的策略就是——补零。在图幅的右侧和下侧补上若干零元(RGB:000000),也就是黑点,这样处理过的图幅就可以进行划分了,如图所示。
![](https://www.cnblogs.com/images/cnblogs_com/rib06/buling.jpg)
切下来的每一块作为一条记录再存入数据库。这样的策略导致问题随之而来:Raster Catalog中的每个图幅都有“黑边”,那又如何实现跨图幅的无缝拼接?前面我说了,ESRI的桌面工具可以做到,这就是我非常想知道它使用的算法的原因。那么我呢?目前唯一的希望就是SDE C-API能够提供读取这些“黑边”信息的接口,为此我给ESRI中国的技术支持发了E-mail。但结果是令人极度失望的,可爱的工程师在回信中热情的告诉我:C-API没有提供读取补零信息的接口,而且没有关于补零信息的任何文档。
![](https://www.cnblogs.com/Emoticons/hitwall.gif)
至此,我的工作就停下了,我只能开始想别的出路。不过最终我手工实现了图幅去零和无缝拼接,这是后话了,具体方法将另文所述。
本文的目的就在于简单介绍一下ArcSDE管理影像数据的基本方法及其缺陷,在本文应用背景下,它的这种缺陷给我带来了很大的麻烦,虽然最终解决了问题,但还是感觉SDE自身应该可以采用更高明的影像管理方案,提供更方便的接口。单看影像这块,似乎不像ESRI这种公司做出来的东西,也许他压根就没想好好做这块。不知道同样领域有没有类似ArcSDE的替代品,更加好用,更方便做二次开发,还请各位指点,我指的是影像。