A native Julia package for satellite images?

I realize this topic has been dormant for several months, but I thought the community may be interested in my new package RemoteSensingToolbox. It’s been under development for several months, but since it’s starting to get some traction, I figured that now was a good time to formally introduce it.

RemoteSensingToolbox is a pure Julia Package built ontop of Rasters.jl with the goal of providing common tools for visualizing, processing, and analyzing remotely sensed imagery. I’m currently aiming to support the following features:

Feature Description Implemented
Visualization Visualize images with various band combinations :white_check_mark:
Land Cover Indices Calculate indices such as MNDWI and NDVI :white_check_mark:
QA and SCL Decoding Decode Quality Assurance and Scene Classification masks :white_check_mark:
Pixel Masking Mask pixels to remove objects such as clouds or shadows :white_check_mark:
PCA Perform PCA analysis, transformation, and reconstruction :white_check_mark:
MNF Minimum Noise Fraction transformation and reconstruction :white_check_mark:
Signature Analysis Analyze spectral signatures for different land cover types :white_check_mark:
Land Cover Classification Expose an MLJ interface for classifying land cover types :x:
Endmember Extraction Extract spectral endmembers from an image :x:
Spectral Unmixing Perform spectral unmixing under a given endmember library :x:

I’m currently working on a fairly major refactor to make the project more maintainable and to improve interop with existing Julia packages. For example, I’ve recently broken out a lot of the sensor-specific functionality to a separate package called SatelliteDataSources, which aims to provide a similar interface to RasterDataSources, but for satellite imagery. The idea is that you can request specific layers from a locally stored satellite product by name or color. You can also retrieve bands by color from a loaded Raster or RasterStack. The interface looks something like this:

# Load The Red, Green, and Blue Sentinel 2 Bands At 10m Resolution
RasterStack(Sentinel2{10}, "data/L2A_T11UPT_A017828_20200804T184659/", [:red, :green, :blue])

# Load The SCL Layer At 60m Resolution
Raster(Sentinel2{60}, "data/L2A_T11UPT_A017828_20200804T184659/", :SCL)

# Load All Sentinel 2 Bands With 10m Resolution, Then Compute NDWI
sen = RasterStack(Sentinel2{10}, "data/L2A_T11UPT_A017828_20200804T184659/")
g = green(Sentinel2{10}, sen) .* 0.0001f0  # Get green band and convert DNs to reflectance
n = nir(Sentinel2{10}, sen) .* 0.0001f0  # Get NIR band and convert DNs to reflectance
ndwi = (g .- n) ./ (g .+ n)

This low-level functionality is what allows RemoteSensingToolbox to support generic code like the following:

# Visualize a landsat scene using a true color band combination
visualize(landsat, TrueColor{Landsat8}; upper=0.90)

# Visualize a landsat scene using the agriculture band combination
visualize(landsat, Agriculture{Landsat8}; upper=0.90)

# Convert Digital Numbers (DNs) to reflectance
landsat_sr = dn_to_reflectance(Landsat8, landsat)

# Calculate the MNDWI from a Landsat 8 scene
index = mndwi(landsat, Landsat8)

This is very much a work in progress and new features are being added on a regular basis. I’m also refactoring the package to make sensor types like Landsat8 or Sentinel2{10} the first argument to all methods for the sake of consistency. After that, I’ll probably look into adding support for GeoStats.jl for land cover classification. Feel free to open new GitHub issues to discuss features you want to see or to influence the discussion on our development going forward.

7 Likes