diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..9ed8c7d --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,48 @@ +name: Publish to PyPI + +# Publishes the PytorchWildlife package to PyPI when a GitHub Release is published. +# Uses PyPI Trusted Publishing (OIDC) -- no API token or stored secret is required. +# +# One-time maintainer setup (PyPI project owner, account-side): +# PyPI -> project "PytorchWildlife" -> Manage -> Publishing -> Add a trusted publisher (GitHub Actions): +# Owner: microsoft +# Repository: Pytorch-Wildlife +# Workflow: publish.yml +# Environment: pypi +# After that, publishing a GitHub Release runs this workflow and uploads the build. + +on: + release: + types: [published] + +permissions: + contents: read + +jobs: + build-and-publish: + name: Build and publish PytorchWildlife + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/project/PytorchWildlife/ + permissions: + id-token: write # required for Trusted Publishing (OIDC) + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Build sdist and wheel + run: | + python -m pip install --upgrade build + python -m build + + - name: Check distribution metadata + run: | + python -m pip install --upgrade twine + python -m twine check dist/* + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/pyproject.toml b/pyproject.toml index 197e71f..1deaff6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "PytorchWildlife" -version = "1.3.0" +version = "1.3.1" description = "PyTorch-Wildlife: unified open-source AI framework for camera-trap detection, species classification, and wildlife monitoring." readme = "README.md" license = {text = "MIT"} diff --git a/src/PytorchWildlife/data/datasets.py b/src/PytorchWildlife/data/datasets.py index ce280f0..39870a6 100644 --- a/src/PytorchWildlife/data/datasets.py +++ b/src/PytorchWildlife/data/datasets.py @@ -14,6 +14,7 @@ # Making the DetectionImageFolder class available for import from this module __all__ = [ + "ClassificationImageFolder", "DetectionImageFolder", ] diff --git a/src/PytorchWildlife/models/classification/resnet_base/base_classifier.py b/src/PytorchWildlife/models/classification/resnet_base/base_classifier.py index 965ff43..a7448c1 100644 --- a/src/PytorchWildlife/models/classification/resnet_base/base_classifier.py +++ b/src/PytorchWildlife/models/classification/resnet_base/base_classifier.py @@ -158,10 +158,9 @@ def batch_image_classification(self, data_path=None, det_results=None, id_strip= """ if data_path: - dataset = pw_data.ImageFolder( + dataset = pw_data.ClassificationImageFolder( data_path, transform=self.transform, - path_head='.' ) elif det_results: dataset = pw_data.DetectionCrops( diff --git a/src/PytorchWildlife/models/classification/timm_base/base_classifier.py b/src/PytorchWildlife/models/classification/timm_base/base_classifier.py index 682333b..5a4268e 100644 --- a/src/PytorchWildlife/models/classification/timm_base/base_classifier.py +++ b/src/PytorchWildlife/models/classification/timm_base/base_classifier.py @@ -177,10 +177,9 @@ def batch_image_classification(self, data_path=None, det_results=None, id_strip= """ if data_path: - dataset = pw_data.ImageFolder( + dataset = pw_data.ClassificationImageFolder( data_path, transform=self.transform, - path_head='.' ) elif det_results: dataset = pw_data.DetectionCrops( diff --git a/src/PytorchWildlife/models/detection/rtdetr_apache/megadetectorv6_apache.py b/src/PytorchWildlife/models/detection/rtdetr_apache/megadetectorv6_apache.py index 2e2cf10..a4b9151 100644 --- a/src/PytorchWildlife/models/detection/rtdetr_apache/megadetectorv6_apache.py +++ b/src/PytorchWildlife/models/detection/rtdetr_apache/megadetectorv6_apache.py @@ -20,7 +20,7 @@ class MegaDetectorV6Apache(RTDETRApacheBase): 2: "vehicle" } - def __init__(self, weights=None, device="cpu", pretrained=True, version='MDV6-rtdetr-x-apache'): + def __init__(self, weights=None, device="cpu", pretrained=True, version='MDV6-apa-rtdetr-c'): """ Initializes the MegaDetectorV6 model with the option to load pretrained weights. @@ -28,7 +28,7 @@ def __init__(self, weights=None, device="cpu", pretrained=True, version='MDV6-rt weights (str, optional): Path to the weights file. device (str, optional): Device to load the model on (e.g., "cpu" or "cuda"). Default is "cpu". pretrained (bool, optional): Whether to load the pretrained model. Default is True. - version (str, optional): Version of the model to load. Default is 'MDV6-rtdetr-x-apache'. + version (str, optional): Version of the model to load. Default is 'MDV6-apa-rtdetr-c'. """ self.IMAGE_SIZE = 640 diff --git a/src/PytorchWildlife/models/detection/ultralytics_based/megadetectorv6.py b/src/PytorchWildlife/models/detection/ultralytics_based/megadetectorv6.py index 0d0ee65..be0dfb6 100644 --- a/src/PytorchWildlife/models/detection/ultralytics_based/megadetectorv6.py +++ b/src/PytorchWildlife/models/detection/ultralytics_based/megadetectorv6.py @@ -20,7 +20,7 @@ class MegaDetectorV6(YOLOV8Base): 2: "vehicle" } - def __init__(self, weights=None, device="cpu", pretrained=True, version='yolov9c'): + def __init__(self, weights=None, device="cpu", pretrained=True, version='MDV6-yolov9-c'): """ Initializes the MegaDetectorV5 model with the option to load pretrained weights. @@ -28,7 +28,7 @@ def __init__(self, weights=None, device="cpu", pretrained=True, version='yolov9c weights (str, optional): Path to the weights file. device (str, optional): Device to load the model on (e.g., "cpu" or "cuda"). Default is "cpu". pretrained (bool, optional): Whether to load the pretrained model. Default is True. - version (str, optional): Version of the model to load. Default is 'yolov9c'. + version (str, optional): Version of the model to load. Default is 'MDV6-yolov9-c'. """ self.IMAGE_SIZE = 1280 diff --git a/src/PytorchWildlife/models/detection/ultralytics_based/megadetectorv6_distributed.py b/src/PytorchWildlife/models/detection/ultralytics_based/megadetectorv6_distributed.py index ba1cf02..1fc0f95 100644 --- a/src/PytorchWildlife/models/detection/ultralytics_based/megadetectorv6_distributed.py +++ b/src/PytorchWildlife/models/detection/ultralytics_based/megadetectorv6_distributed.py @@ -20,7 +20,7 @@ class MegaDetectorV6_Distributed(YOLOV8_Distributed): 2: "vehicle" } - def __init__(self, weights=None, device="cpu", pretrained=True, version='yolov9c'): + def __init__(self, weights=None, device="cpu", pretrained=True, version='MDV6-yolov9-c'): """ Initializes the MegaDetectorV5 model with the option to load pretrained weights. @@ -28,7 +28,7 @@ def __init__(self, weights=None, device="cpu", pretrained=True, version='yolov9c weights (str, optional): Path to the weights file. device (str, optional): Device to load the model on (e.g., "cpu" or "cuda"). Default is "cpu". pretrained (bool, optional): Whether to load the pretrained model. Default is True. - version (str, optional): Version of the model to load. Default is 'yolov9c'. + version (str, optional): Version of the model to load. Default is 'MDV6-yolov9-c'. """ self.IMAGE_SIZE = 1280 diff --git a/src/PytorchWildlife/models/detection/yolo_mit/megadetectorv6_mit.py b/src/PytorchWildlife/models/detection/yolo_mit/megadetectorv6_mit.py index 24a400b..456bdcd 100644 --- a/src/PytorchWildlife/models/detection/yolo_mit/megadetectorv6_mit.py +++ b/src/PytorchWildlife/models/detection/yolo_mit/megadetectorv6_mit.py @@ -20,7 +20,7 @@ class MegaDetectorV6MIT(YOLOMITBase): 2: "vehicle" } - def __init__(self, weights=None, device="cpu", pretrained=True, version='MDV6-yolov9-c-mit'): + def __init__(self, weights=None, device="cpu", pretrained=True, version='MDV6-mit-yolov9-c'): """ Initializes the MegaDetectorV6 model with the option to load pretrained weights. @@ -28,7 +28,7 @@ def __init__(self, weights=None, device="cpu", pretrained=True, version='MDV6-yo weights (str, optional): Path to the weights file. device (str, optional): Device to load the model on (e.g., "cpu" or "cuda"). Default is "cpu". pretrained (bool, optional): Whether to load the pretrained model. Default is True. - version (str, optional): Version of the model to load. Default is 'MDV6-yolov9-c-mit'. + version (str, optional): Version of the model to load. Default is 'MDV6-mit-yolov9-c'. """ self.IMAGE_SIZE = 640