added sand classification

master
kvos 7 years ago
parent ca90712623
commit 2abac763b1

@ -26,6 +26,7 @@ import skimage.transform as transform
import sklearn.decomposition as decomposition import sklearn.decomposition as decomposition
import skimage.measure as measure import skimage.measure as measure
import skimage.morphology as morphology import skimage.morphology as morphology
from sklearn.cluster import KMeans
# import own modules # import own modules
@ -605,3 +606,75 @@ def convert_epsg(points, epsg_in, epsg_out):
raise raise
return points_converted return points_converted
def classify_sand_unsupervised(im_ms_ps, im_pan, cloud_mask, wl_pix, buffer_size, min_beach_size, plot_bool):
"""
Classifies sand pixels using an unsupervised algorithm (Kmeans)
KV WRL 2018
Arguments:
-----------
im_ms_ps: np.ndarray
Pansharpened RGB + downsampled NIR and SWIR
im_pan:
Panchromatic band
cloud_mask: np.ndarray
2D cloud mask with True where cloud pixels are
wl_pix: list of np.ndarray
list of arrays containig the pixel coordinates of the water line
buffer_size: int
radius of the disk used to create a buffer around the water line
min_beach_size: int
minimum number of connected pixels belonging to a single beach
plot_bool: boolean
True if plot is wanted
Returns: -----------
im_sand: np.ndarray
2D binary image containing True where sand pixels are located
"""
# reshape the 2D images into vectors
vec_ms_ps = 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])
vec_mask = cloud_mask.reshape(im_ms_ps.shape[0] * im_ms_ps.shape[1])
# add B,G,R,NIR and pan bands to the vector of features
vec_features = np.zeros((vec_ms_ps.shape[0], 5))
vec_features[:,[0,1,2,3]] = vec_ms_ps[:,[0,1,2,3]]
vec_features[:,4] = vec_pan
# create binary image with ones where the detected water lines is
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
# perform a dilation on the binary image
se = morphology.disk(buffer_size)
im_buffer = morphology.binary_dilation(im_buffer, se)
vec_buffer = (im_buffer == 1).reshape(im_ms_ps.shape[0] * im_ms_ps.shape[1])
# add cloud mask to buffer
vec_buffer= np.logical_and(vec_buffer, ~vec_mask)
# perform kmeans (6 clusters)
kmeans = KMeans(n_clusters=6, random_state=0).fit(vec_features[vec_buffer,:])
labels = np.ones((len(vec_mask))) * np.nan
labels[vec_buffer] = kmeans.labels_
im_labels = labels.reshape(im_ms_ps.shape[0], im_ms_ps.shape[1])
# find the class with maximum reflection in the B,G,R,Pan
im_sand = im_labels == np.argmax(np.mean(kmeans.cluster_centers_[:,[0,1,2,4]], axis=1))
im_sand = morphology.remove_small_objects(im_sand, min_size=min_beach_size, connectivity=2)
# im_sand = morphology.binary_dilation(im_sand, morphology.disk(1))
if plot_bool:
im = np.copy(im_ms_ps)
im[im_sand,0] = 0
im[im_sand,1] = 0
im[im_sand,2] = 1
plt.figure()
plt.imshow(im[:,:,[2,1,0]])
plt.axis('image')
plt.title('Sand classification')
plt.show()
return im_sand

@ -40,6 +40,8 @@ plot_bool = True # if you want the plots
prob_high = 99.9 # upper probability to clip and rescale pixel intensity 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 min_contour_points = 100# minimum number of points contained in each water line
output_epsg = 28356 # GDA94 / MGA Zone 56 output_epsg = 28356 # GDA94 / MGA Zone 56
buffer_size = 10 # radius of disk for buffer (sand classif parameter)
min_beach_size = 50 # number of pixels in a beach (sand classif parameter)
# select collection # select collection
satname = 'L8' satname = 'L8'
@ -99,3 +101,6 @@ wl_coords = sds.convert_pix2world(wl_pix, crs['crs_15m'])
# convert to output epsg spatial reference # convert to output epsg spatial reference
wl = sds.convert_epsg(wl_coords, crs['epsg_code'], output_epsg) 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)

Loading…
Cancel
Save