Skip to content

Commit

Permalink
move building classifier script and data to a folder
Browse files Browse the repository at this point in the history
  • Loading branch information
weiqi-tori committed May 30, 2024
1 parent f93acc8 commit 4329fb6
Show file tree
Hide file tree
Showing 6 changed files with 337 additions and 37 deletions.
2 changes: 1 addition & 1 deletion city_metrix/layers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@
from .built_up_height import BuiltUpHeight
from .average_net_building_height import AverageNetBuildingHeight
from .open_buildings import OpenBuildings
from .tree_canopy_hight import TreeCanopyHeight
from .tree_canopy_height import TreeCanopyHeight
303 changes: 303 additions & 0 deletions city_metrix/layers/building_classifier/V2-building-class-data.geojson

Large diffs are not rendered by default.

Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,18 @@
import matplotlib.pyplot as plt
from xrspatial.classify import reclassify
from exactextract import exact_extract
import pickle

from .layer import Layer, get_utm_zone_epsg
from .esa_world_cover import EsaWorldCover, EsaWorldCoverClass
from .urban_land_use import UrbanLandUse
from .average_net_building_height import AverageNetBuildingHeight
from .open_street_map import OpenStreetMap, OpenStreetMapClass
from .open_buildings import OpenBuildings
from ..layer import Layer, get_utm_zone_epsg
from ..esa_world_cover import EsaWorldCover, EsaWorldCoverClass
from ..urban_land_use import UrbanLandUse
from ..average_net_building_height import AverageNetBuildingHeight
from ..open_street_map import OpenStreetMap, OpenStreetMapClass
from ..open_buildings import OpenBuildings


class BuildingClassifier(Layer):
def __init__(self, geo_file=None, **kwargs):
def __init__(self, geo_file='V2-building-class-data.geojson', **kwargs):
super().__init__(**kwargs)
self.geo_file = geo_file

Expand All @@ -46,7 +47,6 @@ def get_data_esa_reclass(self, bbox, crs):
EsaWorldCoverClass.HERBACEOUS_WET_LAND.value: 20,
EsaWorldCoverClass.MANGROVES.value: 20,
EsaWorldCoverClass.MOSS_AND_LICHEN.value: 3
# Add other mappings as needed
}

# Perform the reclassification
Expand Down Expand Up @@ -147,20 +147,21 @@ def rasterize_polygon(self, gdf, snap_to):
return raster.rio.reproject_match(snap_to)


def building_class_tree(self):
def building_classifier_tree(self):
buildings_sample = self.get_data_geo()
bbox = buildings_sample.reset_index().total_bounds
crs = get_utm_zone_epsg(bbox)

# building_sample has extracted data and saved in geojson

# # Building sample 'V2-building-class-data.geojson' has extracted data and saved in geojson,
# # so no need for steps below
# # Step 1: Get raster data
# bbox = buildings_sample.reset_index().total_bounds
# crs = get_utm_zone_epsg(bbox)
# esa_1m = BuildingClassifier().get_data_esa_reclass(bbox, crs)
# ulu_lulc_1m = self.get_data_ulu(bbox, crs, esa_1m)
# anbh_1m = self.get_data_anbh(bbox, esa_1m)

# # Extract 3 features for buildings:
# # majority of Urban Land Use(ULU) class
# # mean Average Net Building Height(ANBH)
# # area of the building
# # Step 2: Extract 3 features for buildings:
# # 2.1 majority of Urban Land Use(ULU) class
# # 2.2 mean Average Net Building Height(ANBH)
# # 2.3 area of the building
# buildings_sample['ULU'] = exact_extract(ulu_lulc_1m, buildings_sample, ["majority"], output='pandas')['majority']
# buildings_sample['ANBH'] = exact_extract(anbh_1m, buildings_sample, ["mean"], output='pandas')['mean']
# buildings_sample['Area_m'] = buildings_sample.geometry.area
Expand All @@ -172,23 +173,25 @@ def building_class_tree(self):

# Select these rows for the training set
build_train = buildings_sample[buildings_sample['Model']=='training']
# Select the remaining rows for the testing set
build_test = buildings_sample[buildings_sample['Model']=='testing']

clf.fit(build_train[['ULU', 'ANBH', 'Area_m']], build_train['Slope_encoded'])

# save decision tree classifier
with open('building_classifier.pkl','wb') as f:
pickle.dump(clf, f)

# # Check decision tree and accuracy
# # Select the remaining rows for the testing set
# build_test = buildings_sample[buildings_sample['Model']=='testing']
# plt.figure(figsize=(20, 10))
# plot_tree(clf, feature_names=['ULU', 'ANBH', 'Area_m'], class_names=['low','high'], filled=True)
# plt.show()
# # Predict and evaluate
# y_pred = clf.predict(build_train[['ULU', 'ANBH', 'Area_m']])
# accuracy = accuracy_score(build_train['Slope_encoded'], y_pred)
# print(f"Accuracy: {accuracy}")
# print(f"Training Accuracy: {accuracy}")
# len(build_train[build_train['Slope']==build_train['pred']])/len(build_train)

# y_pred = clf.predict(build_test[['ULU', 'ANBH', 'Area_m']])
# accuracy = accuracy_score(build_test['Slope_encoded'], y_pred)
# print(f"Accuracy: {accuracy}")
# print(f"Test Accuracy: {accuracy}")
# len(build_test[build_test['Slope']==build_test['pred']])/len(build_test)

return clf
10 changes: 5 additions & 5 deletions city_metrix/layers/smart_cities_lulc.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
from shapely.geometry import box
import psutil
from exactextract import exact_extract
import pickle
import warnings
warnings.filterwarnings('ignore',category=UserWarning)

from .layer import Layer, get_utm_zone_epsg, create_fishnet_grid, MAX_TILE_SIZE
from .open_street_map import OpenStreetMap, OpenStreetMapClass
from .building_classifier import BuildingClassifier
from .building_classifier.building_classifier import BuildingClassifier


class SmartCitiesLULC(Layer):
Expand All @@ -22,10 +23,9 @@ def __init__(self, land_cover_class=None, **kwargs):
def get_data(self, bbox):
crs = get_utm_zone_epsg(bbox)

# Roof slope model
# buildings sample from US
buildings_sample = BuildingClassifier(geo_file = 'V2-building-class-data.geojson')
clf = buildings_sample.building_class_tree()
# load building roof slope classifier
with open('city_metrix/layers/building_classifier/building_classifier.pkl', 'rb') as f:
clf = pickle.load(f)

# ESA world cover
esa_1m = BuildingClassifier().get_data_esa_reclass(bbox, crs)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@


class TreeCanopyHeight(Layer):

name = "tree_canopy_hight"

NO_DATA_VALUE = 0

def __init__(self, **kwargs):
Expand All @@ -20,10 +18,6 @@ def get_data(self, bbox):
# aggregate time series into a single image
canopy_ht = canopy_ht.reduce(ee.Reducer.mean()).rename("cover_code")




data = get_image_collection(ee.ImageCollection(canopy_ht), bbox, 1, "tree canopy hight")

return data.cover_code

0 comments on commit 4329fb6

Please sign in to comment.