前言:挺久没有更新博客了,前段时间课程实验中需要用代码将矢量数据转成栅格,常见的点栅格化方法通过计算将点坐标(X,Y)转换到格网坐标(I,J),线栅格化方法主要有DDA算法、Bresenham算法等,根据实现效果也可分为八方向和全路径栅格化方法等,面栅格化方法主要有种子点填充、扫面线算法、边界代数法等。详细算法实现可参考GIS中将矢量数据转换栅格数据算法 和 GIS算法基础(五)矢量数据向栅格数据的转换(点,线算法实现)这两篇博客。GDAL为用户提供了矢栅转换的方法,但网络上相关资料比较少,官方文档不明所以,因此本文将基于Python GDAL谈谈矢量转栅格的用法。
使用Python GDAL的RasterizeLayer()方法可以比较容易地实现矢量图层转换为栅格,先看看官方API文档给出的参数列表。
比较重要的参数有:
- dataset
- bands
- layer
- pfnTransformer 几何图形坐标转换图像行列号函数
pTransformArg 几何图形坐标转换图像行列号参数 - burn_values
- GDALProgressFunc callback 进度条回调函数
- options 可选的栅格化参数(字符串参数对),对于该参数文档官方文档没有详细说明,可以参考C++ GDAL的类似API,如下:
- "ATTRIBUTE":
指定输入矢量数据的属性字段中的字段值作为栅格值写入栅格文件中,该值将输出到所有输出波段中。假如该值指定了,burn_Values参数的值将失效数可以设置为空。
- "CHUNKYSIZE":
指定该运行操作的块的高度。该值越大所需的计算时间越小。如果该值没有设置或者设置为0则由GDAL的缓存大小根据公式:缓存所占的字节数/扫描函数的字节数得到。所以该值不会超出缓存的大小。
- "ALL_TOUCHED":
设置为TRUE表示所有的像素接触到矢量中线或多边形,否则只是多边形中心或被Bresenham算法选中的部分。默认值为FALSE。简单来说,FALSE是八方向栅格化,TRUE是全路径栅格化。
- 八方向栅格化:(图片来自https://malagis.com/gis-vector-grid-data-conversion-algorithm.html)
- 全路径栅格化:(图片来自https://malagis.com/gis-vector-grid-data-conversion-algorithm.html)
- "BURN_VALUE_FROM":
用于设置几何图形的Z值
- "MERGE_ALG":
设置重写或增加新值到栅格数据中。选择REPLACE为 重写,选择ADD为添加一个新值到已存在的栅格数据中。默认值为REPLACE。
矢量转栅格函数如下:
from osgeo import gdal,ogr,osr
from gdal import gdalconst
# 需要注意field,all_touch这些option的值必须为字符串
def vector2raster(inputfilePath, outputfile, templatefile,bands=[1],burn_values=[0],field="",all_touch="False"):
# 输入矢量文件
inputfilePath = inputfilePath
# 输出栅格文件
outputfile = outputfile
# 栅格模板文件,确定输出栅格的元数据(坐标系等,栅格大小,范围等)
templatefile = templatefile
# 打开栅格模板文件
data = gdal.Open(templatefile, gdalconst.GA_ReadOnly)
# 确定栅格大小
x_res = data.RasterXSize
y_res = data.RasterYSize
# 打开矢量文件
vector = ogr.Open(inputfilePath)
# 获取矢量图层
layer = vector.GetLayer()
# 查看要素数量
featureCount = layer.GetFeatureCount()
# print(featureCount)
# 创建输出的TIFF栅格文件
targetDataset = gdal.GetDriverByName('GTiff').Create(outputfile, x_res, y_res, 1, gdal.GDT_Byte)
# 设置栅格坐标系与投影
targetDataset.SetGeoTransform(data.GetGeoTransform())
targetDataset.SetProjection(data.GetProjection())
# 目标band 1
band = targetDataset.GetRasterBand(1)
# 白色背景
#NoData_value = -999
NoData_value = 255
band.SetNoDataValue(NoData_value)
band.FlushCache()
if field:
# 调用栅格化函数。RasterizeLayer函数有四个参数,分别有栅格对象,波段,矢量对象,options
# options可以有多个属性,其中ATTRIBUTE属性将矢量图层的某字段属性值作为转换后的栅格值
gdal.RasterizeLayer(targetDataset, bands,layer, burn_values=burn_values,options=["ALL_TOUCHED="+all_touch,"ATTRIBUTE="+field])
else:
gdal.RasterizeLayer(targetDataset, bands,layer, burn_values=burn_values,options=["ALL_TOUCHED="+all_touch])
对于ALL_TOUCHED属性实现的八方向和全路径栅格化,可以从下面两幅图看到结果略有不同,注意此时的ALL_TOUCHED属性设置必须全为字符串。
函数调用:
vector2raster(inputpath,outputpath,maskpath,field="",all_touch="False")
八方向(ALL_TOUCHED=False):
全路径(ALL_TOUCHED=True):
为了实现类似ArcGIS中矢量转栅格(每个要素赋不同值)的效果,可以先为用于测试的原始矢量数据添加一个属性字段用于赋值,例如下图的运动场面数据,以路网范围的栅格作为模板。
其属性表如下,pp_id为自行添加的字段,表示每个要素转换成栅格时的赋值:
函数调用:
vector2raster(inputpath,outputpath,maskpath,field="pp_id",all_touch="False")
得到的栅格化结果的每个要素具有不同的灰度值,对应pp_id字段的值。此时burn_values值会失效,根据pp_id字段值来对栅格赋值。