Skip to content

Commit

Permalink
Fix Release Build/setup.py for SAM2 dependency (#1779)
Browse files Browse the repository at this point in the history
* SAM-2 as extra dependency for PyPi

Signed-off-by: Sachidanand Alle <[email protected]>

* Disable release test once

Signed-off-by: Sachidanand Alle <[email protected]>

* Fix release build

Signed-off-by: Sachidanand Alle <[email protected]>

* Fix release build

Signed-off-by: Sachidanand Alle <[email protected]>

* Fix github sam2 packaging for PyPI release

Signed-off-by: Sachidanand Alle <[email protected]>

* Fix build error

Signed-off-by: Sachidanand Alle <[email protected]>

* Fix build error

Signed-off-by: Sachidanand Alle <[email protected]>

---------

Signed-off-by: Sachidanand Alle <[email protected]>
  • Loading branch information
SachidanandAlle authored Nov 8, 2024
1 parent ea9e302 commit 241f0c4
Show file tree
Hide file tree
Showing 12 changed files with 70 additions and 29 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ __pycache__
.vscode
.webpack
node_modules/
*.log

# Environments
.env
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ jobs:
run: |
rm dist/monai*.tar.gz
- name: Publish distribution to Test PyPI
- name: Publish distribution to Test
if: ${{ github.event.inputs.test_py == 'true' }}
uses: pypa/gh-action-pypi-publish@master
with:
Expand Down
7 changes: 6 additions & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,12 @@ RUN BUILD_OHIF=false python setup.py bdist_wheel --build-number $(date +'%Y%m%d%
FROM ${FINAL_IMAGE}
LABEL maintainer="[email protected]"
WORKDIR /opt/monailabel
COPY requirements.txt /opt/monailabel/requirements.txt

RUN apt update -y && apt install -y git curl openslide-tools python3 python-is-python3 python3-pip
RUN python -m pip install --no-cache-dir pytest torch torchvision torchaudio

COPY --from=build /opt/monailabel/dist/monailabel* /opt/monailabel/dist/
RUN python -m pip install --no-cache-dir /opt/monailabel/dist/monailabel*.whl
RUN python -m pip install -v --no-cache-dir /opt/monailabel/dist/monailabel*.whl
RUN python -m pip uninstall sam2 -y
RUN python -m pip install -v --no-cache-dir -r /opt/monailabel/requirements.txt
19 changes: 13 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,12 +167,6 @@ In addition, you can find a table of the basic supported fields, modalities, vie
<tr>
</table>

> [**SAM2**](https://github.com/facebookresearch/sam2/)
>
> By default, SAM2 is included for all the above Apps only when **_python >= 3.10_**
> - **sam_2d**: for any organ or tissue and others over a given slice/2D image.
> - **sam_3d**: to support SAM2 propagation over multiple slices (Radiology/MONAI-Bundle).
# Getting Started with MONAI Label
### MONAI Label requires a few steps to get started:
- Step 1: [Install MONAI Label](#step-1-installation)
Expand Down Expand Up @@ -219,6 +213,19 @@ To install the _**latest features**_ using one of the following options:
<pre>docker run --gpus all --rm -ti --ipc=host --net=host projectmonai/monailabel:latest bash</pre>
</details>

### SAM-2

> By default, [**SAM2**](https://github.com/facebookresearch/sam2/) model is included for all the Apps when **_python >= 3.10_**
> - **sam_2d**: for any organ or tissue and others over a given slice/2D image.
> - **sam_3d**: to support SAM2 propagation over multiple slices (Radiology/MONAI-Bundle).
If you are using `pip install monailabel` by default it uses [SAM-2](https://huggingface.co/facebook/sam2-hiera-large) models.
<br/>
To use [SAM-2.1](https://huggingface.co/facebook/sam2.1-hiera-large) use one of following options.
- Use monailabel [Docker](https://hub.docker.com/r/projectmonai/monailabel) instead of pip package
- Run monailabel in dev mode (git checkout)
- If you have installed monailabel via pip then uninstall **_sam2_** package `pip uninstall sam2` and then run `pip install -r requirements.txt` or install latest **SAM-2** from it's [github](https://github.com/facebookresearch/sam2/tree/main?tab=readme-ov-file#installation).

## Step 2 MONAI Label Sample Applications

<h3>Radiology</h3>
Expand Down
19 changes: 18 additions & 1 deletion monailabel/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,18 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import os
from importlib.util import find_spec
from typing import Any, Dict, List, Optional

from pydantic import AnyHttpUrl
from pydantic_settings import BaseSettings, SettingsConfigDict


def is_package_installed(name):
return False if find_spec(name) is None else True


class Settings(BaseSettings):
MONAI_LABEL_API_STR: str = ""
MONAI_LABEL_PROJECT_NAME: str = "MONAILabel"
Expand Down Expand Up @@ -98,6 +102,19 @@ class Settings(BaseSettings):
MONAI_ZOO_REPO: str = "Project-MONAI/model-zoo/hosting_storage_v1"
MONAI_ZOO_AUTH_TOKEN: str = ""

# Refer: https://github.com/facebookresearch/sam2?tab=readme-ov-file#model-description
# Refer: https://huggingface.co/facebook/sam2-hiera-large
MONAI_SAM_MODEL_PT: str = (
"https://huggingface.co/facebook/sam2.1-hiera-large/resolve/main/sam2.1_hiera_large.pt"
if is_package_installed("SAM-2")
else "https://huggingface.co/facebook/sam2-hiera-large/resolve/main/sam2_hiera_large.pt"
)
MONAI_SAM_MODEL_CFG: str = (
"https://huggingface.co/facebook/sam2.1-hiera-large/resolve/main/sam2.1_hiera_l.yaml"
if is_package_installed("SAM-2")
else "https://huggingface.co/facebook/sam2-hiera-large/resolve/main/sam2_hiera_l.yaml"
)

model_config = SettingsConfigDict(
env_file=".env",
case_sensitive=True,
Expand Down
26 changes: 18 additions & 8 deletions monailabel/sam2/infer.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
import pylab
import schedule
import torch
from hydra import initialize_config_dir
from hydra.core.global_hydra import GlobalHydra
from monai.transforms import KeepLargestConnectedComponent, LoadImaged
from PIL import Image
from sam2.build_sam import build_sam2, build_sam2_video_predictor
Expand Down Expand Up @@ -114,13 +116,21 @@ def __init__(
self._config.update(config)

# Download PreTrained Model
# https://github.com/facebookresearch/sam2?tab=readme-ov-file#model-description
pt = "sam2.1_hiera_large.pt"
url = f"https://dl.fbaipublicfiles.com/segment_anything_2/092824/{pt}"
self.path = os.path.join(model_dir, f"pretrained_{pt}")
download_file(url, self.path)
pt_url = settings.MONAI_SAM_MODEL_PT
conf_url = settings.MONAI_SAM_MODEL_CFG
sam_pt = pt_url.split("/")[-1]
sam_conf = conf_url.split("/")[-1]

self.path = os.path.join(model_dir, sam_pt)
self.config_path = os.path.join(model_dir, sam_conf)

GlobalHydra.instance().clear()
initialize_config_dir(config_dir=model_dir)

download_file(pt_url, self.path)
download_file(conf_url, self.config_path)
self.config_path = sam_conf

self.config_path = "configs/sam2.1/sam2.1_hiera_l.yaml"
self.predictors = {}
self.image_cache = {}
self.inference_state = None
Expand Down Expand Up @@ -393,8 +403,8 @@ def main():
force=True,
)
app_name = "pathology"
app_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "..", "sample-apps", app_name))
app_name = "radiology"
app_dir = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..", "sample-apps", app_name))
model_dir = os.path.join(app_dir, "model")
logger.info(f"Model Dir: {model_dir}")
if app_name == "pathology":
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ scikit-learn
scipy
google-auth==2.29.0
SAM-2 @ git+https://github.com/facebookresearch/sam2.git@c2ec8e14a185632b0a5d8b161928ceb50197eddc ; python_version >= '3.10'

#sam2>=0.4.1; python_version >= '3.10'

# scipy and scikit-learn latest packages are missing on python 3.8
# sudo apt-get install openslide-tools -y
Expand Down
6 changes: 3 additions & 3 deletions sample-apps/endoscopy/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,9 @@ def __init__(self, app_dir, studies, conf):
print(f" all, {', '.join(configs.keys())}")
print("---------------------------------------------------------------------------------------")
print("")
exit(-1)
# exit(-1)

models = models.split(",")
models = models.split(",") if models else []
models = [m.strip() for m in models]
invalid = [m for m in models if m != "all" and not configs.get(m)]
if invalid:
Expand All @@ -85,7 +85,7 @@ def __init__(self, app_dir, studies, conf):

logger.info(f"+++ Using Models: {list(self.models.keys())}")

self.sam = strtobool(conf.get("sam", "true"))
self.sam = strtobool(conf.get("sam2", "true"))
super().__init__(
app_dir=app_dir,
studies=studies,
Expand Down
2 changes: 1 addition & 1 deletion sample-apps/monaibundle/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def __init__(self, app_dir, studies, conf):
self.epistemic_simulation_size = int(conf.get("epistemic_simulation_size", "5"))
self.epistemic_dropout = float(conf.get("epistemic_dropout", "0.2"))

self.sam = strtobool(conf.get("sam", "true"))
self.sam = strtobool(conf.get("sam2", "true"))
super().__init__(
app_dir=app_dir,
studies=studies,
Expand Down
8 changes: 4 additions & 4 deletions sample-apps/pathology/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def __init__(self, app_dir, studies, conf):

configs = {k: v for k, v in sorted(configs.items())}

models = conf.get("models", "all")
models = conf.get("models")
if not models:
print("")
print("---------------------------------------------------------------------------------------")
Expand All @@ -63,9 +63,9 @@ def __init__(self, app_dir, studies, conf):
print(f" all, {', '.join(configs.keys())}")
print("---------------------------------------------------------------------------------------")
print("")
exit(-1)
# exit(-1)

models = models.split(",")
models = models.split(",") if models else []
models = [m.strip() for m in models]
invalid = [m for m in models if m != "all" and not configs.get(m)]
if invalid:
Expand All @@ -90,7 +90,7 @@ def __init__(self, app_dir, studies, conf):

logger.info(f"+++ Using Models: {list(self.models.keys())}")

self.sam = strtobool(conf.get("sam", "true"))
self.sam = strtobool(conf.get("sam2", "true"))
super().__init__(
app_dir=app_dir,
studies=studies,
Expand Down
4 changes: 2 additions & 2 deletions sample-apps/radiology/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def __init__(self, app_dir, studies, conf):
print("")
exit(-1)

models = models.split(",")
models = models.split(",") if models else []
models = [m.strip() for m in models]
# Can be configured with --conf scribbles false or true
self.scribbles = conf.get("scribbles", "true") == "true"
Expand Down Expand Up @@ -100,7 +100,7 @@ def __init__(self, app_dir, studies, conf):
# Load models from bundle config files, local or released in Model-Zoo, e.g., --conf bundles <spleen_ct_segmentation>
self.bundles = get_bundle_models(app_dir, conf, conf_key="bundles") if conf.get("bundles") else None

self.sam = strtobool(conf.get("sam", "true"))
self.sam = strtobool(conf.get("sam2", "true"))
super().__init__(
app_dir=app_dir,
studies=studies,
Expand Down
3 changes: 2 additions & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,8 @@ install_requires =
scikit-learn
scipy
google-auth>=2.29.0
SAM-2 @ git+https://github.com/facebookresearch/sam2.git@c2ec8e14a185632b0a5d8b161928ceb50197eddc ; python_version >= '3.10'
sam2>=0.4.1; python_version >= '3.10'
#SAM-2 @ git+https://github.com/facebookresearch/sam2.git@c2ec8e14a185632b0a5d8b161928ceb50197eddc ; python_version >= '3.10'

[flake8]
select = B,C,E,F,N,P,T4,W,B9
Expand Down

0 comments on commit 241f0c4

Please sign in to comment.