使用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响应的方法.分享给大家 ...
随机推荐
- Python中下划线---完全解读
Python 用下划线作为变量前缀和后缀指定特殊变量 _xxx 不能用'from module import *'导入 __xxx__ 系统定义名字 __xxx 类中的私有变量名 核心风格:避免用下划 ...
- 博客停更及OI退役公告
停更&&OI退役 公告 高中OI之路就这样结束了,曾经想过回在NOI跪,APIO跪,HNOI跪却从未想过会在NOIP跪! 没办法自己作死啊,CCF感觉还是很良心的混个省一回来了,看以后 ...
- IOS开发中摇一摇是怎么实现的
三个方法,分别是开始摇一摇,结束摇一摇,取消摇一摇,我们可以在里面对应的进行事件处理,或者在ui上进行信息展示: 1.开始摇一摇:(在实际app中用需要处理的语句替换NSLog(@"开始摇一 ...
- 如何用 Git 合并两个库,并保留提交历史
转载自 https://segmentfault.com/a/1190000000678808 背景 一个中型规模项目,开始规划时就打算采用 C/S 架构,后端是单纯的 API 服务,前端在 Web ...
- INSTALL_FAILED_UPDATE_INCOMPATIBLE
安装apk的时候,报错. 解决:把所有这个apk的相关信息删除干净,隐藏较深的是设置->应用管理->这个应用的相关信息删除干净就可以了
- Leetcode 197. Rising Temperature
Given a Weather table, write a SQL query to find all dates' Ids with higher temperature compared to ...
- php调用js变量
<script> function tuichu(skp){ <?php $ok="skp"; echo "alert($ok)";//实验代 ...
- ubuntu修改环境变量
1.修改/etc/profile后重启之后就失效了,需要修改/etc/environment才可以 以下情况是失败的: 在/etc/profile文件中添加变量[对所有用户生效(永久的)] 用VI在文 ...
- 交叉验证(cross validation)
转自:http://www.vanjor.org/blog/2010/10/cross-validation/ 交叉验证(Cross-Validation): 有时亦称循环估计, 是一种统计学上将数据 ...
- 第五组UI组件:ProgressBar及其子类
ProgressBar组件也是一组重要的组件,ProgressBar本身代表了进度条组件,它还派生了两个常用的组件:SeekBar和RatingBar.ProgressBar及其子类在用上十分相似,只 ...