当前位置: 首页 > news >正文

使用rasterio裁剪遥感影像

文章目录

    • 0. 数据准备
    • 1. polygon的坐标系转换
      • 1.1 polygon生成
        • 1.1.1 输入数据是shapefile
        • 1.1.2 输入数据是polygon
      • 1.2 搞清楚遥感的坐标系和polygon的坐标系(重点)
      • 1.3 开始转换
    • 2. 基于polygon的遥感影像裁剪
      • 2.1 基础裁剪方法
      • 2.1.1 使用rasterio保存
      • 2.1.2 使用numpy保存
      • 2.2 多线程裁剪
    • 3. 成品代码

传统裁剪遥感影像的方式是使用gdal裁剪。但是gdal需要安装相应的库和依赖非常麻烦。rasterio就不需要安装gdal,是非常好的替代品。
附带一些同样不需要gdal就能够python安装的地理库

pyproj
shapely
# GDAL   # 咱就是说不要你了
# osgeo # 这个库就是对gdal的封装,本质还是gdal
Fiona
geopandas
rasterio
pyshp

0. 数据准备

  • 原始遥感影像
  • polygon数据
  • python库:rasterio

1. polygon的坐标系转换

坐标系概念讲的很好的文章:https://www.cnblogs.com/onsummer/p/12081889.html

这里需要介绍坐标系的几个概念

  • 地理坐标系统,英文简写GCS,Geographical Coordinate System。说白了就是经纬度
  • 投影坐标系,英文简写PCS,Projection Coordinate System。说白了就是米为单位的坐标系

遥感影像裁剪的时候,需要在投影坐标系的基础上进行裁剪。因此需要进行坐标系转换。坐标系的转换分成三步

1.1 polygon生成

这一步,我们需要得到shapely.geometry.Polygon的对象,有两种数据输入格式

1.1.1 输入数据是shapefile

shapefile中可以包含多个polygon,因此需要一个for循环遍历得到所有的polygon。此时获得的polygon自动就是shapely.geometry.Polygon对象

shpfile = 'beijing_test_2_wgs84.shp'
shpdata = gpd.read_file(shpfile)# 其实这里就可以执行1.2的坐标系转换了,可以看了1.2后回来再看这里
# shpdata = shpdata.to_crs(arcgis_crs)for j in range(0, len(shpdata)):# 此时获得的polygon自动就是`shapely.geometry.Polygon`对象polygon = shpdata.geometry[j]

1.1.2 输入数据是polygon

通过以下代码生成shapely.geometry.Polygon对象

def create_polygon(polygon_str):"""生成polygon对象:param polygon_str: polygon字符串,形如"x1,y1;x2,y2;x3,y3":return: shapely.geometry.Polygon对象"""coords = []for coord in polygon_str.split(';'):x, y = coord.split(',')coords.append((float(x), float(y)))polygon = Polygon(coords)return polygon

1.2 搞清楚遥感的坐标系和polygon的坐标系(重点)

转换的时候需要用到crs模块,表示坐标系。由于polygon的坐标系需要向遥感的坐标系靠近,因此需要获得遥感的坐标系,如下代码所示

import rasterio as rio
with rio.open(rasterPath) as rasterdata:out_crs = rasterdata.crs

我们处理数据的时候遇到一个问题,就是遥感的坐标系是arcgis自定义的一种坐标系,因此需要自己生成crs。生成crs的方法有以下几种

from rasterio import crs
crs.CRS.from_epsg # 常用
crs.CRS.from_wkt # 常用
crs.CRS.from_authority
crs.CRS.from_dict
crs.CRS.from_proj4
crs.CRS.from_string
crs.CRS.from_user_input

我们用到的crs是这样的,是arcgis自己的一套坐标系。如果不用相同的方式改变polygon的坐标系,就会导致裁剪歪掉

out_crs = arcgis_crs = crs.CRS.from_wkt("""PROJCRS["WGS_1984_Web_Mercator_Auxiliary_Sphere",BASEGEOGCRS["WGS 84",DATUM["World Geodetic System 1984",ELLIPSOID["WGS 84",6378137,298.257223563,LENGTHUNIT["metre",1]]],PRIMEM["Greenwich",0,ANGLEUNIT["degree",0.0174532925199433]],ID["EPSG",4326]],CONVERSION["Mercator (variant A)",METHOD["Mercator (variant A)",ID["EPSG",9804]],PARAMETER["Latitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8801]],PARAMETER["Longitude of natural origin",0,ANGLEUNIT["degree",0.0174532925199433],ID["EPSG",8802]],PARAMETER["Scale factor at natural origin",1,SCALEUNIT["unity",1],ID["EPSG",8805]],PARAMETER["False easting",0,LENGTHUNIT["metre",1],ID["EPSG",8806]],PARAMETER["False northing",0,LENGTHUNIT["metre",1],ID["EPSG",8807]]],CS[Cartesian,2],AXIS["easting",east,ORDER[1],LENGTHUNIT["metre",1,ID["EPSG",9001]]],AXIS["northing",north,ORDER[2],LENGTHUNIT["metre",1,ID["EPSG",9001]]]]""")

1.3 开始转换

将polygon对象转换成gdf(geodataframe)对象,然后指定目标crs进行转换。

import geopandas as gpd
from rasterio import crspolygon = "x1,y1;x2,y2;x3,y3"
# 1.首先将polygon转换成gdf
raw_crs = crs.CRS.from_epsg(4326)
polygon = create_polygon(polygon) # 1.1.2定义的函数
gdf = gpd.GeoDataFrame(geometry=[polygon], crs=raw_crs) # 这里的raw_crs# 2.其次将gdf进行坐标系转换,并再次获得polygon
gdf = gdf.to_crs(out_crs)  # 1.2定义的out_crs
polygon = gdf.geometry[0]

2. 基于polygon的遥感影像裁剪

得到polygon后就可以进行裁剪了,有下面两种方法

2.1 基础裁剪方法

直接用polygon得到的信息得到mask遮罩,就可以获取裁剪后的结果了。

import rasterio as rio
from rasterio.mask import mask
with rio.open(rasterPath) as rasterdata:out_crs = rasterdata.crsfeature = [polygon.__geo_interface__] # 1.3中得到的polygonout_image, out_transform = mask(rasterdata, feature, all_touched=True, crop=True, nodata=255)

2.1.1 使用rasterio保存

使用rasterio可以保存更多的地理信息

import rasterio as rio
from rasterio.mask import mask
with rio.open(rasterPath) as rasterdata:# 1.获取基本信息out_meta = rasterdata.meta.copy() # 2.裁剪out_crs = rasterdata.crsfeature = [polygon.__geo_interface__] # 1.3中得到的polygonout_image, out_transform = mask(rasterdata, feature, all_touched=True, crop=True, nodata=255)# 3.更新信息并保存out_meta.update(height=out_image.shape[1],width=out_image.shape[2],shape=(out_image.shape[1], out_image.shape[2]),nodata=255,crs=rasterdata.crs,bounds=[],transform=out_transform,)with rio.open(f"{文件输出路径}", mode='w', **out_meta) as dst:dst.write(out_image)

2.1.2 使用numpy保存

使用numpy就是纯纯保存裁剪结果了

import rasterio as rio
from rasterio.mask import mask
with rio.open(rasterPath) as rasterdata:# 1.获取基本信息out_meta = rasterdata.meta.copy() # 2.裁剪out_crs = rasterdata.crsfeature = [polygon.__geo_interface__] # 1.3中得到的polygonout_image, out_transform = mask(rasterdata, feature, all_touched=True, crop=True, nodata=255)# 3.保存out_image_PIL = Image.fromarray(np.transpose(out_image, (1, 2, 0))).convert('RGB')out_image_PIL.save(f"{文件输出路径}", "PNG", quality=95, optimize=True, progressive=True)

2.2 多线程裁剪

如果直接用Pool, ProcessPoolExecutor等库进行裁剪,会遇到如下问题:

TypeError: self._hds cannot be converted to a Python object for pickling

这是由于 https://github.com/rasterio/rasterio/issues/1731#issuecomment-514781590

栅格数据集(rasterio DatasetReader类型)不能被pickle,也不能在进程或线程之间共享。解决方法是分发数据集标识符(路径或 URI),然后在新线程中打开它们。

解决方法-参照官方文档:https://rasterio.readthedocs.io/en/latest/topics/concurrency.html

"""thread_pool_executor.pyOperate on a raster dataset window-by-window using a ThreadPoolExecutor.Simulates a CPU-bound thread situation where multiple threads can improve
performance.With -j 4, the program returns in about 1/4 the time as with -j 1.
"""import concurrent.futures
import multiprocessing
import threadingimport rasterio
from rasterio._example import computedef main(infile, outfile, num_workers=4):"""Process infile block-by-block and write to a new fileThe output is the same as the input, but with band orderreversed."""with rasterio.open(infile) as src:# Create a destination dataset based on source params. The# destination will be tiled, and we'll process the tiles# concurrently.profile = src.profileprofile.update(blockxsize=128, blockysize=128, tiled=True)with rasterio.open(outfile, "w", **src.profile) as dst:windows = [window for ij, window in dst.block_windows()]# We cannot write to the same file from multiple threads# without causing race conditions. To safely read/write# from multiple threads, we use a lock to protect the# DatasetReader/Writerread_lock = threading.Lock()write_lock = threading.Lock()def process(window):with read_lock:src_array = src.read(window=window)# The computation can be performed concurrentlyresult = compute(src_array)with write_lock:dst.write(result, window=window)# We map the process() function over the list of# windows.with concurrent.futures.ThreadPoolExecutor(max_workers=num_workers) as executor:executor.map(process, windows)

3. 成品代码

多线程方式裁剪

import rasterio as rio
from rasterio.mask import mask
import geopandas as gpdimport concurrent.futures
import threading
from rasterio import crs
import numpy as np
from PIL import Image
import timedef save_result(out_image, name):out_image_PIL = Image.fromarray(np.transpose(out_image, (1, 2, 0))).convert('RGB')out_image_PIL.save(name, "PNG", quality=95, optimize=True, progressive=True)print(name, "保存完毕")return nameif __name__ == '__main__':rasterPath = '/Users/donganning/Desktop/dan_ali_work_space/各种文件/临时实验数据/乌海市/Level16/乌海市.tif'shpfile = '/Users/donganning/Desktop/dan_ali_work_space/Air_Pro/air_project/测试遥感影像剪切/测试/乌海市shp/wuhai_test_1_wgs84.shp'"""1. polygon坐标系转换"""shpdata = gpd.read_file(shpfile)raw_crs = crs.CRS.from_epsg(4326)shpdata = shpdata.to_crs(raw_crs)polygon = shpdata.geometry[0]polygons = [polygon]*5"""2. 多线程处理"""result_list = []"""2.1 读取数据"""with rio.open(rasterPath) as rasterdata:# 定义读取锁read_lock = threading.Lock()"""2.2 定义处理方法"""def process(polygon):"""使用锁锁住rasterio DatasetReader对象,执行裁剪操作"""with read_lock:feature = [polygon.__geo_interface__]# 通过feature裁剪栅格影像out_image, out_transform = mask(rasterdata, feature, all_touched=True, crop=True,nodata=255)# 裁剪完毕,可以写入result = save_result(out_image, f"out-{time.time()}.png")result_list.append(result)"""2.3 执行多线程操作"""with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor:executor.map(process, polygons)print(result_list)

相关文章:

使用rasterio裁剪遥感影像

文章目录 0. 数据准备1. polygon的坐标系转换1.1 polygon生成1.1.1 输入数据是shapefile1.1.2 输入数据是polygon 1.2 搞清楚遥感的坐标系和polygon的坐标系(重点)1.3 开始转换 2. 基于polygon的遥感影像裁剪2.1 基础裁剪方法2.1.1 使用rasterio保存2.1.2 使用numpy保存2.2 多线…...

BetaFlight统一硬件配置文件研读之set命令

BetaFlight统一硬件配置文件研读之set命令 1. 源由2. 代码分析3. 实例分析4. 配置情况4.1 set4.2 set parameter_name4.3 set parameter_name value 5. 参考资料 统一硬件配置文件的设计是一种非常好的设计模式,可以将硬件和软件的工作进行解耦。 1. 源由 cli命令…...

QT+OpenGL高级数据和高级GLSL

QTOpenGL高级数据和高级GLSL 本篇完整工程见gitee:QtOpenGL 对应点的tag,由turbolove提供技术支持,您可以关注博主或者私信博主 高级数据 OpenGL中的缓冲区 对象管理特定的GPU内存 在将缓冲区绑定到特定的缓冲区目标时候赋予它意义 OpenGL在内部会保…...

接口测试之Jmeter+Ant+Jenkins接口自动化测试平台

目录 平台简介 环境准备 Jenkins简介 下载与安装 平台搭建 依赖文件配置 build.xml配置 Ant构建 阿里大佬倾情演绎,3天让你学会Jmeter接口测试,学不会算我输_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Q84y1K7bK/?spm_id_from333.99…...

FPGA设计中锁存器产生、避免与消除

FPGA设计中锁存器产生、避免与消除 一、锁存器的产生1.1 组合逻辑中使用保持状态1.2 组合逻辑中的if-else语句或case语句未列出所有可能性1.3 小结 二、锁存器的避免三、锁存器的消除3.1 情况一 一、锁存器的产生 锁存器的产生主要有以下两种情况:(1&…...

一份标准的软件测试方案模板

第一章 概述 ​ 软件的错误是不可避免的,所以必须经过严格的测试。通过对本软件的测试,尽可能的发现软件中的错误,借以减少系统内部各模块的逻辑,功能上的缺陷和错误,保证每个单元能正确地实现其预期的功能。检测和排…...

【C++】-对于自定义类型的输入输出运算符重载

&#x1f496;作者&#xff1a;小树苗渴望变成参天大树 ❤️‍&#x1fa79;作者宣言&#xff1a;认真写好每一篇博客 &#x1f4a8;作者gitee:gitee &#x1f49e;作者专栏&#xff1a;C语言,数据结构初阶,Linux,C 文章目录 前言一、案例引入二、<<的重载三、>>的…...

(详解)js中什么是宏任务、微任务?宏任务、微任务有哪些?又是怎么执行的?

目录 参考资料 必看强烈建议十分钟看完视频 &#xff0c;即可学会 必看参考详解宏任务微任务 笔记 宏任务与微任务 定时器的任务编排 promise的微任务处理逻辑 DOM渲染任务 任务队列共享内存 进度条的实现 任务拆分成多个任务 promise复杂任务分割 img算同步还是异步…...

Okta 即代码:云原生时代的身份管理

我们为什么应该将 Okta 配置作为代码进行管理&#xff1f; 对于需要跨多个应用程序和环境管理对其数字资源的访问的组织来说&#xff0c;Okta 可能是最受欢迎的选择&#xff0c;因为它提供了一系列使其在身份验证和授权方面很受欢迎的功能&#xff0c;例如&#xff1a; 单点登…...

数据结构(六)—— 二叉树(7)构建二叉树

文章目录 如何使用递归构建二叉树1、创建一颗全新树&#xff08;题1-5&#xff09;2、在原有的树上新增东西&#xff08;题6&#xff09; 1 106 从 后序 与 中序 遍历序列构造二叉树2 105 从 前序 与 中序 遍历序列构造二叉树3 108 将有序数组转换为二叉搜索树&#xff08;输入…...

安装适用于Linux的Windows11子系统(WSL2)

1. 主板BIOS开启虚拟化 开启虚拟化需要在BIOS中进行设置&#xff0c;进入主板BIOS→找到虚拟化设置→开启。 2. 检验是否开启虚拟化 打开Windows命令行&#xff0c;并运行 systeminfo固件中已启用虚拟化为是&#xff0c;代表主板BIOS已经开启虚拟化。 3. 启用Windows功能…...

使用Spring的五大类注解读取和存储Bean

目录 1.存储Bean对象的注解 1.1 五大类注解 1.2 方法注解 1.3添加注解的依赖 2.注解的使用 2.1 controller注解 2. 2Service注解 2.3.Resopsitory注解 2.4Component注解 2.5Configuration注解 2.6 注解之间的关系 3.方法注解 3.1 方法注解要配合类注解来使用。 3.2…...

Vue3通透教程【十一】初探TypeScript

文章目录 🌟 写在前面🌟 TypeScript是什么?🌟TypeScript 增加了什么?🌟TypeScript 初体验🌟 写在最后🌟 写在前面 专栏介绍: 凉哥作为 Vue 的忠实 粉丝输出过大量的 Vue 文章,应粉丝要求开始更新 Vue3 的相关技术文章,Vue 框架目前的地位大家应该都晓得,所谓…...

Linux环境安装iperf3(网络性能测试工具)

[rootlocalhost ]# yum search iperf 已加载插件&#xff1a;fastestmirror Loading mirror speeds from cached hostfile* base: mirrors.tuna.tsinghua.edu.cn* extras: mirrors.huaweicloud.com* updates: mirrors.tuna.tsinghua.edu.cnN/S matched: iperf iperf3-devel.i6…...

回顾第一章

回顾 Shell脚本中的$虚函数虚函数和纯虚函数 git merge/rebasegit merge特点git rebase特点 Linux内核调试——coredump获取core dump 深度测试和模板测试2D游戏的制作思路C11特性 Shell脚本中的$ ​ $0: 脚本自身的名称&#xff1b; $1: 传入脚本的第一个参数&#xff1b; $2…...

Jupyter Notebook入门教程

Jupyter Notebook&#xff08;又称Python Notebook&#xff09;是一个交互式的笔记本&#xff0c;支持运行超过40种编程语言。本文中我们将介绍Jupyter Notebook的主要特点&#xff0c;了解为什么它能成为人们创造优美的可交互式文档和教育资源的一个强大工具。 首先&#xff…...

独立按键识别

项目文件 文件 关于项目的内容知识点可以见专栏单片机原理及应用 的第四章 IO口编写 参考图电路编写程序&#xff0c;要求实现如下功能: 开始时LED均为熄灭状态&#xff0c;随后根据按键动作点亮相应LED(在按键释放后能继续保持该亮灯状态&#xff0c;直至新的按键压下时为止…...

【论文阅读】AlphaFold2阅读笔记

摘要 给一串氨基酸的序列&#xff0c;去预测他的结构是什么样的 蛋白质的折叠问题 alphaFold精度不够 这里可以达到原子精度的预测 CASP14 精度 这个是什么问题是不是解决了问题 模型的结果并不重要 导论 摘要故事的详细版本 在写论文的时候&#xff0c;可以这样写&a…...

机器学习基础知识之数据归一化

文章目录 归一化的原因1、最大最小归一化2、Z-score标准化3、不同方法的应用 归一化的原因 在进行机器学习训练时&#xff0c;通常一个数据集中包含多个不同的特征&#xff0c;例如在土壤重金属数据集中&#xff0c;每一个样本代表一个采样点&#xff0c;其包含的特征有经度、…...

QCC51XX---pydbg_cmd集合

目录 common pydbg_cmd headset pydbg_cmd earbud pydbg_cmd common pydbg_cmd log apps1.log_level() apps1.fw.gbl.debug_log_level__global 查看log等级apps1.fw.gbl.debug_log_level__global.value = 5 设置log等级 apps1.log()...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

模型参数、模型存储精度、参数与显存

模型参数量衡量单位 M&#xff1a;百万&#xff08;Million&#xff09; B&#xff1a;十亿&#xff08;Billion&#xff09; 1 B 1000 M 1B 1000M 1B1000M 参数存储精度 模型参数是固定的&#xff0c;但是一个参数所表示多少字节不一定&#xff0c;需要看这个参数以什么…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述&#xff0c;后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作&#xff0c;其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

深入理解JavaScript设计模式之单例模式

目录 什么是单例模式为什么需要单例模式常见应用场景包括 单例模式实现透明单例模式实现不透明单例模式用代理实现单例模式javaScript中的单例模式使用命名空间使用闭包封装私有变量 惰性单例通用的惰性单例 结语 什么是单例模式 单例模式&#xff08;Singleton Pattern&#…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

《基于Apache Flink的流处理》笔记

思维导图 1-3 章 4-7章 8-11 章 参考资料 源码&#xff1a; https://github.com/streaming-with-flink 博客 https://flink.apache.org/bloghttps://www.ververica.com/blog 聚会及会议 https://flink-forward.orghttps://www.meetup.com/topics/apache-flink https://n…...

AI编程--插件对比分析:CodeRider、GitHub Copilot及其他

AI编程插件对比分析&#xff1a;CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展&#xff0c;AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者&#xff0c;分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

微信小程序云开发平台MySQL的连接方式

注&#xff1a;微信小程序云开发平台指的是腾讯云开发 先给结论&#xff1a;微信小程序云开发平台的MySQL&#xff0c;无法通过获取数据库连接信息的方式进行连接&#xff0c;连接只能通过云开发的SDK连接&#xff0c;具体要参考官方文档&#xff1a; 为什么&#xff1f; 因为…...