使用Python以优雅的方式实现根据shp数据对栅格影像进行切割
目录
一、前言
前面一篇文章(使用Python实现子区域数据分类统计)讲述了通过geopandas库实现对子区域数据的分类统计,说白了也就是如何根据一个shp数据对另一个shp数据进行切割。本篇作为上一篇内容的姊妹篇讲述如何采用优雅的方式根据一个shp数据对一个栅格影像数据进行切割。废话不多说,直接进入主题。
二、涉及到的技术
本方案涉及以下技术点:
- geopandas:已经在上一篇文章中简单介绍。
- numpy:这是一个开源的数据分析处理库,非常高效、简洁。
- rasterio:这是一个开源的影像处理库,非常好用,基本涵盖了常用的功能。也可以配合numpy进行数据计算。
- datashader:这是一个开源的大数据可视化库,可以进行遥感影像、矢量数据的可视化。其基于bokeh,bokeh是一个通用的可视化工具,有兴趣的可以参考github,我之前采用Scala语言对其进行了简单的封装,请参考使用bokeh-scala进行数据可视化以及使用bokeh-scala进行数据可视化(2)。
本文基本涉及以上技术。另,最近Github貌似被墙了,所以你懂的。推荐使用Lantern,请自行百度之。
三、优雅切割
为什么叫优雅的切割,其实我这里倒不是卖弄文字,主要是为了与Gdal的方式相区别。传统的方式可以采用Gdal命令行进行一点点的手动处理,稍微智能化一点可以在python程序中发送控制台语句的方式调用gdal命令。作为程序员我们都是想采用最简单、最不需要手工操作、看上去最舒服的方式。所以我这里称其为优雅的方式。
我们大致需要经历读取影像、投影转换、读取shp、切割、显示等几个步骤。下面逐一介绍。
3.1 读取影像
采用rasterio进行影像读取。代码如下:
import rasterio as rio
band = rio.open(path)
非常简单,只要传入影像的路径即可。rasterio支持tif、hdf格式(亲测)。
3.2 投影转换
这是比较难的一块,需要注意很多细节。代码如下:
from rasterio.warp import (reproject,RESAMPLING, transform_bounds,calculate_default_transform as calcdt)
affine, width, height = calcdt(src.crs, dst_crs, src.width, src.height, *src.bounds)
kwargs = src.meta.copy()
kwargs.update({
'crs': dst_crs,
'transform': affine,
'affine': affine,
'width': width,
'height': height,
'geotransform':(0,1,0,0,0,-1) ,
'driver': 'GTiff'
})
dst = rio.open(newtiffname, 'w', **kwargs)
for i in range(1, src.count + 1):
reproject(
source = rio.band(src, i),
destination = rio.band(dst, i),
src_transform = src.affine,
src_crs = src.crs,
dst_transform = affine,
dst_crs = dst_crs,
dst_nodata = src.nodata,
resampling = RESAMPLING.bilinear)
首先使用calculate_default_transform函数计算投影转换后的影像尺寸以及仿射变换参数。其中src表示原始影像,src.crs可以取到原始投影,dst_crs位定义的目标投影,与上一篇中介绍shp投影变换时基本一致。
然后计算投影后的tiff元数据信息。src.meta.copy()读出原始元数据信息并进行拷贝,kwargs.update将原始元数据更新为目标元数据。
dst = rio.open(newtiffname, 'w', **kwargs)打开一个新的影像其模式w表示写入。
最后循环原始影像的所有波段,逐一进行投影变换并写入新的影像。其参数一目了然,不再赘述。
上一个影像的整体截图,以与下述切割后的效果进行对比。
3.3 读取shp
这在上一篇文章中也已经做了详细描述,不再赘述,需要强调的时此处也需要将shp进行投影转换,使其与我们要处理的影像一致,所以简单的方式就是直接读取影像的投影信息,将shp数据转换到此投影,详情请参考使用Python实现子区域数据分类统计。
3.4 切割
我们要对一个完整的影像进行切割,可以分为两步。首先将shp数据转换为geojson,然后使用rasterio进行切割。
3.4.1 shp数据转换为geojson
rasterio进行切割时需要传入的时geojson对象,而不是普通的GeoSeries对象,所以我们需要进行一步转换。代码如下:
from geopandas import GeoSeries
features = [shpdata.geometry.__geo_interface__]
其中shpdata为读出的shp数据对象。如果我们想要获取shp中的某条空间数据而不是全部,可以采用如下方式:
from geopandas import GeoSeries
features = [GeoSeries(shpdata.geometry[i]).__geo_interface__]
其中i表示的是取出元素的序号,最后都要采用[]将结果变成数组,因为rasterio最后需要传入一个数组参数。
3.4.2 使用rasterio进行切割
其实有了前面的准备这一步也就变的简单了,直接调用rio.mask.mask函数,该函数返回该栅格数据与features相交部分的数组结果以及变换信息。代码如下:
import rasterio.mask
out_image, out_transform = rio.mask.mask(src, features, crop=True, nodata=src.nodata)
out_meta = src.meta.copy()
out_meta.update({"driver": "GTiff",
"height": out_image.shape[1],
"width": out_image.shape[2],
"transform": out_transform})
band_mask = rasterio.open(newtiffname, "w", **out_meta)
band_mask.write(out_image)
其中src为切割前的影像数据,features为上一步得到的shp数据转换后的geojson,crop表示是否对原始影像进行切割,如果为True表示将该geojson的外界框以外的数据全部删除,既缩小原始影像的大小,只保留外界框以内部分,nodata表示无值数据,凡是geojson外部的数据都会转换成此值。
后面的基本与投影转换后的一致,根据切割的结果生成一个新的影像数据。这样我们就实现了根据shp数据对遥感影像进行切割。效果如下:
四、总结
本文所介绍的技术可以用于对全国的影像数据进行分省切割,或者省的影像数据进行县市切割等。同理与上一篇文章一致的是凡是这种处理子区域的方式都可以采用此技术。当然本文没有介绍如何对遥感影像进行处理,其实非常简单,当我们读出影像数据之后,其就是一个numpy的array对象,已经变成了纯数学问题,处理完之后只需要附加投影等信息写入新的tiff文件即可。
使用Python以优雅的方式实现根据shp数据对栅格影像进行切割的更多相关文章
- <转> Python的优雅技巧
枚举 不要这么做: 全选复制放进笔记 i = 0 for item in iterable: print i, item i += 1 而是这样: 全选复制放进笔记 for i, item in en ...
- 关于python - 更优雅的技巧
枚举 不要这么做: i = 0 for item in iterable: print i, item i += 1 而是这样: for i, item in enumerate(iterable): ...
- 让Python更优雅更易读(第二集)
友情链接 让Python更优雅更易读(第一集) 1.装饰器 1.1装饰器特别适合用来实现以下功能 运行时校验:在执行阶段进行特定校验,当校验通不过时终止执行. 适合原因:装饰器可以方便地在函数执行前介 ...
- Python文件使用“wb”方式打开,写入内容
Python文件使用"wb"方式打开,写入字符串会报错,因为这种打开方式为:以二进制格式打开一个文件只用于写入.如果该文件已存在则将其覆盖.如果该文件不存在,创建新文件. 所以写入 ...
- python出输出字符串方式:
python出输出字符串方式: >>> who='knights' >>> what='NI' >>> print ('we are the',w ...
- python 如何优雅地退出子进程
python 如何优雅地退出子进程 主进程产生子进程,子进程进入永久循环模式.当主进程要求子进程退出时,如何能安全地退出子进程呢? 参考一些代码,我写了这个例子.运行之后,用kill pid试试.pi ...
- Android APP新的“优雅”退出方式--EventBus大显身手
最近在研究eventBus..很多小伙伴不知道他有什么用.. 前篇介绍了EventBus的基本使用 这里简单举一个例子,就是退出APP 转载请注明出处:http://blog.csdn.net/win ...
- 潭州课堂25班:Ph201805201 爬虫基础 第七课 Python与常见加密方式 (课堂笔记)
打开图形界面 18版 Python与常见加密方式 前言 我们所说的加密方式,都是对二进制编码的格式进行加密的,对应到Python中,则是我们的Bytes. 所以当我们在Python中进行加密操作的时 ...
- python通过get,post方式发送http请求和接收http响应的方法,pythonget
python通过get,post方式发送http请求和接收http响应的方法,pythonget 本文实例讲述了python通过get,post方式发送http请求和接收http响应的方法.分享给大家 ...
随机推荐
- CoordinatorLayout学习笔记
CoordinatorLayout是一个增强型的FrameLayout.它的作用有两个 作为一个布局的根布局 最为一个为子视图之间相互协调手势效果的一个协调布局 代码如下: <?xml vers ...
- IOS开发-ObjC-对象、封装
C语言是基于过程的一种编程语言,而OC语言是基于对象的一种语言. C是和其他的面向对象的语言的区别在于C语言更注重地层操作,思维方式相比面向对象的语言而言更接近机器的思维方式,而面向对象的语言更接近于 ...
- List<KeyValuePair<TKey,TValue>> 与 Dictionary<TKey,TValue> 不同
两者都可以通过 KeyValuePair<TKey,TValue> 进行遍历,并且两者可以相互转换: List<KeyValuePair<string,string>&g ...
- 安装pybloomfiltermmap 遇到bug
pybloomfiltermmap pip 安装 : sudo pip install pybloomfiltermmap I want to try one program which have m ...
- 环信 之 iOS 客户端集成四:集成UI 之 会话列表
1. 初始化 EaseConversationListViewController *chatListVC = [[EaseConversationListViewController alloc] ...
- 判断js对象的数据类型,有没有一个最完美的方法?
先来一个例子: var string1=""; var string2=new String(""); alert(typeof string1); // st ...
- DELPHI中多线程知识【转】
本文的内容取自网络,并重新加以整理,在此留存仅仅是方便自己学习和查阅.所有代码均亲自测试 delphi7下测试有效.图片均为自己制作. 多线程应该是编程工作者的基础技能, 但这个基础我从来没学过,所以 ...
- HTTP协议缓存策略深入详解之ETAG妙用
Etag是什么: Etag 是URL的Entity Tag,用于标示URL对象是否改变,区分不同语言和Session等等.具体内部含义是使服务器控制的,就像Cookie那样. HTTP协议规格说明定义 ...
- jQuery如何实现点击页面获得当前点击元素
获得jquery对象: function foo(e){ var obj = $(e.target); }
- Bootstrap入门(七)组件1:字体图标
Bootstrap入门(七)组件1:字体图标 包括200个来自 Glyphicon Halflings 的字体图标,允许 Bootstrap 免费使用. 部分可用图标截图: 所有图标都需要一个基类 ...