From d6a42b3a3b32365933e326f451d959577697c28d Mon Sep 17 00:00:00 2001 From: Benedikt Mersch Date: Thu, 3 Aug 2023 14:31:22 +0200 Subject: [PATCH 1/8] Add CI --- .github/workflows/python.yml | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 .github/workflows/python.yml diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml new file mode 100644 index 0000000..2d3d578 --- /dev/null +++ b/.github/workflows/python.yml @@ -0,0 +1,27 @@ +name: Python API +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + python_package: + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-22.04, ubuntu-20.04] + + steps: + - uses: actions/checkout@v3 + - name: Set up Python3 + uses: actions/setup-python@v3 + - name: Install dependencies + run: | + python -m pip install --upgrade pip + - name: Build pip package + run: | + python -m pip install --verbose . + - name: Test installation + run: | + mapmos_pipeline --help From 0527f9d96f3abe7f43497e76145522fcc2f5806e Mon Sep 17 00:00:00 2001 From: Benedikt Mersch Date: Thu, 3 Aug 2023 14:44:20 +0200 Subject: [PATCH 2/8] Downgrade to Python3.10 --- .github/workflows/python.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 2d3d578..e2e4156 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -16,6 +16,8 @@ jobs: - uses: actions/checkout@v3 - name: Set up Python3 uses: actions/setup-python@v3 + with: + python-version: '3.10' - name: Install dependencies run: | python -m pip install --upgrade pip From 21c9f59e582edcb6a37d142dbf53af29f988ebab Mon Sep 17 00:00:00 2001 From: Benedikt Mersch Date: Thu, 3 Aug 2023 14:51:34 +0200 Subject: [PATCH 3/8] Use setup-python action v4 and get python version from pyproject.toml --- .github/workflows/python.yml | 6 +++--- pyproject.toml | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index e2e4156..1eedb2e 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -14,10 +14,10 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Set up Python3 - uses: actions/setup-python@v3 + - name: Setup Python3 + uses: actions/setup-python@v4 with: - python-version: '3.10' + python-version-file: pyproject.toml - name: Install dependencies run: | python -m pip install --upgrade pip diff --git a/pyproject.toml b/pyproject.toml index 43e6a06..76a50b1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,6 @@ [project] name = "mapmos" +requires-python = "<3.11" # TODO: Remove when open3d is available for Python 3.11 version = "0.0.1" description = "Building Volumetric Beliefs for Dynamic Environments Exploiting Map-Based Moving Object Segmentation" readme = "README.md" From 942f404a949d74eb642f61dc3a2419ef3aeceb3c Mon Sep 17 00:00:00 2001 From: Benedikt Mersch Date: Thu, 3 Aug 2023 15:57:28 +0200 Subject: [PATCH 4/8] Make o3d dependency optional --- pyproject.toml | 3 +- scripts/cache_to_ply.py | 8 ++++- src/mapmos/pipeline.py | 29 ++++++++--------- src/mapmos/utils/save.py | 68 ++++++++++++++++++++++++++-------------- 4 files changed, 65 insertions(+), 43 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 76a50b1..a20dcad 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,5 @@ [project] name = "mapmos" -requires-python = "<3.11" # TODO: Remove when open3d is available for Python 3.11 version = "0.0.1" description = "Building Volumetric Beliefs for Dynamic Environments Exploiting Map-Based Moving Object Segmentation" readme = "README.md" @@ -11,7 +10,6 @@ license_files = "LICENSE" dependencies = [ "kiss-icp>=0.2.10", "diskcache>=5.3.0", - "open3d>=0.13", "pytorch_lightning>=1.6.4", ] @@ -21,6 +19,7 @@ all = [ "ouster-sdk>=0.7.1", "pyntcloud", "trimesh", + "open3d>=0.13", ] [project.scripts] diff --git a/scripts/cache_to_ply.py b/scripts/cache_to_ply.py index 7ff281c..1137c68 100755 --- a/scripts/cache_to_ply.py +++ b/scripts/cache_to_ply.py @@ -23,13 +23,13 @@ import os import typer +import importlib import numpy as np import torch from typing import List, Optional from torch.utils.data import DataLoader from tqdm import tqdm -import open3d as o3d from pathlib import Path from mapmos.datasets.mapmos_dataset import MapMOSDataset, collate_fn @@ -68,6 +68,12 @@ def cache_to_ply( help="[Optional] Path to the configuration file", ), ): + try: + o3d = importlib.import_module("open3d") + except ModuleNotFoundError as err: + print(f'open3d is not installed on your system, run "pip install open3d"') + exit(1) + for seq in sequence: # Run cfg = load_config(config) diff --git a/src/mapmos/pipeline.py b/src/mapmos/pipeline.py index 5d723ff..a5e5a2b 100644 --- a/src/mapmos/pipeline.py +++ b/src/mapmos/pipeline.py @@ -37,7 +37,7 @@ from mapmos.metrics import get_confusion_matrix from mapmos.utils.visualizer import MapMOSVisualizer, StubVisualizer from mapmos.utils.pipeline_results import MOSPipelineResults -from mapmos.utils.save import save_to_ply, save_to_kitti +from mapmos.utils.save import PlyWriter, KITTIWriter, StubWriter from mapmos.config import load_config @@ -99,8 +99,8 @@ def __init__( self.visualize = visualize self.visualizer = MapMOSVisualizer() if visualize else StubVisualizer() - self.save_ply = save_ply - self.save_kitti = save_kitti + self.ply_writer = PlyWriter() if save_ply else StubWriter() + self.kitti_writer = KITTIWriter() if save_kitti else StubWriter() # Public interface ------ def run(self): @@ -203,19 +203,16 @@ def process_final_prediction(self, query_index, query_points, query_labels): torch.tensor(belief_labels_query, dtype=torch.int32), torch.tensor(query_labels, dtype=torch.int32), ) - if self.save_ply: - save_to_ply( - query_points, - belief_labels_query, - query_labels, - filename=f"{self.results_dir}/ply/{query_index:06}.ply", - ) - - if self.save_kitti: - save_to_kitti( - belief_labels_query, - filename=f"{self.results_dir}/bin/sequences/{self.dataset_sequence}/predictions/{query_index:06}.label", - ) + self.ply_writer.write( + query_points, + belief_labels_query, + query_labels, + filename=f"{self.results_dir}/ply/{query_index:06}.ply", + ) + self.kitti_writer.write( + belief_labels_query, + filename=f"{self.results_dir}/bin/sequences/{self.dataset_sequence}/predictions/{query_index:06}.label", + ) def _next(self, idx): dataframe = self._dataset[idx] diff --git a/src/mapmos/utils/save.py b/src/mapmos/utils/save.py index 623c7d9..de18775 100644 --- a/src/mapmos/utils/save.py +++ b/src/mapmos/utils/save.py @@ -20,38 +20,58 @@ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -import open3d as o3d import numpy as np import os +import importlib from pathlib import Path -def save_to_ply( - scan_points: np.ndarray, pred_labels: np.ndarray, gt_labels: np.ndarray, filename: str -): - os.makedirs(Path(filename).parent, exist_ok=True) - pcd_current_scan = o3d.geometry.PointCloud( - o3d.utility.Vector3dVector(scan_points) - ).paint_uniform_color([0, 0, 0]) +class StubWriter: + def __init__(self) -> None: + pass - scan_colors = np.array(pcd_current_scan.colors) + def write(self, *_, **__): + pass - tp = (pred_labels == 1) & (gt_labels == 1) - fp = (pred_labels == 1) & (gt_labels != 1) - fn = (pred_labels != 1) & (gt_labels == 1) - scan_colors[tp] = [0, 1, 0] - scan_colors[fp] = [1, 0, 0] - scan_colors[fn] = [0, 0, 1] +class PlyWriter: + def __init__(self) -> None: + try: + self.o3d = importlib.import_module("open3d") + except ModuleNotFoundError as err: + print(f'open3d is not installed on your system, run "pip install open3d"') + exit(1) - pcd_current_scan.colors = o3d.utility.Vector3dVector(scan_colors) - o3d.io.write_point_cloud(filename, pcd_current_scan) + def write( + self, scan_points: np.ndarray, pred_labels: np.ndarray, gt_labels: np.ndarray, filename: str + ): + os.makedirs(Path(filename).parent, exist_ok=True) + pcd_current_scan = self.o3d.geometry.PointCloud( + self.o3d.utility.Vector3dVector(scan_points) + ).paint_uniform_color([0, 0, 0]) + scan_colors = np.array(pcd_current_scan.colors) -def save_to_kitti(pred_labels: np.ndarray, filename: str): - os.makedirs(Path(filename).parent, exist_ok=True) - kitti_labels = np.copy(pred_labels) - kitti_labels[pred_labels == 0] = 9 - kitti_labels[pred_labels == 1] = 251 - kitti_labels = kitti_labels.reshape(-1).astype(np.int32) - kitti_labels.tofile(filename) + tp = (pred_labels == 1) & (gt_labels == 1) + fp = (pred_labels == 1) & (gt_labels != 1) + fn = (pred_labels != 1) & (gt_labels == 1) + + scan_colors[tp] = [0, 1, 0] + scan_colors[fp] = [1, 0, 0] + scan_colors[fn] = [0, 0, 1] + + pcd_current_scan.colors = self.o3d.utility.Vector3dVector(scan_colors) + self.o3d.io.write_point_cloud(filename, pcd_current_scan) + + +class KITTIWriter: + def __init__(self) -> None: + pass + + def write(self, pred_labels: np.ndarray, filename: str): + os.makedirs(Path(filename).parent, exist_ok=True) + kitti_labels = np.copy(pred_labels) + kitti_labels[pred_labels == 0] = 9 + kitti_labels[pred_labels == 1] = 251 + kitti_labels = kitti_labels.reshape(-1).astype(np.int32) + kitti_labels.tofile(filename) From d9f8dc4646d2254c5c332f522d050b9c17723e1e Mon Sep 17 00:00:00 2001 From: Benedikt Mersch Date: Thu, 3 Aug 2023 15:57:41 +0200 Subject: [PATCH 5/8] No need --- .github/workflows/python.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index 1eedb2e..d12289d 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -16,8 +16,6 @@ jobs: - uses: actions/checkout@v3 - name: Setup Python3 uses: actions/setup-python@v4 - with: - python-version-file: pyproject.toml - name: Install dependencies run: | python -m pip install --upgrade pip From c77fb58840983202ca06ed999f2fa11b0d936d73 Mon Sep 17 00:00:00 2001 From: Benedikt Mersch Date: Thu, 3 Aug 2023 16:02:21 +0200 Subject: [PATCH 6/8] Extend Makefile --- Makefile | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e7b6123..3cd58d8 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,17 @@ install: @pip install -v . +install-all: + @pip install -v ".[all]" + uninstall: @pip -v uninstall mapmos -editable: +build-system: @pip install scikit-build-core pyproject_metadata pathspec pybind11 ninja cmake + +editable: build-system @pip install --no-build-isolation -ve . + +editable-all: build-system + @pip install --no-build-isolation -ve ".[all]" From c7ce93727b61040c8cf46a39130cbad08e516d32 Mon Sep 17 00:00:00 2001 From: Benedikt Mersch Date: Thu, 3 Aug 2023 16:11:22 +0200 Subject: [PATCH 7/8] Update Readme --- Makefile | 3 --- README.md | 7 +++++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Makefile b/Makefile index 3cd58d8..94f9315 100644 --- a/Makefile +++ b/Makefile @@ -12,6 +12,3 @@ build-system: editable: build-system @pip install --no-build-isolation -ve . - -editable-all: build-system - @pip install --no-build-isolation -ve ".[all]" diff --git a/README.md b/README.md index d27052f..cf5a58e 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,6 @@ First, make sure the [MinkowskiEngine](https://github.com/NVIDIA/MinkowskiEngine) is installed on your system, see [here](https://github.com/NVIDIA/MinkowskiEngine#installation) for more details. Next, clone our repository - ```bash git clone git@github.com:PRBonn/MapMOS && cd MapMOS ``` @@ -40,7 +39,11 @@ and install with make install ``` -**or** in editable mode: +**or** +```bash +make install-all +``` +if you want to install the project with all optional dependencies (needed for the visualizer). In case you want to edit the Python code, install in editable mode: ```bash make editable ``` From 0fcd06b0254a6656af7b5433606d76ca1e94c092 Mon Sep 17 00:00:00 2001 From: Benedikt Mersch Date: Thu, 3 Aug 2023 16:14:26 +0200 Subject: [PATCH 8/8] Back to v3 --- .github/workflows/python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/python.yml b/.github/workflows/python.yml index d12289d..5ba924d 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/python.yml @@ -15,7 +15,7 @@ jobs: steps: - uses: actions/checkout@v3 - name: Setup Python3 - uses: actions/setup-python@v4 + uses: actions/setup-python@v3 - name: Install dependencies run: | python -m pip install --upgrade pip