# -*- coding: utf-8 -*- #==========================================================# # Extract shorelines from Landsat images #==========================================================# # Initial settings import ee import matplotlib.pyplot as plt import matplotlib.cm as cm import numpy as np import pandas as pd from datetime import datetime import pickle import pdb import pytz # image processing modules import skimage.filters as filters import skimage.exposure as exposure import skimage.transform as transform import sklearn.decomposition as decomposition import skimage.morphology as morphology import skimage.measure as measure # machine learning modules from sklearn.cluster import KMeans # my modules import functions.utils as utils import functions.sds as sds # some settings np.seterr(all='ignore') # raise/ignore divisions by 0 and nans plt.rcParams['axes.grid'] = False plt.rcParams['figure.max_open_warning'] = 100 ee.Initialize() # parameters cloud_thresh = 0.5 # threshold for cloud cover plot_bool = True # if you want the plots prob_high = 99.9 # upper probability to clip and rescale pixel intensity min_contour_points = 100# minimum number of points contained in each water line output_epsg = 28356 # GDA94 / MGA Zone 56 buffer_size = 10 # radius (in pixels) of disk for buffer (pixel classification) min_beach_size = 50 # number of pixels in a beach (pixel classification) # select collection satname = 'L8' input_col = ee.ImageCollection('LANDSAT/LC08/C01/T1_RT_TOA') # Landsat 8 Tier 1 TOA # location (Narrabeen-Collaroy beach) polygon = [[[151.3473129272461,-33.69035274454718], [151.2820816040039,-33.68206818063878], [151.27281188964844,-33.74775138989556], [151.3425064086914,-33.75231878701767], [151.3473129272461,-33.69035274454718]]]; # dates start_date = '2013-01-01' end_date = '2018-12-31' # filter by location and date flt_col = input_col.filterBounds(ee.Geometry.Polygon(polygon)).filterDate(start_date, end_date) n_img = flt_col.size().getInfo() print('Number of images covering the polygon:', n_img) im_all = flt_col.getInfo().get('features') i = 0 # first image # find image in ee database im = ee.Image(im_all[i].get('id')) # load image as np.array im_pan, im_ms, im_cloud, crs, meta = sds.read_eeimage(im, polygon, satname, plot_bool) # rescale intensities im_ms = sds.rescale_image_intensity(im_ms, im_cloud, prob_high, plot_bool) im_pan = sds.rescale_image_intensity(im_pan, im_cloud, prob_high, plot_bool) # pansharpen rgb image im_ms_ps = sds.pansharpen(im_ms[:,:,[0,1,2]], im_pan, im_cloud, plot_bool) # add down-sized bands for NIR and SWIR (since pansharpening is not possible) im_ms_ps = np.append(im_ms_ps, im_ms[:,:,[3,4]], axis=2) # calculate NDWI im_ndwi = sds.nd_index(im_ms_ps[:,:,3], im_ms_ps[:,:,1], im_cloud, plot_bool) # edge detection wl_pix = sds.find_wl_contours(im_ndwi, im_cloud, min_contour_points, plot_bool) # convert from pixels to world coordinates wl_coords = sds.convert_pix2world(wl_pix, crs['crs_15m']) # convert to output epsg spatial reference wl = sds.convert_epsg(wl_coords, crs['epsg_code'], output_epsg) # classify sand pixels im_sand = sds.classify_sand_unsupervised(im_ms_ps, im_pan, im_cloud, wl_pix, buffer_size, min_beach_size, plot_bool) #%% plt.figure() plt.imshow(im_ms_ps[:,:,[2,1,0]]) for i,contour in enumerate(wl_pix): plt.plot(contour[:, 1], contour[:, 0], linewidth=2) plt.axis('image') plt.title('Detected water lines') plt.show() vec = im_ms_ps.reshape(im_ms_ps.shape[0] * im_ms_ps.shape[1], im_ms_ps.shape[2]) vec_pan = im_pan.reshape(im_pan.shape[0]*im_pan.shape[1]) features = np.zeros((len(vec), 5)) features[:,[0,1,2,3]] = vec[:,[0,1,2,3]] features[:,4] = vec_pan vec_mask = im_cloud.reshape(im_ms_ps.shape[0] * im_ms_ps.shape[1]) # create buffer im_buffer = np.zeros((im_ms_ps.shape[0], im_ms_ps.shape[1])) for i, contour in enumerate(wl_pix): indices = [(int(_[0]), int(_[1])) for _ in list(np.round(contour))] for j, idx in enumerate(indices): im_buffer[idx] = 1 plt.figure() plt.imshow(im_buffer) plt.draw() se = morphology.disk(buffer_size) im_buffer = morphology.binary_dilation(im_buffer, se) plt.figure() plt.imshow(im_buffer) plt.draw() vec_buffer = (im_buffer == 1).reshape(im_ms_ps.shape[0] * im_ms_ps.shape[1]) vec_buffer= np.logical_and(vec_buffer, ~vec_mask) #vec_buffer = np.ravel_multi_index(z,(im_ms_ps.shape[0], im_ms_ps.shape[1])) kmeans = KMeans(n_clusters=6, random_state=0).fit(vec[vec_buffer,:]) labels = kmeans.labels_ labels_full = np.ones((len(vec_mask))) * np.nan labels_full[vec_buffer] = labels im_labels = labels_full.reshape(im_ms_ps.shape[0], im_ms_ps.shape[1]) plt.figure() plt.imshow(im_labels) plt.axis('equal') plt.draw() utils.compare_images(im_labels, im_pan) plt.figure() for i in range(6): plt.plot(kmeans.cluster_centers_[i,:]) plt.draw() im_sand = im_labels == np.argmax(np.mean(kmeans.cluster_centers_[:,[0,1,2,4]], axis=1)) im_sand2 = morphology.remove_small_objects(im_sand, min_size=min_beach_size, connectivity=2) im_sand3 = morphology.binary_dilation(im_sand2, morphology.disk(1)) plt.figure() plt.imshow(im_sand3) plt.draw() im_ms_ps[im_sand3,0] = 0 im_ms_ps[im_sand3,1] = 0 im_ms_ps[im_sand3,2] = 1 plt.figure() plt.imshow(im_ms_ps[:,:,[2,1,0]]) plt.axis('image') plt.title('Sand classification') plt.show() #%%