Skip to content

Commit

Permalink
Merge pull request #379 from microsoft/PyTorchWildlife_Dev_0.0.1.1.2
Browse files Browse the repository at this point in the history
PyTorchWildlife 0.0.1.1.2
  • Loading branch information
zhmiao authored Nov 22, 2023
2 parents 92e1d5f + 35a11b2 commit 746f2e5
Show file tree
Hide file tree
Showing 849 changed files with 3,714 additions and 14,047 deletions.
72 changes: 11 additions & 61 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,61 +1,11 @@
################################################################################
# This .gitignore file was automatically created by Microsoft(R) Visual Studio.
################################################################################

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Jupyter Notebook
.ipynb_checkpoints

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Apple directory
*.DS_Store

# IDEs
*.idea/
*.project
.spyderproject
.spyproject
.vscode

# Demo files
demo/aadconfig.py
demo/apiconfig.py
demo/CameraTrapAssets
demo/static/uploads
demo/static/results
.webassets-cache/

# CameraTrapJsonFileProcessingApp
api/batch_processing/postprocessing/CameraTrapJsonFileProcessingApp/.vs/
api/batch_processing/postprocessing/CameraTrapJsonFileProcessingApp/bin/
api/batch_processing/postprocessing/CameraTrapJsonFileProcessingApp/obj/
api/batch_processing/postprocessing/CameraTrapJsonFileProcessingApp/packages/

# TF and PyTorch model files
*.pb
*.pt

# batch processing API config files
api_config*.py

# Other
*.pth
*.o
debug.log
*.swp

# Things created when building the sync API
yolov5
api/synchronous/api_core/animal_detection_api/detection

__pycache__
*weights*
*processed.*
*output*
*flagged*
*temp*
PytorchWildlife.egg-info/
*dev*
*test*
*setup/*
*dist/*
13 changes: 13 additions & 0 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: "2"

build:
os: "ubuntu-22.04"
tools:
python: "3.8"

python:
install:
- requirements: docs/requirements.txt

sphinx:
configuration: docs/conf.py
65 changes: 65 additions & 0 deletions INSTALLATION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# PyTorch Wildlife: A Collaborative Deep Learning Framework for Conservation

## Welcome to Version 0.0.1.1.2

The Pytorch-wildlife library allows users to directly load the MegadetectorV5 model weights for animal detection. We've fully refactored our codebase, prioritizing ease of use in model deployment and expansion. In addition to `MegadetectorV5`, `Pytorch-wildlife` also accommodates a range of classification weights, such as those derived from the Amazon Rainforest dataset and the Opossum classification dataset. Explore the codebase and functionalities of `Pytorch-wildlife` through our interactive `Gradio` web app and detailed Jupyter notebooks, designed to showcase the practical applications of our enhancements. You can find more information in our [documentation](https://cameratraps.readthedocs.io/en/latest/).

## Table of Contents
1. [Prerequisites](#prerequisites)
2. [Installation](#installation)
3. [Running the Demo](#running-the-demo)
4. [License](#license)

## Prerequisites

1. Python 3.8
2. NVIDIA GPU (for CUDA support, although the demo can run on CPU)

If you have conda/mamba installed, you can create a new environment with the following command:
```bash
conda create -n pytorch-wildlife python=3.8 -y
conda activate pytorch-wildlife
```

## Installation
### 1. Install through pip:
```bash
pip install PytorchWildlife
```
## Running the Demo
Here is a brief example on how to perform detection and classification on a single image using `PyTorch-wildlife`:
```python
import torch
from PytorchWildlife.models import detection as pw_detection
from PytorchWildlife.models import classification as pw_classification
img = torch.randn((3, 1280, 1280))
# Detection
detection_model = pw_detection.MegaDetectorV5()
detection_result = detection_model.single_image_detection(img)
#Classification
classification_model = pw_classification.AI4GAmazonRainforest()
classification_results = classification_model.single_image_classification(img)
```

#### Version 0.0.1.1.2 does not currently have video detection support, you can use the Gradio app for single image and batch image detection \& classification.
If you want to use our Gradio demo for a user-friendly interface. Please run the following code inside the current repo. You can also find Jupyter Notebooks with an image and video tutorial:
```bash
git clone -b PytorchWildlife_Dev --single-branch https://github.com/microsoft/CameraTraps.git
cd CameraTraps
cd demo
# For the image demo
python image_demo.py
# For the video demo
python video_demo.py
# For the gradio app
python demo_gradio.py
```
The `demo_gradio.py` will launch a Gradio interface where you can:
- Perform Single Image Detection: Upload an image and set a confidence threshold to get detections.
- Perform Batch Image Detection: Upload a zip file containing multiple images to get detections in a JSON format.
- Perform Video Detection: Upload a video and get a processed video with detected animals (Not supported in version 0.0.1.1.2).

## License
This project is licensed under the MIT License. Refer to the LICENSE file for more details.
## Copyright
Copyright (c) Microsoft Corporation. All rights reserved.
34 changes: 17 additions & 17 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
MIT License
MIT License

Copyright (c) Microsoft Corporation. All rights reserved.
Copyright (c) [2023] [Microsoft]

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
3 changes: 3 additions & 0 deletions PytorchWildlife/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .data import *
from .models import *
from .utils import *
2 changes: 2 additions & 0 deletions PytorchWildlife/data/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
from .datasets import *
from .transforms import *
120 changes: 120 additions & 0 deletions PytorchWildlife/data/datasets.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

import os
from PIL import Image
import numpy as np
import supervision as sv
from torch.utils.data import Dataset

# Making the DetectionImageFolder class available for import from this module
__all__ = [
"DetectionImageFolder",
]


class DetectionImageFolder(Dataset):
"""
A PyTorch Dataset for loading images from a specified directory.
Each item in the dataset is a tuple containing the image data,
the image's path, and the original size of the image.
"""

def __init__(self, image_dir, transform=None):
"""
Initializes the dataset.
Parameters:
image_dir (str): Path to the directory containing the images.
transform (callable, optional): Optional transform to be applied on the image.
"""
self.image_dir = image_dir
# Listing and sorting all image files in the specified directory
self.images = sorted(os.listdir(self.image_dir))
self.transform = transform

def __getitem__(self, idx):
"""
Retrieves an image from the dataset.
Parameters:
idx (int): Index of the image to retrieve.
Returns:
tuple: Contains the image data, the image's path, and its original size.
"""
# Get image filename and path
img = self.images[idx]
img_path = os.path.join(self.image_dir, img)

# Load and convert image to RGB
img = Image.open(img_path).convert("RGB")
img = np.asarray(img)
img_size_ori = img.shape

# Apply transformation if specified
if self.transform:
img = self.transform(img)

return img, img_path, np.array(img_size_ori)

def __len__(self):
"""
Returns the total number of images in the dataset.
Returns:
int: Total number of images.
"""
return len(self.images)


class DetectionCrops(Dataset):

def __init__(self, detection_results, transform=None, path_head=None, animal_cls_id=0):

self.detection_results = detection_results
self.transform = transform
self.path_head = path_head
self.animal_cls_id = animal_cls_id # This determins which detection class id represents animals.
self.img_ids = []
self.xyxys = []

self.load_detection_results()

def load_detection_results(self):
for det in self.detection_results:
for xyxy, det_id in zip(det["detections"].xyxy, det["detections"].class_id):
# Only run recognition on animal detections
if det_id == self.animal_cls_id:
self.img_ids.append(det["img_id"])
self.xyxys.append(xyxy)

def __getitem__(self, idx):
"""
Retrieves an image from the dataset.
Parameters:
idx (int): Index of the image to retrieve.
Returns:
tuple: Contains the image data and the image's path.
"""

# Get image path and corresponding bbox xyxy for cropping
img_id = self.img_ids[idx]
xyxy = self.xyxys[idx]

img_path = os.path.join(self.path_head, img_id) if self.path_head else img_id

# Load and crop image with supervision
img = sv.crop_image(np.array(Image.open(img_path).convert("RGB")),
xyxy=xyxy)

# Apply transformation if specified
if self.transform:
img = self.transform(Image.fromarray(img))

return img, img_path

def __len__(self):
return len(self.img_ids)
Loading

0 comments on commit 746f2e5

Please sign in to comment.