基于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()
个人学习记录