diff --git a/ai2_docs/landsat_vessels/model_summary.md b/ai2_docs/landsat_vessels/model_summary.md
index c81a37ce..9092b4f1 100644
--- a/ai2_docs/landsat_vessels/model_summary.md
+++ b/ai2_docs/landsat_vessels/model_summary.md
@@ -30,8 +30,8 @@ Note: The evaluation metrics are reported for the two-stage model (detector + cl
---
## Model Configurations
-- **Detector**: `rslearn_projects/data/landsat_vessels/config.yaml`
-- **Classifier**: `rslearn_projects/landsat/recheck_landsat_labels/phase123_config.yaml`
+- **Detector**: `rslearn_projects/data/landsat_vessels/config_detector.yaml`
+- **Classifier**: `rslearn_projects/data/landsat_vessels/config_classifier.yaml`
- **Filters**: marine infrastructure `rslearn_projects/rslp/utils/filter.py`
---
diff --git a/ai2_docs/landsat_vessels/train_eval.md b/ai2_docs/landsat_vessels/train_eval.md
index 0c3b8da6..31291c8a 100644
--- a/ai2_docs/landsat_vessels/train_eval.md
+++ b/ai2_docs/landsat_vessels/train_eval.md
@@ -12,17 +12,17 @@ This detects vessels in Landsat imagery using two models:
The object detector can be trained like this:
- python -m rslp.rslearn_main model fit --config data/landsat_vessels/config.yaml
+ python -m rslp.rslearn_main model fit --config data/landsat_vessels/config_detector.yaml
The dataset was originally labeled in siv and has been converted to rslearn dataset
using the code in `landsat/existing_dataset_to_utm/`.
The classifier can be trained like this:
- python -m rslp.rslearn_main model fit --config landsat/recheck_landsat_labels/phase123_config.yaml
+ python -m rslp.rslearn_main model fit --config data/landsat_vessels/config_classifier.yaml
The data collection process for the classifier is described in
-`landsat/recheck_landsat_labels/README.md`.
+`one_off_projects/landsat/recheck_landsat_labels/README.md`.
---
diff --git a/data/landsat_vessels/config_classifier.yaml b/data/landsat_vessels/config_classifier.yaml
new file mode 100644
index 00000000..1288b444
--- /dev/null
+++ b/data/landsat_vessels/config_classifier.yaml
@@ -0,0 +1,105 @@
+model:
+ class_path: rslearn.train.lightning_module.RslearnLightningModule
+ init_args:
+ model:
+ class_path: rslearn.models.multitask.MultiTaskModel
+ init_args:
+ encoder:
+ - class_path: rslearn.models.swin.Swin
+ init_args:
+ input_channels: 7
+ output_layers: [1, 3, 5, 7]
+ pretrained: true
+ decoders:
+ class:
+ - class_path: rslearn.models.pooling_decoder.PoolingDecoder
+ init_args:
+ in_channels: 1024
+ out_channels: 2
+ - class_path: rslearn.train.tasks.classification.ClassificationHead
+ lr: 0.0001
+ plateau_factor: 0.1
+ plateau_patience: 10
+ plateau_min_lr: 0
+ plateau_cooldown: 0
+ restore_config:
+ restore_path: gcs://rslearn-eai/datasets/landsat_vessel_detection/artifacts/2024-03-13-landsat-vessels/vessel02_satlas_freeze_crop512_nosatlas_b8first2/best.pth
+ remap_prefixes:
+ - ["backbone.backbone.", "encoder.0.model."]
+data:
+ class_path: rslearn.train.data_module.RslearnDataModule
+ init_args:
+ path: gcs://rslearn-eai/datasets/landsat_vessel_detection/classifier/dataset_20240905/
+ inputs:
+ image:
+ data_type: "raster"
+ layers: ["landsat"]
+ bands: ["B8", "B2", "B3", "B4", "B5", "B6", "B7"]
+ passthrough: true
+ label:
+ data_type: "vector"
+ layers: ["label"]
+ is_target: true
+ task:
+ class_path: rslearn.train.tasks.multi_task.MultiTask
+ init_args:
+ tasks:
+ class:
+ class_path: rslearn.train.tasks.classification.ClassificationTask
+ init_args:
+ property_name: "label"
+ classes: ["correct", "incorrect"]
+ allow_invalid: true
+ skip_unknown_categories: true
+ prob_property: "prob"
+ positive_class: "correct"
+ positive_class_threshold: 0.85
+ input_mapping:
+ class:
+ label: "targets"
+ batch_size: 16
+ num_workers: 16
+ default_config:
+ transforms:
+ - class_path: rslearn.train.transforms.normalize.Normalize
+ init_args:
+ mean: 0
+ std: 255
+ - class_path: rslearn.train.transforms.pad.Pad
+ init_args:
+ mode: "center"
+ size: 32
+ - class_path: rslearn.train.transforms.flip.Flip
+ groups: ["selected_copy", "phase2a_completed", "phase3a_selected"]
+ train_config:
+ tags:
+ split: train
+ sampler:
+ class_path: rslearn.train.dataset.WeightedRandomSamplerFactory
+ init_args:
+ option_key: "weight"
+ num_samples: 1000
+ val_config:
+ groups: ["phase2a_completed"]
+ tags:
+ split: val
+ test_config:
+ groups: ["phase2a_completed"]
+ tags:
+ split: val
+ predict_config:
+ groups: ["classify_predict"]
+ skip_targets: true
+trainer:
+ max_epochs: 64
+ callbacks:
+ - class_path: lightning.pytorch.callbacks.LearningRateMonitor
+ init_args:
+ logging_interval: "epoch"
+ - class_path: rslearn.train.prediction_writer.RslearnWriter
+ init_args:
+ path: gcs://rslearn-eai/datasets/landsat_vessel_detection/classifier/dataset_20240905/
+ output_layer: output
+ selector: ["class"]
+rslp_project: rslearn-landsat-recheck
+rslp_experiment: phase123_20240919_01_copy
diff --git a/data/landsat_vessels/config.yaml b/data/landsat_vessels/config_detector.yaml
similarity index 100%
rename from data/landsat_vessels/config.yaml
rename to data/landsat_vessels/config_detector.yaml
diff --git a/docs/images/landsat_vessels/prediction.png b/docs/images/landsat_vessels/prediction.png
new file mode 100644
index 00000000..6a66d831
Binary files /dev/null and b/docs/images/landsat_vessels/prediction.png differ
diff --git a/docs/landsat_vessels.md b/docs/landsat_vessels.md
new file mode 100644
index 00000000..ca800087
--- /dev/null
+++ b/docs/landsat_vessels.md
@@ -0,0 +1,91 @@
+Landsat Vessel Detection
+---------------------------
+
+The Landsat vessel detection model detects ships in Landsat 8/9 scenes. We use Level-1 data since they are released with a lower latency, and latency is
+important for [Skylight](https://www.skylight.global/) (which is the primary use of
+this model within Ai2).
+
+The model includes of a detector and a classifier: the detector detects ship-like objects, and the classifier refines these detections by pruning ones that it is confident are not ships. The detector is trained on a dataset consisting of 7,954 Landsat patches (ranging from 384x384 to 768x768) with 18,509 ship labels. The classifier is trained on a dataset consisting of 1,733 annotated detections, with each detection represented as a 64x64 patch centered at the position of a detected ship. See our paper for more details about the model and dataset.
+
+
+
+
+
+
+Inference
+---------
+
+First, download the detector and classifier checkpoints to the `RSLP_PREFIX` directory.
+
+ cd rslearn_projects
+ mkdir -p project_data/projects/landsat_vessels/data_20240924_model_20240924_imagenet_patch512_flip_03/checkpoints/
+ wget https://storage.googleapis.com/ai2-rslearn-projects-data/landsat_vessels/detector/best.ckpt -O project_data/projects/landsat_vessels/data_20240924_model_20240924_imagenet_patch512_flip_03/checkpoints/last.ckpt
+
+ mkdir -p project_data/projects/rslearn-landsat-recheck/phase123_20240919_01_copy/checkpoints/
+ wget https://storage.googleapis.com/ai2-rslearn-projects-data/landsat_vessels/classifer/best.ckpt -O project_data/projects/rslearn-landsat-recheck/phase123_20240919_01_copy/checkpoints/last.ckpt
+
+The easiest way to apply the model is using the prediction pipeline in `rslp/landsat_vessels/predict_pipeline.py`. You can download the Landsat scene files, e.g. from USGS EarthExplorer or AWS, and then create a configuration file for the prediction pipeline, here is an example:
+
+```json
+{
+ "image_files": {
+ "B2": "/home/data/LC08_L1TP_125059_20240727_20240801_02_T1_B2.TIF",
+ "B3": "/home/data/LC08_L1TP_125059_20240727_20240801_02_T1_B3.TIF",
+ "B4": "/home/data/LC08_L1TP_125059_20240727_20240801_02_T1_B4.TIF",
+ "B5": "/home/data/LC08_L1TP_125059_20240727_20240801_02_T1_B5.TIF",
+ "B6": "/home/data/LC08_L1TP_125059_20240727_20240801_02_T1_B6.TIF",
+ "B7": "/home/data/LC08_L1TP_125059_20240727_20240801_02_T1_B7.TIF",
+ "B8": "/home/data/LC08_L1TP_125059_20240727_20240801_02_T1_B8.TIF",
+ },
+ "scratch_path": "/home/data/scratch/",
+ "json_path": "/home/data/vessels.json",
+ "crop_path": "/home/data/crops/"
+}
+```
+
+This specifies the arguments to
+`rslp.landsat_vessels.predict_pipeline.predict_pipeline` via `jsonargparse`.
+
+Now we can run the pipeline:
+
+ python -m rslp.main landsat_vessels predict --config /path/to/config.json
+
+Here, `scratch_path` saves the rslearn dataset, `crop_path` saves the cropped RGB images centered around the detected ships, and `json_path` saves the JSON output of the detected ships, all of which are optional, depending on whether the user wants to save the intermediate results or not.
+
+The prediction pipeline also accepts a Landsat scene ID and automatically downloads the scene images from [AWS](https://aws.amazon.com/marketplace/pp/prodview-ivr4jeq6flk7u#resources). You will need to set up your AWS account for accessing Landsat data. Use the command below to run the pipeline with scene ID:
+
+ python -m rslp.main landsat_vessels predict --scene_id LC08_L1TP_125059_20240727_20240801_02_T1
+
+
+Training
+--------
+
+First, download the training dataset for detector:
+
+ cd rslearn_projects
+ mkdir -p project_data/datasets/landsat_vessels/
+ wget https://storage.googleapis.com/ai2-rslearn-projects-data/landsat_vessels/landsat_vessels_detector.tar -0 project_data/datasets/landsat_vessels_detector.tar
+ tar xvf project_data/datasets/landsat_vessels_detector.tar --directory project_data/datasets/landsat_vessels/
+
+It is an rslearn dataset consisting of window folders like `windows/labels_utm/41984_2354176_f7c057a567ee40b694d0a77ea59ef81a_6359/`. Inside each window folder:
+
+- `layers/landsat/` contains different Landsat bands used by the model.
+- `layers/label/data.geojson` contains the positions of ships. These are offset from
+ the bounds of the window which are in `metadata.json`, so subtract the window's
+ bounds to get pixel coordinates relative to the image.
+
+Use the command below to train the detector. Note that Weights & Biases is needed. You can
+disable W&B with `--no_log true` but then it may be difficult to track the metrics.
+
+ python -m rslp.rslearn_main model fit --config data/landsat_vessels/config_detector.yaml --data.init_args.path project_data/datasets/landsat_vessels/dataset_20240924/
+
+Second, download the training dataset for classifier:
+
+ wget https://storage.googleapis.com/ai2-rslearn-projects-data/landsat_vessels/landsat_vessels_classifier.tar -0 project_data/datasets/landsat_vessels_classifier.tar
+ tar xvf project_data/dataset/landsat_vessels_classifier.tar --directory project_data/datasets/landsat_vessels/
+
+Use the command below to train the classifier.
+
+ python -m rslp.rslearn_main model fit --config data/landsat_vessels/config_classifier.yaml --data.init_args.path project_data/datasets/landsat_vessels/dataset_20240905/
diff --git a/landsat/confirm_same_performance_as_integration/README.md b/one_off_projects/landsat/confirm_same_performance_as_integration/README.md
similarity index 100%
rename from landsat/confirm_same_performance_as_integration/README.md
rename to one_off_projects/landsat/confirm_same_performance_as_integration/README.md
diff --git a/landsat/confirm_same_performance_as_integration/rslearn_to_multisat.py b/one_off_projects/landsat/confirm_same_performance_as_integration/rslearn_to_multisat.py
similarity index 100%
rename from landsat/confirm_same_performance_as_integration/rslearn_to_multisat.py
rename to one_off_projects/landsat/confirm_same_performance_as_integration/rslearn_to_multisat.py
diff --git a/landsat/existing_dataset_to_utm/add_label_layer.py b/one_off_projects/landsat/existing_dataset_to_utm/add_label_layer.py
similarity index 100%
rename from landsat/existing_dataset_to_utm/add_label_layer.py
rename to one_off_projects/landsat/existing_dataset_to_utm/add_label_layer.py
diff --git a/landsat/existing_dataset_to_utm/config.json b/one_off_projects/landsat/existing_dataset_to_utm/config.json
similarity index 100%
rename from landsat/existing_dataset_to_utm/config.json
rename to one_off_projects/landsat/existing_dataset_to_utm/config.json
diff --git a/landsat/existing_dataset_to_utm/prepare_windows.py b/one_off_projects/landsat/existing_dataset_to_utm/prepare_windows.py
similarity index 100%
rename from landsat/existing_dataset_to_utm/prepare_windows.py
rename to one_off_projects/landsat/existing_dataset_to_utm/prepare_windows.py
diff --git a/landsat/existing_dataset_to_utm/reformat_multisat.py b/one_off_projects/landsat/existing_dataset_to_utm/reformat_multisat.py
similarity index 100%
rename from landsat/existing_dataset_to_utm/reformat_multisat.py
rename to one_off_projects/landsat/existing_dataset_to_utm/reformat_multisat.py
diff --git a/landsat/quick_vis_script.py b/one_off_projects/landsat/quick_vis_script.py
similarity index 100%
rename from landsat/quick_vis_script.py
rename to one_off_projects/landsat/quick_vis_script.py
diff --git a/landsat/random_landsat/convert_to_multisat_dataset.py b/one_off_projects/landsat/random_landsat/convert_to_multisat_dataset.py
similarity index 100%
rename from landsat/random_landsat/convert_to_multisat_dataset.py
rename to one_off_projects/landsat/random_landsat/convert_to_multisat_dataset.py
diff --git a/landsat/random_landsat/convert_windows_to_utm.py b/one_off_projects/landsat/random_landsat/convert_windows_to_utm.py
similarity index 100%
rename from landsat/random_landsat/convert_windows_to_utm.py
rename to one_off_projects/landsat/random_landsat/convert_windows_to_utm.py
diff --git a/landsat/random_landsat/random_landsat_windows.py b/one_off_projects/landsat/random_landsat/random_landsat_windows.py
similarity index 100%
rename from landsat/random_landsat/random_landsat_windows.py
rename to one_off_projects/landsat/random_landsat/random_landsat_windows.py
diff --git a/landsat/recheck_landsat_labels/README.md b/one_off_projects/landsat/recheck_landsat_labels/README.md
similarity index 100%
rename from landsat/recheck_landsat_labels/README.md
rename to one_off_projects/landsat/recheck_landsat_labels/README.md
diff --git a/landsat/recheck_landsat_labels/phase123_config.yaml b/one_off_projects/landsat/recheck_landsat_labels/phase123_config.yaml
similarity index 100%
rename from landsat/recheck_landsat_labels/phase123_config.yaml
rename to one_off_projects/landsat/recheck_landsat_labels/phase123_config.yaml
diff --git a/landsat/recheck_landsat_labels/phase123_config_hparams.yaml b/one_off_projects/landsat/recheck_landsat_labels/phase123_config_hparams.yaml
similarity index 100%
rename from landsat/recheck_landsat_labels/phase123_config_hparams.yaml
rename to one_off_projects/landsat/recheck_landsat_labels/phase123_config_hparams.yaml
diff --git a/landsat/recheck_landsat_labels/phase12_config.yaml b/one_off_projects/landsat/recheck_landsat_labels/phase12_config.yaml
similarity index 100%
rename from landsat/recheck_landsat_labels/phase12_config.yaml
rename to one_off_projects/landsat/recheck_landsat_labels/phase12_config.yaml
diff --git a/landsat/recheck_landsat_labels/phase1_assign_split.py b/one_off_projects/landsat/recheck_landsat_labels/phase1_assign_split.py
similarity index 100%
rename from landsat/recheck_landsat_labels/phase1_assign_split.py
rename to one_off_projects/landsat/recheck_landsat_labels/phase1_assign_split.py
diff --git a/landsat/recheck_landsat_labels/phase1_config.json b/one_off_projects/landsat/recheck_landsat_labels/phase1_config.json
similarity index 100%
rename from landsat/recheck_landsat_labels/phase1_config.json
rename to one_off_projects/landsat/recheck_landsat_labels/phase1_config.json
diff --git a/landsat/recheck_landsat_labels/phase1_config.yaml b/one_off_projects/landsat/recheck_landsat_labels/phase1_config.yaml
similarity index 100%
rename from landsat/recheck_landsat_labels/phase1_config.yaml
rename to one_off_projects/landsat/recheck_landsat_labels/phase1_config.yaml
diff --git a/landsat/recheck_landsat_labels/phase1_get_1000.py b/one_off_projects/landsat/recheck_landsat_labels/phase1_get_1000.py
similarity index 100%
rename from landsat/recheck_landsat_labels/phase1_get_1000.py
rename to one_off_projects/landsat/recheck_landsat_labels/phase1_get_1000.py
diff --git a/landsat/recheck_landsat_labels/phase1_index.html b/one_off_projects/landsat/recheck_landsat_labels/phase1_index.html
similarity index 100%
rename from landsat/recheck_landsat_labels/phase1_index.html
rename to one_off_projects/landsat/recheck_landsat_labels/phase1_index.html
diff --git a/landsat/recheck_landsat_labels/phase1_server.py b/one_off_projects/landsat/recheck_landsat_labels/phase1_server.py
similarity index 100%
rename from landsat/recheck_landsat_labels/phase1_server.py
rename to one_off_projects/landsat/recheck_landsat_labels/phase1_server.py
diff --git a/landsat/recheck_landsat_labels/phase2_config.json b/one_off_projects/landsat/recheck_landsat_labels/phase2_config.json
similarity index 100%
rename from landsat/recheck_landsat_labels/phase2_config.json
rename to one_off_projects/landsat/recheck_landsat_labels/phase2_config.json
diff --git a/landsat/recheck_landsat_labels/phase2_config.yaml b/one_off_projects/landsat/recheck_landsat_labels/phase2_config.yaml
similarity index 100%
rename from landsat/recheck_landsat_labels/phase2_config.yaml
rename to one_off_projects/landsat/recheck_landsat_labels/phase2_config.yaml
diff --git a/landsat/recheck_landsat_labels/phase2_get_3000.py b/one_off_projects/landsat/recheck_landsat_labels/phase2_get_3000.py
similarity index 100%
rename from landsat/recheck_landsat_labels/phase2_get_3000.py
rename to one_off_projects/landsat/recheck_landsat_labels/phase2_get_3000.py
diff --git a/landsat/recheck_landsat_labels/phase2_index.html b/one_off_projects/landsat/recheck_landsat_labels/phase2_index.html
similarity index 100%
rename from landsat/recheck_landsat_labels/phase2_index.html
rename to one_off_projects/landsat/recheck_landsat_labels/phase2_index.html
diff --git a/landsat/recheck_landsat_labels/phase2_make_overview_windows.py b/one_off_projects/landsat/recheck_landsat_labels/phase2_make_overview_windows.py
similarity index 100%
rename from landsat/recheck_landsat_labels/phase2_make_overview_windows.py
rename to one_off_projects/landsat/recheck_landsat_labels/phase2_make_overview_windows.py
diff --git a/landsat/recheck_landsat_labels/phase2_overview_rgb.py b/one_off_projects/landsat/recheck_landsat_labels/phase2_overview_rgb.py
similarity index 100%
rename from landsat/recheck_landsat_labels/phase2_overview_rgb.py
rename to one_off_projects/landsat/recheck_landsat_labels/phase2_overview_rgb.py
diff --git a/landsat/recheck_landsat_labels/phase2_pansharpen.py b/one_off_projects/landsat/recheck_landsat_labels/phase2_pansharpen.py
similarity index 100%
rename from landsat/recheck_landsat_labels/phase2_pansharpen.py
rename to one_off_projects/landsat/recheck_landsat_labels/phase2_pansharpen.py
diff --git a/landsat/recheck_landsat_labels/phase2_server.py b/one_off_projects/landsat/recheck_landsat_labels/phase2_server.py
similarity index 100%
rename from landsat/recheck_landsat_labels/phase2_server.py
rename to one_off_projects/landsat/recheck_landsat_labels/phase2_server.py
diff --git a/landsat/recheck_landsat_labels/phase3_get_750.py b/one_off_projects/landsat/recheck_landsat_labels/phase3_get_750.py
similarity index 100%
rename from landsat/recheck_landsat_labels/phase3_get_750.py
rename to one_off_projects/landsat/recheck_landsat_labels/phase3_get_750.py
diff --git a/landsat/recheck_landsat_labels/phase3a_selected.csv b/one_off_projects/landsat/recheck_landsat_labels/phase3a_selected.csv
similarity index 100%
rename from landsat/recheck_landsat_labels/phase3a_selected.csv
rename to one_off_projects/landsat/recheck_landsat_labels/phase3a_selected.csv
diff --git a/rslp/landsat_vessels/config.py b/rslp/landsat_vessels/config.py
index 96a5b613..510eb82a 100644
--- a/rslp/landsat_vessels/config.py
+++ b/rslp/landsat_vessels/config.py
@@ -6,13 +6,9 @@
LANDSAT_LAYER_NAME = "landsat"
LANDSAT_RESOLUTION = 15
-# Detector config
+# Data config
LOCAL_FILES_DATASET_CONFIG = "data/landsat_vessels/predict_dataset_config.json"
AWS_DATASET_CONFIG = "data/landsat_vessels/predict_dataset_config_aws.json"
-DETECT_MODEL_CONFIG = "data/landsat_vessels/config.yaml"
-DETECT_MODEL_EVAL_CONFIG = (
- "data/landsat_vessels/config_eval.yaml" # config for evaluation
-)
# Extract Landsat bands from local config file
with open(LOCAL_FILES_DATASET_CONFIG) as f:
@@ -21,8 +17,9 @@
band["bands"][0] for band in json_data["layers"][LANDSAT_LAYER_NAME]["band_sets"]
]
-# Classifier config
-CLASSIFY_MODEL_CONFIG = "landsat/recheck_landsat_labels/phase123_config.yaml"
+# Model config
+DETECT_MODEL_CONFIG = "data/landsat_vessels/config_detector.yaml"
+CLASSIFY_MODEL_CONFIG = "data/landsat_vessels/config_classifier.yaml"
CLASSIFY_WINDOW_SIZE = 64
# Filter config