使用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++】-对于自定义类型的输入输出运算符重载
💖作者:小树苗渴望变成参天大树 ❤️🩹作者宣言:认真写好每一篇博客 💨作者gitee:gitee 💞作者专栏:C语言,数据结构初阶,Linux,C 文章目录 前言一、案例引入二、<<的重载三、>>的…...
(详解)js中什么是宏任务、微任务?宏任务、微任务有哪些?又是怎么执行的?
目录 参考资料 必看强烈建议十分钟看完视频 ,即可学会 必看参考详解宏任务微任务 笔记 宏任务与微任务 定时器的任务编排 promise的微任务处理逻辑 DOM渲染任务 任务队列共享内存 进度条的实现 任务拆分成多个任务 promise复杂任务分割 img算同步还是异步…...
Okta 即代码:云原生时代的身份管理
我们为什么应该将 Okta 配置作为代码进行管理? 对于需要跨多个应用程序和环境管理对其数字资源的访问的组织来说,Okta 可能是最受欢迎的选择,因为它提供了一系列使其在身份验证和授权方面很受欢迎的功能,例如: 单点登…...
数据结构(六)—— 二叉树(7)构建二叉树
文章目录 如何使用递归构建二叉树1、创建一颗全新树(题1-5)2、在原有的树上新增东西(题6) 1 106 从 后序 与 中序 遍历序列构造二叉树2 105 从 前序 与 中序 遍历序列构造二叉树3 108 将有序数组转换为二叉搜索树(输入…...
安装适用于Linux的Windows11子系统(WSL2)
1. 主板BIOS开启虚拟化 开启虚拟化需要在BIOS中进行设置,进入主板BIOS→找到虚拟化设置→开启。 2. 检验是否开启虚拟化 打开Windows命令行,并运行 systeminfo固件中已启用虚拟化为是,代表主板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 已加载插件: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: 脚本自身的名称; $1: 传入脚本的第一个参数; $2…...
Jupyter Notebook入门教程
Jupyter Notebook(又称Python Notebook)是一个交互式的笔记本,支持运行超过40种编程语言。本文中我们将介绍Jupyter Notebook的主要特点,了解为什么它能成为人们创造优美的可交互式文档和教育资源的一个强大工具。 首先ÿ…...
独立按键识别
项目文件 文件 关于项目的内容知识点可以见专栏单片机原理及应用 的第四章 IO口编写 参考图电路编写程序,要求实现如下功能: 开始时LED均为熄灭状态,随后根据按键动作点亮相应LED(在按键释放后能继续保持该亮灯状态,直至新的按键压下时为止…...
【论文阅读】AlphaFold2阅读笔记
摘要 给一串氨基酸的序列,去预测他的结构是什么样的 蛋白质的折叠问题 alphaFold精度不够 这里可以达到原子精度的预测 CASP14 精度 这个是什么问题是不是解决了问题 模型的结果并不重要 导论 摘要故事的详细版本 在写论文的时候,可以这样写&a…...
机器学习基础知识之数据归一化
文章目录 归一化的原因1、最大最小归一化2、Z-score标准化3、不同方法的应用 归一化的原因 在进行机器学习训练时,通常一个数据集中包含多个不同的特征,例如在土壤重金属数据集中,每一个样本代表一个采样点,其包含的特征有经度、…...
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()...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
Ubuntu系统下交叉编译openssl
一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机:Ubuntu 20.04.6 LTSHost:ARM32位交叉编译器:arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...
SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端
🌟 什么是 MCP? 模型控制协议 (MCP) 是一种创新的协议,旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议,它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
论文浅尝 | 基于判别指令微调生成式大语言模型的知识图谱补全方法(ISWC2024)
笔记整理:刘治强,浙江大学硕士生,研究方向为知识图谱表示学习,大语言模型 论文链接:http://arxiv.org/abs/2407.16127 发表会议:ISWC 2024 1. 动机 传统的知识图谱补全(KGC)模型通过…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
HarmonyOS运动开发:如何用mpchart绘制运动配速图表
##鸿蒙核心技术##运动开发##Sensor Service Kit(传感器服务)# 前言 在运动类应用中,运动数据的可视化是提升用户体验的重要环节。通过直观的图表展示运动过程中的关键数据,如配速、距离、卡路里消耗等,用户可以更清晰…...
回溯算法学习
一、电话号码的字母组合 import java.util.ArrayList; import java.util.List;import javax.management.loading.PrivateClassLoader;public class letterCombinations {private static final String[] KEYPAD {"", //0"", //1"abc", //2"…...
Web后端基础(基础知识)
BS架构:Browser/Server,浏览器/服务器架构模式。客户端只需要浏览器,应用程序的逻辑和数据都存储在服务端。 优点:维护方便缺点:体验一般 CS架构:Client/Server,客户端/服务器架构模式。需要单独…...
