基于alphashape算法提取Geo点集外轮廓+ST_ChaikinSmoothing(PGSQL+PostGIS)算法对外边界平滑处理

  1 import pickle
  2 import psycopg2
  3 import alphashape
  4 import numpy as np
  5 import geopandas as gpd
  6 import matplotlib.pyplot as plt
  7 from shapely.geometry import Point
  8 
  9 # table_exist
 10 def table_exist(table_name=None, conn=None, cur=None):
 11     try:
 12         cur.execute("select to_regclass(" + "\'" + table_name + "\'" + ") is not null")
 13         rows = cur.fetchall()
 14     except Exception as e:
 15         rows = []
 16         conn.close()
 17     if rows:
 18         data = rows
 19         flag = data[0][0]
 20         return flag
 21 # X2GDF
 22 def X2GDF(X, input_crs = "EPSG:2436", output_crs = "EPSG:4326", plot=True):
 23     # input_crs = "EPSG:2436"# input_crs = "EPSG:4326"
 24     # output_crs = "EPSG:4326"# output_crs = "EPSG:2436"
 25     coords, IDs = [], []
 26     for i in range(X.shape[0]):
 27         coords.append(Point(X[i, 0], X[i, 1]))# (X, Y)
 28         IDs.append("%d" % i)
 29     data = {'ID': IDs, 'geometry': coords}
 30     gdf = gpd.GeoDataFrame(data, crs=input_crs)
 31     # print(gdf.crs)  # 查看数据对应的投影信息(坐标参考系)
 32     if output_crs is not None:
 33         gdf.to_crs(crs=output_crs)# (Lon, Lat)
 34 
 35     if plot:
 36         gdf.plot()
 37         plt.show()#展示
 38 
 39     return gdf
 40 # GDF2X
 41 def GDF2X(gdata, to_epsg=2436, plot=True):
 42     print('input gdf crs:', gdata.crs)  # 查看数据对应的投影信息(坐标参考系) ---> epsg == 4326  (WGS_84)
 43     gdata = gdata.to_crs(epsg=to_epsg)# epsg == 2436 (X, Y), 4326 (lon, lat)
 44     print('output X crs:', gdata.crs)
 45     # print(gdata.columns.values)# 列名
 46     # print(gdata.head())  # 查看前5行数据
 47     if plot:
 48         gdata.plot()
 49         plt.show()#展示
 50     geo = gdata.geometry.values
 51     X0, Y0 = geo.x, geo.y
 52     X = np.zeros(shape=(X0.shape[0], 2), dtype=float)
 53     for i in range(X0.shape[0]):
 54         X[i, 0], X[i, 1] = X0[i],  Y0[i]
 55     return X
 56 # LonLat2XY
 57 def LonLat2XY(X, input_crs = "EPSG:4326", output_crs = "EPSG:3857", shpfile_name = "point_shp.shp"):
 58     # index = ['node_'+str(node) for node in range(X.shape[0])]
 59     # columns = ['column_'+str(col) for col in range(X.shape[1])]
 60     # df = pd.DataFrame(X, index=index, columns=columns)
 61     coords, IDs = [], []
 62     for i in range(X.shape[0]):
 63         coords.append(Point(X[i, 0], X[i, 1]))  # (X, Y)
 64         IDs.append("%d" % i)
 65 
 66     data = {'ID': IDs, 'geometry': coords}
 67     gdf = gpd.GeoDataFrame(data, crs=input_crs)
 68 
 69     print('input crs', gdf.crs)  # 查看数据对应的投影信息(坐标参考系)
 70     if output_crs is not None:
 71         gdf.to_crs(crs=output_crs)  # (Lon, Lat)
 72 
 73     print('output crs', gdf.crs)  # 查看数据对应的投影信息(坐标参考系)  output_crs = "EPSG:3857" or "EPSG:2436"
 74     if shpfile_name is not None:# shpfile = "point_shap.shp"
 75         gdf.to_file(filename=shpfile_name)
 76         print('shpfile is saved')
 77 
 78     geo = gdf.geometry.values
 79     X0, Y0 = geo.x, geo.y
 80     X = np.zeros(shape=(X0.shape[0], 2), dtype=float)
 81     for i in range(X0.shape[0]):
 82         X[i, 0], X[i, 1] = X0[i], Y0[i]
 83 
 84     return X
 85 # get_X_fromSHP
 86 def get_X_fromSHP(filename=r'./park/BJ_park_m.shp', epsg4326_srid=2436, plot=True):
 87     gdata = gpd.read_file(filename=filename, bbox=None, mask=None, rows=None)#读取磁盘上的矢量文件
 88     # gdata = gpd.read_file(filename=r'CUsersjeshyDocumentsArcGISJ50.gdb', layer='BOUA')#读取gdb中的矢量数据
 89     print('Input geodata crs:', gdata.crs)  # 查看数据对应的投影信息(坐标参考系) ---> epsg == 4326  (WGS_84)
 90     gdata = gdata.to_crs(epsg=epsg4326_srid)# epsg == 2436 (X, Y)
 91     print('Output geodata crs:', gdata.crs)
 92     print('Column names', gdata.columns.values)# 列名
 93     # print(gdata.head())  # 查看前5行数据
 94     if plot:
 95         gdata.plot()
 96         plt.show()#展示
 97 
 98     geo = gdata.geometry.values
 99     X0, Y0 = geo.x, geo.y
100     X = np.zeros(shape=(X0.shape[0], 2), dtype=float)
101     for i in range(X0.shape[0]):
102         X[i, 0], X[i, 1] = X0[i],  Y0[i]
103 
104     print('n_samples:', X0.shape[0])
105     output = open('X.pkl', 'wb')
106     pickle.dump(X, output)
107     output.close()
108     print('X.pkl is saved')
109 
110     from sklearn.preprocessing import StandardScaler
111     X_trans = StandardScaler().fit_transform(X)
112     output = open('trans_X.pkl', 'wb')
113     pickle.dump(X_trans, output)
114     output.close()
115     print('trans_X.pkl is saved')
116 
117     return X
118 
119 if __name__ == '__main__':
120     # Load the geodata
121     output = open('park_X.pkl', 'rb')# park_X = get_X_fromSHP(filename=r'./park/BJ_park_m.shp', epsg4326_srid=2436, plot=True)
122     X = pickle.load(output)
123     output.close()
124 
125     input_crs = "EPSG:2436"
126     output_crs = None
127 
128     X_uniques = np.unique(X, axis=0)# 去除重复行
129     if X_uniques.shape[0] > 2:
130         # get the outlines by alphashape method
131         gdf_alpha_shape = alphashape.alphashape(X2GDF(X_uniques, input_crs=input_crs, output_crs=output_crs, plot=None))
132         polyg = gdf_alpha_shape.geometry.values  # GeometryArray
133         polyg = polyg[0]  # Not smoothed poly_line
134 
135         # pgsql-postgis with ST_ChaikinSmoothing
136         Polyg_wkt_str, SRID_str = polyg.wkt, input_crs.split(':')[-1]
137         sql = 'select ST_ChaikinSmoothing(ST_GeomFromEWKT(\'SRID={0};{1}\'),5) as the_geom;'.format(SRID_str, Polyg_wkt_str)
138 
139         # connection the database
140         table_name = "beijing"
141         conn = psycopg2.connect(database=table_name, user="postgres", password="jiangshan", host="localhost", port="5432")
142 
143         # cur = conn.cursor()
144         # # CREATE TABLE IF table IS NOT EXIST
145         # # 查询出来的表是否存在的状态,存在则为True,不存在则为False
146         # table_flg = table_exist(table_name, conn, cur)
147         # if table_flg is False:
148         #     sql = "DROP TABLE public.{0} CASCADE".format(table_name)  # -- 删除表
149         #     sql = "CREATE TABLE IF NOT EXISTS {0} (serial_number BIGINT, code_company TEXT, lon DOUBLE PRECISION, lat DOUBLE PRECISION, state INT)".format(table_name)
150         #     cur.execute(sql)
151         #     conn.commit()
152         #     cur.close()
153 
154         out = gpd.read_postgis(sql=sql, con=conn, geom_col="the_geom")
155         polyg = out['the_geom'].values  # GeometryArray
156         polyg = polyg[0]  # Smoothed poly_line
157         # close
158         conn.close()

 

posted @ 2021-08-08 16:43  土博姜山山  阅读(687)  评论(0)    收藏  举报