geotrellis使用(十六)使用缓冲区分析的方式解决投影变换中边缘数据值计算的问题
Geotrellis系列文章链接地址http://www.cnblogs.com/shoufengwei/p/5619419.html
目录
一、前言
上一篇文章讲了通过Geotrellis导出自定义的Tiff文件(见geotrellis使用(十四)导出定制的GeoTiff),但是实际中有时会有BUG,就是数据值发生非常明显的变化,理论上只进行了切割、重投影操作,数据值不应该会发生特别大的变化。今天认认真真查找了下问题,发现是因为采样方式造成的。
二、问题探索
使用QGIS打开导出的Tiff文件,形状、位置、投影等信息都正确,甚至大部分数据值都正确,唯一出现问题的地方就是边缘,边缘出现了很多不正常的值。经过试验不同的投影方式、采样方式、数据类型,发现只有在投影方式选择4326(原始数据投影方式是墨卡托-3857),采样方式选择三次卷积法内插等几种重采样方式的时候才会出现边缘的问题,那么很明显导致该问题的原因肯定是投影的时候选择的采样方式造成的,发现问题是解决问题的第一步。
三、采样说明
什么是采样?先来看一下百度百科对重采样的定义。
就是根据一类象元的信息内插出另一类象元信息的过程。在遥感中,重采样是从高分辨率遥感影像中提取出低分辨率影像的过程。
简单的说采样就是根据栅格图中坐标点周围的一些值重新计算该点的值。这里我们虽然没有进行降低分辨率操作但是由于改变了投影方式,各坐标点的数据肯定是要重新计算的,所以需要用到重采样。那么为什么采样会造成边缘数据值出现偏差呢?
很简单,重采样要根据坐标点周围的几个点的值来重新计算当前点的值,在图像边缘处,只有部分临近点有数据,其他无数据的地方会用NODATA值来替代,所以计算结果当然会出问题。
下面简单介绍一下在Geotrellis中支持的采样方式以及其几种常用的采样方式的简单原理。在Geotrellis中写好了以下几种采样方式:
编号 | 英文名称 | 中文名称 |
---|---|---|
1 | NearestNeighbor | 最邻近内插法 |
2 | Bilinear | 双线性内插法 |
3 | CubicConvolution | 三次卷积法内插 |
4 | CubicSpline | 三次样条插值 |
5 | Lanczos | 正交相似变换 |
6 | ... | ... |
最近邻插值法是最简单的插值方法。也称作零阶插值,就是令变换后像素值等于距它最近的输入像素值。所以采用该方法边缘值计算不会出现问题。
双线性内插法取(x,y)点周围的4邻点,在y方向(或x方向)内插两次,再在x方向(或y方向)内插一次,得到(x,y)点的值f(x,y)。
设4个邻点分别为(i,j),(i,j+1),(i+1,j),(i+1,j+1),i代表左上角为原点的行数,j代表列数。设α=x-i,β=y-j,过(x,y)作直线与x轴平行,与4邻点组成的边相交于点(i,y)和点(i+1,y)。先在y方向内插,计算交点的值f(i,y)和f(i+1,y)。f(i,y)即由f(i,j+1)与f(i,j)内插计算而来。简单的说就是选周围的四个点,然后做一条水平的线,按照线性求出水平线与四个点组成的四边形的交点的值,然后根据这两个值再计算出该点的值,理论上使用Bilinear也应该会出现边缘问题,但是实际测试并没有出现。查看其源码,发现其实现原理是根据四个点进行一个加权计算,所以边缘处有值,只是不够准确。
三次卷积法内插法计算精度高,但计算量大,它考虑坐标点周围的16个邻点值,具体公式不在这里罗列,可以参考(http://wenku.baidu.com/link?url=mvyjK0h98UAldYFr_L0-qW-3Rj73uW_yMz0Jwo4ulbWUIfzdAI9f_qOqv_rVqhlTDmEU3xW6vLxp8JTTDtTeCsBGmcb1pmkUfhv-XlkAB6O)。
三次样条插值是通过一系列形值点的一条光滑曲线,数学上通过求解三弯矩方程组得出曲线函数组的过程。简单说就是找插值结果是光滑的。其他采样方式不在哲理具体介绍。
理论上插值结果越精确则需要的邻点就越多,边缘处就越容易出问题。可能Geotrellis中采样代码写的并不完善是导致边缘问题的因素之一,也许随着Geotrellis的更新,边缘问题会自动解决。但是目前来看我们必须要想一个办法来解决这个问题,下面就是本文重点要讲的——使用缓冲区分析的方式解决投影变换中边缘数据值计算的问题。
四、实现方案
1.缓冲区分析
之前在做矢量数据栅格化的时候已经讲解过一次(见geotrellis使用(十)缓冲区分析以及多种类型要素栅格化)。这里用到缓冲区分析的思想,首先将要导出的区域做一个缓冲区分析,将范围扩大,然后根据扩大后的区域进行切割、重投影、数据类型转换等工作,待处理完毕之后再根据原始区域进行切割,这样虽然投影变换时的边缘问题依然存在,但是有问题的边界比实际需要的边界大,在用原始数据切割的时候,“有问题的边界”自然就被去掉了,就能得到一个正确的结果。下面来看具体实现。
2.扩大区域
这一步很简单,Geotrellis中已经写好了缓冲区分析的函数,直接调用即可,代码如下:
poly.buffer(3 * cellWidth)
其中ploy是原始区域,cellWidth是栅格数据的分辨率,这里相当于将面扩大3个像素,保证有足够的邻点。有了扩大后的区域之后,按照上文讲述的方式处理数据即可。
3.裁剪结果
将得到的处理结果按照原始区域进行切割即可得到最终结果,但是Geotrellis中并没有提供不规则切割的方式,只能按照矩形切割。所以我们只能按照不规则区域的外接矩形进行切割,而原始区域又不一定是矩形,即使按照外接矩形切割一样会在很多地方包含扩大后的边界,得不到理想的效果。为了解决这一问题可以先将处理结果按照原始区域进行mask操作,然后切割,便会得到正确的结果。实现代码如下:
val mask = tile.mask(extent, poly)
val realTile = GeoTiff(mask, extent, crs)
.raster
.crop(poly.envelope)
其中poly为原始区域,extent为缓冲区分析后的面的外接矩形,crs为数据投影方式,poly.envelope获取原始区域的外接矩形。这样第一行实现了mask操作,第二行先将mask的结果转为Geotiff然后进行crop(切割)操作。
五、总结
以上就是通过使用缓冲区分析的方式解决投影变换中边缘数据值计算过程中出现偏差的问题。看似简单的原理与实现过程,其实同样可以上升到哲学的高度去思考。当我们解决一个问题的时候,如果不能有所突破何不换个角度考虑绕过这个问题,采取迂回的方式。当然该方法不止能解决重采样造成的问题,凡是涉及到边缘值计算的都可以采用该方法,下一篇文章我将讲解如何使用该方法解决瓦片计算过程中的边缘问题。最后申明这么好的方法并不是我想出来的,要归功于吴老板(具体姓名不在这里透露(●'◡'●))。
geotrellis使用(十六)使用缓冲区分析的方式解决投影变换中边缘数据值计算的问题的更多相关文章
- geotrellis使用(十七)使用缓冲区分析的方式解决单瓦片计算边缘值问题
Geotrellis系列文章链接地址http://www.cnblogs.com/shoufengwei/p/5619419.html 目录 前言 需求分析 实现方案 总结 一.前言 最 ...
- MP实战系列(十六)之性能分析插件
性能分析拦截器,用于输出每条 SQL 语句及其执行时间. 虽然使用阿里的Druid连接池可以完成这个目的,但是,我们一般认为,目前的组件能够达到这个目的,尽量使用目前的组件,因为修改配置和引入第三方库 ...
- Hive学习之路 (十六)Hive分析窗口函数(四) LAG、LEAD、FIRST_VALUE和LAST_VALUE
数据准备 数据格式 cookie4.txt cookie1, ::,url2 cookie1, ::,url1 cookie1, ::,1url3 cookie1, ::,url6 cookie1, ...
- [ExtJS5学习笔记]第十六节 Extjs5使用panel新增的ViewModel属性绑定数据
本文地址:http://blog.csdn.net/sushengmiyan/article/details/39078627 sencha官方API:http://docs.sencha.com/e ...
- [Python爬虫] 之十六:Selenium +phantomjs 利用 pyquery抓取一点咨询数据
本篇主要是利用 pyquery来定位抓取数据,而不用xpath,通过和xpath比较,pyquery效率要高. 主要代码: # coding=utf-8 import os import re fro ...
- Android实战简易教程-第六十六枪(server端搭建和server端Json数据交互)
学习Android有一段时间了.对server端有非常深的好奇,决定对server端的实现进行一些研究,这里实现了一个简单的小样例,用于获取server端的json数据,样例非常easy,适合刚開始学 ...
- SpringMVC(十六):如何使用编程方式替代/WEB-INF/web.xml中的配置信息
在构建springmvc+mybatis项目时,更常用的方式是采用web.xml来配置,而且一般情况下会在web.xml中使用ContextLoaderListener加载applicationCon ...
- 设计模式学习笔记(十六)迭代器模式及其在Java 容器中的应用
迭代器(Iterator)模式,也叫做游标(Cursor)模式.我们知道,在Java 容器中,为了提高容器遍历的方便性,把遍历逻辑从不同类型的集合类中抽取出来,避免向外部暴露集合容器的内部结构. 一. ...
- ElasticStack系列之十六 & ElasticSearch5.x index/create 和 update 源码分析
开篇 在ElasticSearch 系列十四中提到的问题即 ElasticStack系列之十四 & ElasticSearch5.x bulk update 中重复 id 性能骤降,继续这个问 ...
随机推荐
- USACO翻译:USACO 2013 NOV Silver三题
USACO 2013 NOV SILVER 一.题目概览 中文题目名称 未有的奶牛 拥挤的奶牛 弹簧牛 英文题目名称 nocow crowded pogocow 可执行文件名 nocow crowde ...
- SVN Server for Migration
SVN Server: http://mxsuse01/svn/repos/erp/Oracle_EMS Report SVN (Put to SVN Sort) 1. *.RDF 2. *CP.LD ...
- The Solution of UESTC 2016 Summer Training #1 Div.2 Problem A
Link http://acm.hust.edu.cn/vjudge/contest/121539#problem/A Description standard input/output Haneen ...
- 下载判断Android和iOS
//下载 function down(){ var url = ''; var u = navigator.userAgent, app = navigator.appVersion; var isA ...
- Ajax全面基础学习(一)
快捷方法: $.get(url,[data],[callback],[type])get方法的[data]将被链在url后面[callback]是请求成功后的回调,可以得到响应数据,如果请求失败,看不 ...
- Sql Server 2012新特性 Online添加非空栏位.
我们都知道,Sql Server在一个数据量巨大的表中添加一个非空栏位是比较费心的,缺乏经验的DBA或是开发人员甚至可能鲁莽地直接添加导致阻塞相应业务,甚至可能因为资源欠缺造成实例的全局问题.当然这都 ...
- 在 Azure 上使用 Docker运行 Mono
Docker 是最近相当热门的一个名词,它是一个基于 Linux Container 的轻量化的虚拟技术,而微软也相当积极与 Docker 合作,在 Azure 上支持这个火热的技术,并且提供简单的方 ...
- 细嗅Promise
读完这篇文章,预计会消耗你 40 分钟的时间. Ajax 出现的时候,刮来了一阵异步之风,现在 Nodejs 火爆,又一阵异步狂风刮了过来.需求是越来越苛刻,用户对性能的要求也是越来越高,随之而来的是 ...
- Silverlight和WPF中DataContractJsonSerializer对时间的处理差异
原创文章转载请注明出处:@协思, http://zeeman.cnblogs.com Silverlight脱胎于WPF,他们的行为不完全并不完全相同,DataContractJsonSerializ ...
- 喜大普奔,微软Microsoft JDBC Driver For SQL Server已发布到maven中央仓库
相信通过java和SQLServer开发应用的同学们都经历过如下类似的问题. 微软提供的JDBC官方驱动没有放置在Maven仓库中,这样如果你的Java应用需要访问SQL Server,你不得不下载s ...