geotrellis使用(四)geotrellis数据处理部分细节
前面写了几篇博客介绍了Geotrellis的简单使用,具体链接在文后,今天我主要介绍一下Geotrellis在数据处理的过程中需要注意的细节,或者一些简单的经验技巧以供参考。
一、直接操作本地Geotiff
如果不想将tiff数据切割成瓦片存放到集群中,也可以直接使用Geotrellis操作本地geotiff文件,可以直接使用SinglebandGeoTiff读取单波段的tiff,使用MultibandGeoTiff读取多波段tiff。
val geotiff = SinglebandGeoTiff("data/test.tif")
然后使用geotiff.tile就可以像处理普通瓦片那样处理整幅tiff图像。
二、Geotiff数据处理需要注意的细节
如果需要将geotiff数据切割并上传到集群首先需要处理的是geotiff的数据类型、无数据值等元数据信息,即前期处理数据的时候需要将tiff文件处理到合适的情况以方便在程序中使用。
与数据类型和无数据值相关的属性是Tile类的CellType,Geotrellis中定义了与各种类型相对应的CellType类型,具体在geotrellis.raster.CellType类中,当然程序中可以使用tile.convert(ShortConstantNoDataCellType)将瓦片的类型转换为其他形式。
三、获取瓦片编号或者瓦片的范围(Extent)
将数据上传到集群后,一般可以使用LayerReader将整层的瓦片信息全部读出,
val r = reader.read[SpatialKey, Tile, TileLayerMetadata[SpatialKey]](layerId)
其中reader为LayerRander的实例,可以是AccumuloLayerReader等,具体看用户将瓦片数据存放到什么位置,layerId是存放信息的实例,包含存放的layer名称以及第几层,然后就可以使用r.metadata.mapTransform函数获取
瓦片的范围或者瓦片的编号,如果该函数的参数是一个key(瓦片编号实例),结果就是瓦片的Extent,如果参数是一个point,算出来的就是包含该点的瓦片的key。
四、数据的重投影
程序中如果需要对tile进行点、线、面的相交取值等处理就必须使用与tile相同的投影方式,否则处理过程中会出现错误,可以使用ReProject首先对点、线、面进行重投影。
Reproject(geo, LatLng, WebMercator)
其中geo表示需要进行重投影的点、线、面,LatLng是原始投影方式,WebMercator是需要转换到的投影方式。Geotrellis中定义了一个CRS类用于记录投影信息。LatLng和WebMercator继承了CRS类,是定义好的4326和3857投影方式,其他投影类型可以使用CRS类中提供的fromEpsgCode等方法进行设置。
五、获取某个坐标点对应的值
如果我们想要获取某个坐标点所对应的数据的值,有两种方式,第一种是使用LayerReader先读取整层瓦片信息,然后根据偏移得到改点的值,具体方法如下:
val r = reader.read[SpatialKey, Tile, TileLayerMetadata[SpatialKey]](layerId)
val mapTransform = r.metadata.mapTransform
val key = r.metadata.mapTransform(point)
val dataValues: Seq[Double] = r.asRasters().lookup(key).map(_.getDoubleValueAtPoint(point))
val value = if(dataValues == null || dataValues.length <= 0) 0 else dataValues.head
其中reader和layerId的意义与上文相同,同样key就是根据坐标点的偏移算出的瓦片坐标,然后在所有瓦片中查找此key并且获取该坐标点的值,若多个瓦片均包含该坐标点会获取多个值,取出第一个。
第二种方式是使用ValueReader直接找到包含改点的瓦片,然后根据偏移得到此点的数据,具体代码如下:
val key = attributeStore.readMetadata[TileLayerMetadata[SpatialKey]](layerId).mapTransform(point)
val (col, row) = attributeStore.readMetadata[TileLayerMetadata[SpatialKey]](layerId).toRasterExtent().mapToGrid(point)
val tile: Tile = tileReader.reader[SpatialKey, Tile](layerId).read(key)
val tileCol = col - key.col * tile.cols
val tileRow = row - key.row * tile.rows
println(s"tileCol=${tileCol} tileRow = ${tileRow}")
tile.get(tileCol, tileRow)
其中attributeStore是元数据信息,与用户数据上传的位置有关,key是从元数据中根据坐标点偏移算出的瓦片编号,tilReader是ValueReader实例,col、row是根据偏移算出的坐标点在整个数据集中的像素偏移值,然后通过减去编号乘以瓦片像素个数来获取相对当前瓦片的偏移,从而实现获取当前坐标点的数据值。
两种方式均能得到坐标点对应的值,但是其效率却相差几十倍,在我自己的测试中,使用ValueReader取到数据值大概需要20ms,而使用layerReader则大概需要6000ms,我猜测应当是使用LayerReader的方式会在所有瓦片中lookup,而ValueReader则直接获取单个瓦片,所以效率存在差别。
六、结束语
本文简单记录了近期使用Geotrellis过程中遇到的一些问题,及其解决方案,目前项目只用到了栅格数据,所以只是针对Raster模块,后续会探索其他模块功能,并随时将心得发布到博客园中,欢迎大家共同探讨。
七、参考文献
一、geotrellis使用初探
二、geotrellis使用(二)geotrellis-chatta-demo以及geotrellis框架数据读取方式初探
三、geotrellis使用(三)geotrellis数据处理过程分析四、geotrellis使用(四)geotrellis数据处理部分细节
geotrellis使用(四)geotrellis数据处理部分细节的更多相关文章
- geotrellis使用(三十三)关于Geotrellis读取Geotiff的两个细节
前言 在上两篇文章中我介绍了如何直接将Geotiff(一个或者多个)发布为TMS服务.这中间其实我遇到了一个问题,并且这个问题伴随Geotrellis的几乎所有使用案例,下面我进行详细讲述. 一.问题 ...
- Django学习笔记第四篇--数据处理URL和数据库
一.URL: 1.基础的URL与视图函数的映射 from django.conf.urls import url from django.contrib import admin from appna ...
- C++知识点总结(四)——面向对象的编程细节总结
1.空类的默认函数 一般情况下,对于任意一个类A,如果程序员不显示的声明和定义上述函数,C++编译器将会自动的为A产生4个public inline(公有.内联)的默认函数,这4个函数最常见的形式为: ...
- pandas 学习(四)—— 数据处理(清洗)、缺失值的处理
创建 DataFrame: df = pd.DataFrame(np.random.randint(0, 10, (2, 4)), columns=list('ABCD')) 0. 为 data fr ...
- geotrellis使用(四十一)流水线技术
前言 之前 GeoTrellis 为方便用户将数据(GeoTiff 等遥感影像)导入到 backend (包含 Accumulo.File.Hadoop 等格式)中,编写了一个 ETL 类,该类的输入 ...
- Geotrellis系列文章链接
本文存放了我在博客园中撰写的Geotrellis系列文章链接,方便查阅! 一.geotrellis使用初探 二.geotrellis使用(二)geotrellis-chatta-demo以及geotr ...
- geotrellis使用(五)使用scala操作Accumulo
要想搞明白Geotrellis的数据处理情况,首先要弄清楚数据的存放,Geotrellis将数据存放在Accumulo中. Accumulo是一个分布式的Key Value型NOSQL数据库,官网为( ...
- geotrellis使用(六)Scala并发(并行)编程
本文主要讲解Scala的并发(并行)编程,那么为什么题目概称geotrellis使用(六)呢,主要因为本系列讲解如何使用Geotrellis,具体前几篇博文已经介绍过了.我觉得干任何一件事情基础很重要 ...
- geotrellis使用(七)记录一次惨痛的bug调试经历以及求DEM坡度实践
眼看就要端午节了,屌丝还在写代码,话说过节也不给轻松,折腾了一天终于解决了一个BUG,并完成了老板安排的求DEM坡度的任务,那么就分两段来表. 一.BUG调试 首先记录一天的BUG调试,简单copy了 ...
随机推荐
- 临时更换hadoop-ugi
在用spark读写hdfs数据时,有时候当前用户对要读写的hdfs路径没有权限,需要临时改变用户去读写hdfs,操作完后回到原来的用户.我们的hdfs是没有权限认证的,一开始通过下面代码的方式来实现. ...
- Flume_常见的几个问题
在HDFS的文件默认生成文件大小1K,如何设置文件大小和数量 拷贝一份flume-conf.properties.template改名为hive-mem-size.properties hive-me ...
- Apache服务器在80端口配置多域名虚拟主机的方法
我们在配置一台服务器的时候,如果只运行一个站点,往往过于浪费资源.Nginx和Apache都可以通过配置虚拟主机实现多站点.配置虚拟主机的方式主要有两种,一种是多个不同端口对应的多个虚拟主机站点,一种 ...
- ViewPager自动轮播
Android使用ViewPager实现左右循环滑动及轮播效果 ViewPager是一个常用的android组件,不过通常我们使用ViewPager的时候不能实现左右无限循环滑动,在滑到边界的时候 ...
- CI框架,双层弹出框的样式实现
在弹出的主页面上,写一个隐藏的悬浮的div 通过标记使他显示,通过计数器使他关闭 部分代码: <div id="common_msg"></div>//主页 ...
- 通过jquery js 实现幻灯片切换轮播效果
观察各个电商网址轮播图的效果,总结了一下主要突破点与难点 1.->封装函数的步骤与具体实现 2->this关键字的指向 3->jquery js函数熟练运用 如animate 4-& ...
- .NET面试题系列[9] - IEnumerable
.NET面试题系列目录 什么是IEnumerable? IEnumerable及IEnumerable的泛型版本IEnumerable<T>是一个接口,它只含有一个方法GetEnumera ...
- iOS开发系列--C语言之预处理
概述 大家都知道一个C程序的运行包括编译和链接两个阶段,其实在编译之前预处理器首先要进行预处理操作,将处理完产生的一个新的源文件进行编译.由于预处理指令是在编译之前就进行了,因此很多时候它要比在程序运 ...
- gulp使用小结(二)
接上篇文章接Gulp使用小结(一) 内容如下: 首先,偶在gulp-demos上已经提交了个较通用的栗子...俺琢磨半天,原准备分阶段搞些 Gulp 套路,但是写完介个栗子之后,觉得已经能覆盖绝大多数 ...
- 《Entity Framework 6 Recipes》翻译系列 (3) -----第二章 实体数据建模基础之创建一个简单的模型
第二章 实体数据建模基础 很有可能,你才开始探索实体框架,你可能会问“我们怎么开始?”,如果你真是这样的话,那么本章就是一个很好的开始.如果不是,你已经建模,并在实体分裂和继承方面感觉良好,那么你可以 ...