address = "Royal Palace of Brussels"
#address = input("Enter an address in Belgium:")
import os
import pandas as pd
from glob import glob
from natsort import natsorted, ns
import geopy
import folium
from geopy.geocoders import Nominatim
from geopy.extra.rate_limiter import RateLimiter
import rasterio
from rasterio.plot import show
from pyproj import Transformer
from rasterio.windows import Window
import rioxarray
import imageio
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
%matplotlib inline
flandre_path = '/Users/adamtky/Desktop/BeCode/3. Project/Project 3 - 3D Houses'
wallonie_path = '/Volumes/Seagate Expansion Drive/Project 3 - 3D Houses_Wallonie'
def tif_file(path):
tif_file =[]
# using glob library to get all the file with .tif
files = glob(path,recursive = True)
for file in files:
tif_file.append(file)
# sort files with number in the file (ascending order) using natsorted library
tif_file = natsorted(tif_file, alg=ns.IGNORECASE)
return tif_file
path = './DSM/**/*.tif'
DSM_tif = tif_file(path)
DSM_tif[:3]
path = './DTM/**/*.tif'
DTM_tif = tif_file(path)
DTM_tif[:3]
os.chdir(wallonie_path)
path_wal = './DSM/*.tif'
DSM_tif_wal = tif_file(path_wal)
DSM_tif_wal
path_wal = './DTM/*.tif'
DTM_tif_wal = tif_file(path_wal)
DTM_tif_wal
# to get the longtitude and latitude of the address entered & plot address on a map
def lat_long(address):
# to get the longtitude and latitude
locator = Nominatim(user_agent="myGeocoder")
location = locator.geocode(address)
house_lat_long = [location.latitude, location.longitude]
return house_lat_long
def house_map(func):
# to plot address
house_map = folium.Map(location=func,zoom_start=150)
folium.Marker(location=func,popup=lat_long(address)).add_to(house_map)
#house_map.save(address+".html")
return house_map
house_map(lat_long(address))
# longtitude and latitude of the address entered
lat,lon = lat_long(address)
lat,lon
def transform(lon, lat):
# transform to Belgium 'EPSG:31370' coordinate
transformer = Transformer.from_crs("EPSG:4326", crs_to = 'EPSG:31370' ,always_xy=True)
xx, yy = transformer.transform(lon, lat)
print(f'longtitude:{xx} latitude:{yy}' )
return xx,yy
# coordinate EPSG:31370
xx,yy = transform(lon, lat)
address_path = '/Users/adamtky/Desktop/BeCode/3. Project/Project 3 - 3D Houses/Data/Belgium_Address.csv'
def get_coordinate(path,address):
index = []
df = pd.read_csv(path)
for i in range(df.shape[0]):
if df['Address'][i] == address :
index.append(i)
break
continue
xx, yy = df['EPSG:31370_x'][index][index[0]] ,df['EPSG:31370_y'][index][index[0]]
lat, lon = df['EPSG:4326_lat'][index][index[0]] ,df['EPSG:4326_lon'][index][index[0]]
return (xx, yy) , (lat, lon)
#(xx, yy) , (lat, lon) = get_coordinate(address_path,address)
os.chdir(flandre_path)
# create all bounding box from tifs
def bounds(tifs):
bounds = []
for i in tifs:
src = rasterio.open(i)
bounds.append(src.bounds)
return bounds
src_bounds_flb = bounds(DSM_tif)
src_bounds_flb[:3]
os.chdir(wallonie_path)
src_bounds_wal = bounds(DSM_tif_wal)
src_bounds_wal
# check which tif contains the location in DSM
def check_DSM_flb(xx,yy):
scr_path = []
for i,bound in enumerate(src_bounds_flb,1):
if (xx >= bound[0] and xx <= bound[2]) & \
(yy >= bound[1] and yy <= bound[3]):
scr_path.append('./DSM/DHMVIIDSMRAS1m_k'+ str(i) +'/GeoTIFF/DHMVIIDSMRAS1m_k'+ str(i) + '.tif')
print('The house is in this tif :', 'DHMVIIDSMRAS1m_k' + str(i) + '.tif')
else:
None
return scr_path
dsm_path_flb = check_DSM_flb(xx,yy)
dsm_path_flb
# check which tif contains the location in DSM
def check_DSM_wal(xx,yy):
scr_path = []
for i,bound in enumerate(src_bounds_wal,1):
if (xx >= bound[0] and xx <= bound[2]) & \
(yy >= bound[1] and yy <= bound[3]):
scr_path.append('/Volumes/Seagate Expansion Drive/Project 3 - 3D Houses_Wallonie/DSM/dsm_'+ str(i) + '.tif')
print('The house is in this tif :', '/Volumes/Seagate Expansion Drive/Project 3 - 3D Houses_Wallonie/DSM/dsm_' + str(i) + '.tif')
return scr_path
dsm_path_wal = check_DSM_wal(xx,yy)
dsm_path_wal
# check which tif contains the location in DTM
def check_DTM_flb(xx,yy):
scr_path = []
for i,bound in enumerate(src_bounds_flb,1):
if (xx >= bound[0] and xx <= bound[2]) & \
(yy >= bound[1] and yy <= bound[3]):
scr_path.append('./DTM/DHMVIIDTMRAS1m_k'+ str(i) +'/GeoTIFF/DHMVIIDTMRAS1m_k'+ str(i) + '.tif')
print('The house is in this tif :', 'DHMVIIDTMRAS1m_k' + str(i) + '.tif')
else:
None
return scr_path
dtm_path_flb = check_DTM_flb(xx,yy)
dtm_path_flb
# check which tif contains the location in DTM
def check_DTM_wal(xx,yy):
scr_path = []
for i,bound in enumerate(src_bounds_wal,1):
if (xx >= bound[0] and xx <= bound[2]) & \
(yy >= bound[1] and yy <= bound[3]):
scr_path.append('/Volumes/Seagate Expansion Drive/Project 3 - 3D Houses_Wallonie/DTM/dtm_'+ str(i) + '.tif')
print('The house is in this tif :', '/Volumes/Seagate Expansion Drive/Project 3 - 3D Houses_Wallonie/DTM/dtm_' + str(i) + '.tif')
return scr_path
dtm_path_wal = check_DTM_wal(xx,yy)
dsm_path = []
if not dsm_path_flb:
dsm_path.append(dsm_path_wal[0])
os.chdir(wallonie_path)
else:
dsm_path.append(dsm_path_flb[0])
os.chdir(flandre_path)
dtm_path = []
if not dtm_path_flb:
dtm_path.append(dtm_path_wal[0])
os.chdir(wallonie_path)
else:
dtm_path.append(dtm_path_flb[0])
os.chdir(flandre_path)
dsm_path
dtm_path
def clip_dsm(path,window_size:int):
xds = rioxarray.open_rasterio(path,masked=True,chunks=True)
# set window size
n = window_size
# create coordinates and geometries
coor1,coor2 = [(xx-n),(yy+n)],[(xx+n),(yy+n)]
coor3,coor4 = [(xx+n),(yy-n)] ,[(xx-n),(yy-n)]
geometries = [ {'type': 'Polygon', 'coordinates': [[coor1,coor2, coor3,coor4,coor1 ]]}]
# clip the image as per the geometries size
clipped = xds.rio.clip(geometries)
# change directory
os.chdir(flandre_path)
# save clip
clip_dsm = clipped.rio.to_raster(address+"_clipped_dsm.tif",tiled=True, dtype="int32")
return clipped.plot()
def clip_dtm(path,window_size:int):
xds = rioxarray.open_rasterio(path,masked=True,chunks=True)
# set window size
n = window_size
# create coordinates and geometries
coor1,coor2 = [(xx-n),(yy+n)],[(xx+n),(yy+n)]
coor3,coor4 = [(xx+n),(yy-n)] ,[(xx-n),(yy-n)]
geometries = [ {'type': 'Polygon', 'coordinates': [[coor1,coor2, coor3,coor4,coor1 ]]}]
# clip the image as per the geometries size
clipped = xds.rio.clip(geometries)
# change directory
os.chdir(flandre_path)
# save clip
clip_dtm = clipped.rio.to_raster(address +"_clipped_dtm.tif",tiled=True, dtype="int32")
return clipped.plot()
dsm_path[0]
clip_dsm(dsm_path[0],100)
clip_dtm(dtm_path[0],100)
def chm_tif():
# open the digital terrain model
with rasterio.open(address +'_clipped_dtm.tif') as src:
lidar_dtm_im = src.read(1, masked=True)
dtm_meta = src.profile
# open the digital surface model
with rasterio.open(address +'_clipped_dsm.tif') as src:
lidar_dsm_im = src.read(1, masked=True)
dsm_meta = src.profile
# calculate canopy height model
lidar_chm = lidar_dsm_im - lidar_dtm_im
# change directory
os.chdir(flandre_path)
# save chm clipped
with rasterio.open(address +'_clipped_chm.tif', 'w', **dsm_meta) as ff:
ff.write(lidar_chm,1)
chm_tif = address +'_clipped_chm.tif'
return chm_tif
def House_3D(tif,size:int,azim=215):
chm = imageio.imread(tif)
nx,ny = chm.shape
x = np.linspace(0, size*2, nx)
y = np.linspace(0, size*2, ny)
yv,xv = np.meshgrid(x, y)
fig = plt.figure(figsize=(15,15))
ax = fig.add_subplot(111, projection='3d')
chm3d=ax.plot_surface(xv,yv,chm,cmap='plasma',linewidth=0)
ax.set_title('CHM(Canopy Height Model)')
ax.set_xlabel('Distance (m)')
ax.set_ylabel('Distance (m)')
ax.set_zlabel('Elevation (m)')
ax.view_init(azim=azim)
fig.colorbar(chm3d, shrink=0.3, aspect=10);
fig.savefig(address +'_3D.png', dpi=200)
return plt.show()
House_3D(chm_tif(),100,125)
# compare google map image of the house
from IPython.display import Image
#Image(address+".png")
# to view actual house on google map
import webbrowser
url = 'https://www.google.com.my/maps/place/'+str(lat)+','+str(lon)
webbrowser.open(url)
## Plotting the CHM with Mayavi2
from osgeo import gdal
from mayavi import mlab
ds = gdal.Open(chm_tif())
data = ds.ReadAsArray()
data = data.astype(np.float32)
mlab.figure(size=(640, 800), bgcolor=(0.16, 0.28, 0.46))
surf = mlab.surf(data)
#mlab.show()
from IPython.display import Image
Image(address+"_mayavi.png")