Shipwrecks detection using bathymetric data¶
- 🔬 Data Science
- 🥠 Deep Learning and Instance Segmentation
Table of Contents¶
- Necessary imports
- Connect to your GIS
- Get the data for analysis
- Preprocess bathymetric data
- Export training data
- Train the model
- Model inference
In this notebook, we will use bathymetry data provided by NOAA to detect shipwrecks from the Shell Bank Basin area located near New York City in United States. A Bathymetric Attributed Grid (BAG) is a two-band imagery where one of the bands is elevation and the other is uncertainty (define uncertainty of elevation value). We have applied deep learning methods after pre-processing the data (which is explained in Preprocess bathymetric data) for the detection.
One important step in pre-processing is applying shaded relief function provided in ArcGIS which is also used by NOAA in one of their BAG visualizations here. Shaded Relief is a 3D representation of the terrain which differentiate the shipwrecks distinctly from the background and reveals them. This is created by merging the Elevation-coded images and
Hillshade method where a 3-band imagery is returned which is easy to interpret as compared to the raw bathymetry image. Subsequently, the images are exported as "RCNN Masks" to train a
MaskRCNN model provided by ArcGIS API for Python for detecting the shipwrecks.
The notebook presents the use of deep learning methods to automate the identification of submerged shipwrecks which could be useful for hydrographic offices, archaeologists, historians who otherwise would spend a lot of time doing it manually.
import os from pathlib import Path from datetime import datetime as dt from arcgis.gis import GIS from arcgis.raster.functions import RFT from arcgis.learn import prepare_data, MaskRCNN
gis = GIS(url='https://pythonapi.playground.esri.com/portal', username='arcgis_python', password='amazing_arcgis_123')
bathymetry_img = gis.content.search("title: Bathymetrydata owner:api_data_owner", "Imagery Layer") bathymetry_img
training_data_wrecks = gis.content.search('title:training_data_wrecks owner:api_data_owner', "Map Image Layer") training_data_wrecks
We are applying some preprocessing to the bathymetry data so that we can export the data for training a deep learning model. The preprocessing steps include mapping 'No Data' pixels value to '-1' and applying Shaded Relief function to the output raster. The resultant raster after applying Shaded Relief function will be a 3-band imagery that we can use to export data using
Export Training Data for Deep Learning tool in ArcGIS Pro 2.5, for training our deep learning model.
All the preprocessing steps are recorded in the form of a Raster function template which you can use in ArcGIS Pro to generate the processed raster.
shaded_relief_rft = gis.content.search("title: shaded_Relief owner:api_data_owner", "Raster Function Template") shaded_relief_rft
shaded_relief_ob = RFT(shaded_relief_rft)
# ! conda install -c anaconda graphviz -y
We need to add this custom raster function to ArcGIS Pro using Import functions option in the 'Custom' tab of 'Raster Functions'
Once we apply the Raster function template on the bathymetry data, we will get the output image below. We will use this image to export training data for our deep learning model.
shaded_relief = gis.content.search('title:shaded_Relief owner:api_data_owner', "Map Image Layer") shaded_relief
Export training data using 'Export Training data for deep learning' tool, click here for detailed documentation:
- Set 'shaded_relief' as
- Set a location where you want to export the training data in
Output Folderparameter, it can be an existing folder or the tool will create that for you.
- Set the 'training_data_wrecks' as input to the
Input Feature Class Or Classified Rasterparameter.
Class Field Valueas 'ecode'.
Image Formatas 'TIFF format'
Tile Size X&
Tile Size Ycan be set to 256.
Stride Ycan be set to 50.
- Select 'RCNN Masks' as the
Meta Data Formatbecause we are training a 'MaskRCNN Model'.
- In 'Environments' tab set an optimum
Cell Size. For this example, as we have performing the analysis on the bathymetry data with 50 cm resolution, so, we used '0.5' as the cell size.
arcpy.ia.ExportTrainingDataForDeepLearning(in_raster="shaded_Relief_CopyRaster", out_folder=r"\256X256_multiple_cellsize_stride50", in_class_data="training_data_wrecks", image_chip_format="TIFF", tile_size_x=256, tile_size_y=256, stride_x=50, stride_y=50, output_nofeature_tiles="ONLY_TILES_WITH_FEATURES", metadata_format="RCNN_Masks", start_index=0, class_value_field="ecode", buffer_radius=0, in_mask_polygons=None, rotation_angle=0, reference_system="MAP_SPACE", processing_mode="PROCESS_AS_MOSAICKED_IMAGE", blacken_around_feature="NO_BLACKEN", crop_mode="FIXED_SIZE")
As we have already exported our training data, we will now train our model using ArcGIS API for Python. We will be using
arcgis.learn module which contains tools and deep learning capabilities. Documentation is available here to install and setup environment.
We can always apply multiple transformations to our training data when training a model that can help generalize the model better. Though, we do some standard data augmentations, we can enhance them further based on the data at hand, to increase data size, and avoid occurring.
Let us have look, how we can do it using Fastai's image transformation library.
from fastai.vision.transform import crop, rotate, brightness, contrast, rand_zoom
train_tfms = [rotate(degrees=30, # defining a transform using rotate with degrees fixed to p=0.5), # a value, but by passing an argument p. crop(size=224, # crop of the image to return image of size 224. The position p=1., # is given by (col_pct, row_pct), with col_pct and row_pct row_pct=(0, 1), # being normalized between 0 and 1. col_pct=(0, 1)), brightness(change=(0.4, 0.6)), # Applying change in brightness of image. contrast(scale=(1.0, 1.5)), # Applying scale to contrast of image. rand_zoom(scale=(1.,1.2))] # Randomized version of zoom. val_tfms = [crop(size=224, # cropping the image to same size for validation datasets p=1.0, # as in training datasets. row_pct=0.5, col_pct=0.5)] transforms = (train_tfms, val_tfms) # tuple containing transformations for data augmentation # of training and validation datasets respectively.
We would specify the path to our training data and a few hyper parameters.
path: path of folder containing training data.
batch_size: No of images your model will train on each step inside an epoch, it directly depends on the memory of your graphic card.
transforms: tuple containing Fast.ai transforms for data augmentation of training and validation datasets respectively.
This function will return a fast.ai databunch, we will use this in the next step to train a model.
gis = GIS('home')
training_data = gis.content.get('91178e9303af49b0b9ae09c0d32ec164') training_data
filepath = training_data.download(file_name=training_data.name)
import zipfile with zipfile.ZipFile(filepath, 'r') as zip_ref: zip_ref.extractall(Path(filepath).parent)
data_path = Path(os.path.join(os.path.splitext(filepath)))
data = prepare_data(path=data_path, batch_size=8, transforms=transforms)
To make sense of training data we will use the
show_batch() method in
arcgis.learn. This method randomly picks few samples from the training data and visualizes them.
rows: number of rows we want to see the results for.