python 网格_python 栅格处理利器之Rasterio

本文主要是Automatize data download​automating-gis-processes.github.io

中栅格图像处理的学习笔记,分享给大家,同时也便于自己记忆以及查看,节省时间。数据准备

如果手头有数据,可以跳过该步骤,如果没有,可以按照原文提供的下载链接,保存数据。

import os

import urllib

def get_filename(url):

"""

Parses filename from given url

"""

if url.find('/'):

return url.rsplit('/', 1)[1]

# 保存路径

outdir = r"data"

# 如果没有路径,在当前环境路径下创建

if not os.path.exists(outdir):

os.makedirs(outdir)

# url

url_list = ["https://github.com/Automating-GIS-processes/CSC18/raw/master/data/Helsinki_masked_p188r018_7t20020529_z34__LV-FIN.tif"]

# 数据下载

for url in url_list:

# Parse filename

fname = get_filename(url)

outfp = os.path.join(outdir, fname)

# Download the file if it does not exist already

if not os.path.exists(outfp):

print("Downloading", fname)

r = urllib.request.urlretrieve(url, outfp)读取

以前面下载的数据为例,数据读取操作如下,rasterio的数据读取还是很python的,这也是分享的主要的原因。

import rasterio

import os

import numpy as np

%matplotlib inline

# 数据路径,根据自己的需求设定

data_dir = "data"

fp = os.path.join(data_dir, "Helsinki_masked_p188r018_7t20020529_z34__LV-FIN.tif")

#

raster = rasterio.open(fp)

type(raster)

数据读取之后,需要查看栅格的属性,不得不说,感觉这这方面还是Matlab方便,读取之后能直接看到各种属性的变量,直接手动点击就可以方便查看。

地理栅格数据的主要的属性有坐标系、仿射变换(Affine transform)、维度、波段、缺失值格式以及边界等,实现如下

raster.crs # 坐标系

raster.transform # 仿射变换

(raster.width,raster.height) # 维度

raster.count # 波段

raster.nodatavals # 缺失值

raster.dirver # 数据格式

# 上面的所有信息,也可以通过raster.meta一次展示

raster.meta

如果需要查看波段的具体的数值以及统计信息,则可以通过如下的操作实现

band1 = raster.read(1) # 第一波段属性值

# 所有波段

array = raster.read()

# 统计每个波段的信息

stats = []

for band in array:

stats.append({

'min': band.min(),

'mean': band.mean(),

'median': np.median(band),

'max': band.max()})

# 展示统计信息

stats可视化

对于前面的读入的数据,通过以下简单的命令即可

import matplotlib.pyplot as plt

from rasterio.plot import show

%matplotlib inline

# band 1

show((raster, 1))

fig, (ax1, ax2, ax3) = plt.subplots(ncols=3, nrows=1, figsize=(10, 4), sharey=True)

# rgb 展示

show((raster, 4), cmap='Reds', ax=ax1)

show((raster, 3), cmap='Greens', ax=ax2)

show((raster, 1), cmap='Blues', ax=ax3)

# 添加标题

ax1.set_title("Red")

ax2.set_title("Green")

ax3.set_title("Blue")图像合成

假彩色或者真彩色的合成,此处以假彩色为例,真彩色的合成同理。

# 假彩色合成

nir,red,green = raster.read(4),raster.read(3),raster.read(2)

def normalize(array):

"""Normalizes numpy arrays into scale 0.0 - 1.0"""

array_min, array_max = array.min(), array.max()

return ((array - array_min)/(array_max - array_min))

# 标准化

nirn,redn,greenn = normalize(nir),normalize(red),normalize(green)

# 图像合成

nrg = np.dstack((nirn, redn, greenn))

plt.imshow(nrg)

栅格属性的直方图展示

# 栅格

from rasterio.plot import show_hist

show_hist(raster, bins=50, lw=0.0, stacked=False, alpha=0.3,

histtype='stepfilled', title="Histogram")矢量裁剪

栅格中最为常见的功能之一,rasterio中的操作可以通过如下代码实现,直接运行原文的代码可能会因为坐标系的转换出现错误,此处稍微做了修改。

此处涉及到的geopandas包是矢量处理的利器,依赖包包括shapely、fiona等,可以直接通过conda install geopandas 的方式安装,省去麻烦,pycrs包可以通过pip安装。

栅格的保存也是比较重要的操作,在裁剪的过程中保存结果的代码也在此处提及。

from rasterio.mask import mask

from shapely.geometry import box

import geopandas as gpd

from fiona.crs import from_epsg

import pycrs

%matplotlib inline

# 保存

out_tif = os.path.join(data_dir, "Helsinki_Masked.tif")

# 根据raster边界创建边界

minx, miny = 700000,6660000

maxx, maxy = 730000, 6690000

bbox = box(minx, miny, maxx, maxy)

geo = gpd.GeoDataFrame({'geometry': bbox}, index=[0], crs=raster.crs.data)

# geo.plot()

def getFeatures(gdf):

"""Function to parse features from GeoDataFrame in such a manner that rasterio wants them"""

import json

return [json.loads(gdf.to_json())['features'][0]['geometry']]

coords = getFeatures(geo)

# 裁剪

out_img, out_transform = mask(dataset=raster, shapes=coords, crop=True)

# 输出属性信息

out_meta = raster.meta.copy()

out_meta.update({"driver": "GTiff",

"height": out_img.shape[1],

"width": out_img.shape[2],

"transform": out_transform,

"crs":raster.crs}

)

with rasterio.open(out_tif, "w", **out_meta) as dest:

dest.write(out_img)栅格数值运算

以NDVI计算为例,计算的结果的保存可以参照裁剪的计算,并保存ndvi图像。

# red波段

red = raster.read(3)

# 近红外-NIR波段

nir = raster.read(4)

# 数值类型转换

red = red.astype('f4')

nir = nir.astype('f4')

np.seterr(divide='ignore', invalid='ignore')

# ndvi 计算

ndvi = (nir - red) / (nir + red)

#

plt.imshow(ndvi, cmap='terrain_r')

# 添加colorbar

plt.colorbar()

其余的部分在后续进行补充,最近在项目中涉及到的矢量以及栅格的运算的操作,也计划慢慢分享给大家。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值