赞
踩
gdalwarp 实用程序是一种图像拼接、重投影和扭曲实用程序。该程序可以重新投影到任何支持的投影。如果图像是带有控制信息的“原始”图像,也可以存储原始图像的投影信息。
gdal.warp官网链接:
https://gdal.org/api/python/osgeo.gdal.html#osgeo.gdal.Warp
def extractTiff(input_shape,input_raster,output_raster):
#裁剪
input_raster = gdal.Open(input_raster)
# 开始裁剪
result = gdal.Warp(output_raster,
input_raster,
format='GTiff',
cutlineDSName=input_shape,
cropToCutline=True)
result.FlushCache()
del result
gdal.Warp主要参数如下:
gdal.Warp(options = [], format = 'GTiff', outputBounds = None, outputBoundsSRS = one, xRes = None, yRes = None, targetAlignedPixels = False, width = 0, height = 0, srcSRS = None, dstSRS = None, srcAlpha = False, dstAlpha = False, warpOptions = None, errorThreshold = None, warpMemoryLimit = None, creationOptions = None, outputType = GDT_Unknown, workingType = GDT_Unknown, resampleAlg = None, srcNodata = None, dstNodata = None, multithread = False, tps = False, rpc = False, geoloc = False, polynomialOrder = None, transformerOptions = None, cutlineDSName = None, cutlineLayer = None, cutlineWhere = None, cutlineSQL = None, cutlineBlend = None, ropToCutline = False, copyMetadata = True, metadataConflictValue = None, setColorInterpretation = False, callback = None, callback_data = None): 其中: options — 可以是一个字符串数组,一个字符串或者令其为空值,但是使用后面其他的参数来定义。 format — 输出的格式 (例如"GTiff"等)。 outputBounds — 在目标空间参考系统的输出数据集的范围,形式为 (minX,minY, maxX, maxY) 。 outputBoundsSRS — 如果在dstSRS中没有定义的话,使用这个关键字定义输出数据集的边界的空间参考系统。 xRes, yRes — 在目标参考系统中的像元大小。 targetAlignedPixels —是否强制输出边界为输出分辨率的倍数。 width — 输出栅格的像素列数。 height — 输出栅格的像素行数。 srcSRS —源空间参考系统。 dstSRS — 输出空间参考系统。 srcAlpha — 是否强制将输入数据集的最后一个波段作为alpha波段。 dstAlpha — 是否强制创建一个输出数据集的alpha波段。 outputType — 输出类型 (例如gdal.GDT_Byte等) workingType — working type (gdal.GDT_Byte, etc…) warpOptions —变形选项列表。 errorThreshold --近似转换的误差阈值(用像素表示) 。 warpMemoryLimit — 工作缓存大小,单位是bytes。 resampleAlg — 重采样模式。 creationOptions — 创建选项列表。 srcNodata — 源数据的nodata值。 dstNodata — 输出数据的nodata值。 multithread — 是否多线程计算和输入输出操作。 tps— 是否使用Thin Plate Spline GCP 转换器。 rpc— 是否使用RPC转换器。 geoloc — 是否使用GeoLocation数组转换器。 polynomialOrder — 多项式GCP插值的阶数。 transformerOptions — 转换参数 cutlineDSName — 剪切线数据集名称。这里的剪切线是指对影像进行剪切的时候所使用的矢量图层。 cutlineLayer — 剪切线图层名称。 cutlineWhere — 剪切线的WHERE语句。 cutlineSQL — 剪切线的SQL 语句。 cutlineBlend — 以像素为单位的剪切线混合距离。 cropToCutline — 是否使用剪切线的extent作为输出的界线。 copyMetadata — 是否拷贝源数据的元数据。 metadataConflictValue — 元数据冲突值。 setColorInterpretation — 是否强制将输入波段的颜色解释赋予输出波段。 callback — 回调函数。 callback_data — 回调函数数据
cropToCutline为True时,使用剪切线的extent作为输出的界线;dstNodata='NULL’时,可将背景值设置为空。此方法非常好用,强烈推荐。
注意cropToCutline默认为False,默认界限为输入矢量图的界限,使用默认设置会导致裁剪后的图片非常大(见下图设置不同的dstNodata后的文件大小)。另外还可以参考这篇文章的说明:python批量遥感影像裁剪的三种方法
基本原理可以参考:GDAL和 Pillow 的互操作
网上公开的代码是通过PIL与GDAL栅格数据互操作,将栅格数据转换为PIL中的对象,使用PyShp读取矢量边界,裁剪PIL,最后通过数组,转回栅格数据。以下是完整代码
#!/usr/bin/env python # -*- encoding: utf-8 -*- ''' @File : k_factor.py @Time : 2022/09/26 08:45:09 @Author : Junlai @Version : 1.0 @Desc : None ''' import os,shapefile from osgeo import gdal, gdal_array, ogr from PIL import Image, ImageDraw def image2Array(i): """ 将一个Python图像库的数组转换为一个gdal_array图片 """ a = gdal_array.numpy.frombuffer(i.tobytes(), 'b') a.shape = i.im.size[1], i.im.size[0] return a def world2Pixel(geoMatrix, x, y): """ 使用GDAL库的geomatrix对象((gdal.GetGeoTransform()))计算地理坐标的像素位置 """ ulx = geoMatrix[0] uly = geoMatrix[3] xDist = geoMatrix[1] yDist = geoMatrix[5] rtnX = geoMatrix[2] rtnY = geoMatrix[4] pixel = int((x - ulx) / xDist) line = int((uly - y) / abs(yDist)) return (pixel, line) def extractFromShp(input_raster,input_shape,output_raster): # 用于裁剪的栅格数据 raster = input_raster # 裁剪后的栅格数据 output = output_raster # 将数据源作为gdal_array载入 srcArray = gdal_array.LoadFile(raster) # 同时载入gdal库的图片从而获取geotransform srcImage = gdal.Open(raster) geoTrans = srcImage.GetGeoTransform() geoProj = srcImage.GetProjection() # # 使用PyShp库打开shp文件 shp = input_shape r = shapefile.Reader("{}.shp".format(shp)) # # 将图层扩展转换为图片像素坐标 minX, minY, maxX, maxY = r.bbox ulX, ulY = world2Pixel(geoTrans, minX, maxY) lrX, lrY = world2Pixel(geoTrans, maxX, minY) # 计算新图片的尺寸 pxWidth = int(lrX - ulX) pxHeight = int(lrY - ulY) clip = srcArray[ulY:lrY, ulX:lrX] # 为图片创建一个新的geomatrix对象以便附加地理参照数据 geoTrans = list(geoTrans) geoTrans[0] = minX geoTrans[3] = maxY # 在一个空白的8字节黑白掩膜图片上把点映射为像元 # 边界线 pixels = [] for p in r.shape(0).points: pixels.append(world2Pixel(geoTrans, p[0], p[1])) rasterPoly = Image.new("L", (pxWidth, pxHeight), 1) # 使用PIL创建一个空白图片用于绘制多边形 rasterize = ImageDraw.Draw(rasterPoly) rasterize.polygon(pixels, 0) # 使用PIL图片转换为Numpy掩膜数组 mask = image2Array(rasterPoly) # 根据掩膜图层对图像进行裁剪 clip = gdal_array.numpy.choose(mask, (clip, 0)).astype(gdal_array.numpy.uint8) print(clip.max()) # 保存为tiff文件 gdal_array.SaveArray(clip, "{}.tif".format(output),format="GTiff") if __name__ == '__main__': pj_path = os.path.abspath( os.path.dirname(os.path.abspath(os.path.dirname(__file__)))) fpath = os.path.join(pj_path, 'data') input_shape = f'{fpath}\\boundary\\input' output_raster = f'{fpath}\\out' # tif输入路径,打开文件 input_raster = f'{fpath}\\lu\\input.tif' # 矢量裁剪栅格 extractFromShp(input_raster,input_shape,output_raster)
该方法存在一个小bug,当矢量文件属性表存在中文,会出现以下报错,
解决方法可以简单粗暴,直接修改PyShp源码:
self.encoding = kwargs.pop('encoding', 'utf-8')
修改为self.encoding = kwargs.pop('encoding', 'gbk')
笔者尝试直接用ogr替代PyShp,完成上述操作,完全可行,结果一致,在此不表,感兴趣的可以自行尝试。
过于简单粗暴,在此不表
有个小的BUG,暂时还没摸清楚原因,MARK一下:
使用GDAL结合PIL裁剪后的栅格图,会比ArcTool少一行,GDAL.WRAP裁剪时会少两行一列。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。