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 性能骤降,继续这个问 ...
随机推荐
- axis2开发webservice程序
一.环境 eclipse + jdk 6.0 + win7 64位 +tomcat7.0 二.创建服务端程序 1.新建web项目,webserviceTest 2.下载axis2,将lib目录下的ja ...
- Winform控件WebBrowser与JS脚本交互
1)在c#中调用js函数 如果要传值,则可以定义object[]数组. 具体方法如下例子: 首先在js中定义被c#调用的方法: function Messageaa(message) { ...
- jquery常见获取高度
jquery获取文档高度和窗口高度,$(document).height().$(window).height() $(document).height():整个网页的文档高度 $(window).h ...
- 解决Ionic的ion-slide-box 2条数据渲染问题
当slider数据列表是动态获取时,如果数据结果只有2条数据时,slider列表会多复制俩个,通过下面的slideChange方法做个判断可以解决这个bug 第一步:添加slideChande方法 & ...
- web程序的路径笔记
"/"与”\“区别:”/“是unix系统区分文件层级的标志,因为当前web应用程序在服务器端大都使用基于unix系统开发的操作系统,所以web程序包括浏览器里url都遵以”/“来区 ...
- Swift小练习-引导页
任何一门语言,只要长期不用就会忘掉,得时不时的敲敲小项目,练练手; let scrollViewBG = UIScrollView.init(frame: SLScreenRect) let imag ...
- Shell下突破安全狗远程桌面守护
首先在Shell下把安全狗的安装配置给下来 默认安装路径: C:\Program Files\SafedogServer\SafeDogGuardCenter 找到 ProGuardData.ini ...
- asp.net 基礎部分一
过程: 客户端像服务器发送一个请求,iis服务器接收到请求的数据,并且将数据交给c#程序进行处理,并且对数据库进行操作,并且将处理到的结果响应给浏览器客户端 过程2:第一次浏览器请求,后端应该发一个表 ...
- PostgreSQL 9.3发布
9月9日,PostgreSQL全球开发组宣布了9.3版发布的消息.从2010年9.0版开始,PostgreSQL已经连续四个版本稳定地按时在每年9月中旬发布,从一个侧面也显示了开发团队的强大实力. 9 ...
- Centos 使用YUM安装MariaDB
1.在 /etc/yum.repos.d/ 下建立 MariaDB.repo,内容如下: [azureuser@mono etc]$ cd /etc/yum.repos.d [azureuser@mo ...