Public part of my satellite image processing pipeline.
Processing satellite images can be problematic due to atmospheric phenomenons like clouds, fog, shadows, etc. I had problems with SentinelHub cloud mask so I decided to make one for myself. The filter was trained on data from the Sentinel-2 L1C dataset.
(The Sentinel-2 mission is a land monitoring constellation of two satellites that provide high resolution (mostly 10x10m) optical imagery. The mission provides a global coverage of the Earth's land surface every 5 days. L1C data are available from June 2015 globally.)
Description of files:
- environment.yaml - Anaconda environment
- Dependecies for both file. Pip install also required.
- loader.ipynb - How to download images from entire regions.
- Requirements, creating region of interest, dowloading from SentineHub.
- roi.geojson - Coordinates of Region of Interest(RoI).
- cldetector.py - Cloud detection.
- pixelwise_v8.h5 - Used to reconstruct neural network structure.
- pixelwise_v8_weights.hdf5 - Model weights.
- cnn_v4.h5 - Used to reconstruct neural network structure.
- cnn_v4_weights.hdf5 - Model weights.
- example.py - Example to show the use of the detector and the it's output.
- test_set.rar - For example.py. Has to be unpacked.
A small training set was used to train the model. I plan to update only the CNN model in the future.
The trained model works fairly well for classic clouds and cirrus. Few false detection expected on white structures. Fog usually partly detected. Bodies of water often mislabeled as shadow.
Less false detection on white buildings and water but more on open field. There is still issues with fog like atmospheric distortions but better than pixel model.
Example.py uses an already processed image so step 2 is skipped.
1, Import cldetector.py
import cldetector as cld
2, Calculate temporal product from two previously taken image (same coordinates). Append temporal product to band data.
# img shape = (x, y, 13 band)
image_time_series = [img0, img1, img2]
std = np.std(image_time_series, axis=0)
temporal_product = np.sum(pixel_std, axis=2) * 2 / 13
3, Initialize an CloudDetector object by passing the input array. The expected input is an image with dimensions: (x, y, 14). The last index consist of 13 spectral band value plus one temporal product. Model type can be 'pixel' or 'cnn'.
glassball = cld.CloudDetector(image, modelType='pixel')
4, Call the prediction function. Output is a (x, y, 3) shape array. Land, cloud and shadow probability are included.
output = glassball.predict()
5, Call the update function in case of new data. Repeat step 4 for prediction.
glassball.updateInput(new_image)