python gdal 矢量(shapefile)平滑 与 arcpy 矢量文件平滑对比,arcpy shp文件平滑时间过长

最近遇到一个问题,就是对shapefile文件(矢量面文件)进行平滑的时候,由于数据比较大(我的shp文件大约30多兆),导致调用arcpy平滑过程非常非常慢,大概40-50分钟,但是在arcgis里面处理就很快,只需要几分钟。为了降低平滑时间,我在网上进行了各种搜索,也没有看到有人遇到类似的问题。后来搜到了用gdal对shp文件进行平滑的代码,想用gdal进行shp文件的平滑,但是gdal平滑的结果有问题。下面就先将gdal和arcpy进行平滑的做个对比。

1. gdal对矢量面文件进行平滑

代码如下:

from osgeo import ogr
from pathlib import Path
import os

def shapefile_edge_smooth(_input_shapefile, _smoothed_shapefile_output_path, _buffer_distance=0.0005):
    '''平滑矢量文件边界
    _input_shapefile:输入的矢量文件路径
    _smoothed_shapefile_output_path:平滑后输出的矢量文件路径
    _buffer_distance:平滑缓冲区距离,单位是米,可以根据影像分辨率设定,不能低于影像分辨率'''
    in_ds = ogr.Open(_input_shapefile)
    in_lyr = in_ds.GetLayer()
    # feature_number = in_lyr.GetFeatureCount()
    driver = ogr.GetDriverByName('ESRI Shapefile')
    if Path(_smoothed_shapefile_output_path).exists():
        # 如果输出的文件存在,则删除这个文件
        driver.DeleteDataSource(_smoothed_shapefile_output_path)
    out_ds = driver.CreateDataSource(_smoothed_shapefile_output_path)
    out_lyr = out_ds.CreateLayer(_smoothed_shapefile_output_path, in_lyr.GetSpatialRef(), ogr.wkbPolygon)
    def_feature = out_lyr.GetLayerDefn()

    for feature in in_lyr:
        geometry = feature.GetGeometryRef()
        _buffer = geometry.Buffer(_buffer_distance).Buffer(-1 * _buffer_distance)
        out_feature = ogr.Feature(def_feature)
        out_feature.SetGeometry(_buffer)
        out_lyr.CreateFeature(out_feature)
        out_feature = None
    out_ds.FlushCache()
    in_ds.Destroy()
    out_ds.Destroy()


if __name__ == '__main__':
    input_shp = r'D:\data\test_data\HZ\shp\HZ.shp'
    output_shp = r'D:\data\test_data\HZ\smooth_result\gdal_smoothed2.shp'
    shapefile_edge_smooth(input_shp, output_shp)

2. arcpy对矢量面文件进行平滑

代码如下:

# encoding=utf8
# Import system modules
import os
import arcpy
import arcpy.cartography as CA
import arcpy.management as DM
import time
arcpy.env.overwriteOutput = True


def smooth_shp(workspace_path, inshp_path, outshp_path):
    # 设置workspace路径
    tempworkspace = os.path.join(workspace_path, 'tempworkspace.gdb')
    arcpy.env.workspace = tempworkspace
    infeature_layer = os.path.join(tempworkspace, 'infeatures')

    arcpy.MakeFeatureLayer_management(inshp_path, infeature_layer)  #将shp文件转换为feature layer
    CA.SmoothPolygon(infeature_layer, outshp_path, "PAEK", 0.0005, "", "FLAG_ERRORS")  #矢量面平滑
    

if __name__ == '__main__':
    smoothed_result = r'D:\data\test_data\HZ\smoothed_result.shp'
    shp_path = r'D:\data\test_data\HZ\shp\infeature.shp'
    workspace_path = r'D:\data\test_data\HZ\shp'
    smooth_shp(workspace_path, inshp_path=shp_path, outshp_path=smoothed_result)
    

3. gdal和arcpy平滑结果对比

下图的黑线是原始数据的图斑边界红线是gdal平滑后的图斑边界蓝线是arcpy平滑后的图斑边界
在这里插入图片描述
可以看出,gdal和arcpy的平滑都相较原始数据的边界都少了锯齿和尖角,可见平滑都是有效果的。二者的结果边界不太一样,可能是内置的算法的问题,这样看起来gdal和arcpy平滑效果都还不错

但是,真的如此吗?

再看一些结果对比
在这里插入图片描述

可以看出,gdal的平滑结果在图斑内部生成了很多⚪,而且gdal平滑的边界不准。两种平滑方法我的平滑的单位都是设置的0.0005,完全一样的参数。 但是gdal的平滑外边界明显比arcpy平滑的边界大很多,也会在图形内部生成不必要的边界线(这可能跟gdal平滑方法是建立在buffer上有关)。所以gdal平滑不太适用于我这个数据量大,图形复杂的数据上,但是有些图形相对简单的数据gdal的结果还是可以的

最终还是得用arcpy进行数据平滑。

但是调用arcpy进行smooth的时候,太慢了,这又是怎么回事呢?

4. 调用arcpy 进行smooth polygon 时间过长

经过我无数次的实验和调参数,加上查阅官方帮助文档,发现,arcpy 用来平滑的函数SmoothPolygon,需要输入以下参数SmoothPolygon(infeature_layer, outshp_path, “PAEK”, 0.0005, “”, “FLAG_ERRORS”)

下面一个一个讲解这几个参数含义:
infeature_layer:输入数据集要素
outshp_path:输出文件路径
“PAEK”:平滑所采用的算法,可以是 “PAEK"或者"BEZIER_INTERPOLATION”
0.0005:容差,一般以米为单位的话是15左右比较合适(因数据而异),这里我的数据是经纬度,所以我用了一个很小的值。
“FLAG_ERRORS”:这个参数是对于数据中的拓扑错误是否检查,arcgis10.8有三种选项:“NO_CHECK”,"FLAG_ERRORS"和"RESOLVE_ERRORS"分别对应不检擦拓扑错误,检查并标记拓扑错误和解决拓扑错误,arcgis10.2只有前两种选项。

在arcgis中,进行平滑默认是"NO_CHECK"即不检查拓扑错误,所以运行起来很快。但是arcpy调用的时候,官方文档中推荐的是"FLAG_ERRORS",所以我也写的"FLAG_ERRORS",这就导致遇到特别大的数据时运行特别特别慢,当改成"NO_CHECK"后就快了。就是这个小小的问题,困扰了我好久啊,在这里记录一下,希望能够帮助到大家。

猜你喜欢

转载自blog.csdn.net/persist_ence/article/details/127903046