Skip to content

Commit

Permalink
Merge branch 'philip/flesh_out_mediapipe_model_info' of https://githu…
Browse files Browse the repository at this point in the history
…b.com/freemocap/skellytracker into philip/flesh_out_mediapipe_model_info
  • Loading branch information
philipqueen committed Aug 28, 2024
2 parents 4c92f85 + be6bdcc commit 871c1d1
Show file tree
Hide file tree
Showing 43 changed files with 1,891 additions and 266 deletions.
27 changes: 27 additions & 0 deletions .github/workflows/linting-ruff.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Linting Ruff

on:
pull_request:
branches: [ main ]
paths:
- 'skellytracker/**'

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Python 3.x
uses: actions/setup-python@v4
with:
# Semantic version range syntax or exact version of a Python version
python-version: '3.9'
# Optional - x64 or x86 architecture, defaults to x64
architecture: 'x64'
cache: 'pip'
- name: Install dependencies
run: |
pip install "-e.[dev]"
- name: Run linting
run: |
ruff check skellytracker
41 changes: 41 additions & 0 deletions .github/workflows/python-testing.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: SkellyTracker Tests

on:
pull_request:
branches: [ main ]
paths:
- 'skellytracker/**'

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: System Info
run: |
uname -a || true
lsb_release -a || true
gcc --version || true
env
- name: Set up Python 3.x
uses: actions/setup-python@v4
with:
# Semantic version range syntax or exact version of a Python version
python-version: '3.9'
# Optional - x64 or x86 architecture, defaults to x64
architecture: 'x64'
cache: 'pip'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install "-e.[all]"
- name: Fix OpenCV conflict
run: |
pip uninstall -y opencv-python opencv-contrib-python
pip install opencv-contrib-python==4.8.1.78
- name: Set PYTHONPATH
run: echo "PYTHONPATH=$PYTHONPATH:$(pwd)/skellytracker" >> $GITHUB_ENV
- name: Run Tests with Pytest
run: |
pip install pytest
pytest skellytracker/tests
31 changes: 31 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,34 @@ Then it can be run with `skellytracker`.
Running the basic `skellytracker` will open the first webcam port on your computer and run pose estimaiton in realtime with mediapipe holistic as a tracker. You can specify the tracker with `skellytracker TRACKER_NAME`, where `TRACKER_NAME` is the name of an available tracker. To view the names of all available trackers, see `RUN_ME.py`.

It will take some time to initialize the tracker the first time you run it, as it will likely need to download the model.

## Using skellytracker in your project

To use skellytracker in your project, import a tracker like `from skellytracker import YOLOPoseTracker`, then instantiate it with your desired parameters like `tracker = YOLOPoseTracker(model_size="medium")`, and then use `tracker.process_image(frame)` or `tracker.process_video(video_filepath)`. Processing image by image will let you access each individual annotated frame with `tracker.annotated_image`, and you can optionally record the data with `tracker.recorder.record()`. Access recorded data with `tracker.recorder.process_tracked_objects()`. The running, recording, and processing are done separately to give control over the amount of processing done at each step in the pipeline. Processing an entire video allows you to save the annotated frames as a video, and optionally saves and returns the data as a numpy array. Each tracker has an associated `ModelInfo` class to access model attributes.

Skellytracker is still under development, so version updates may make breaking changes to the API. Please report any issues and pull requests to the [skellytracker repo](https://github.com/freemocap/skellytracker).

### Extending the API
To extend the API, import the `BaseTracker` and `BaseRecorder` abstract base classes from skellytracker. Then create a new tracker and recorder inheriting from the base classes and implement all of the abstract methods.

## Contributing

We love your input! We want to make contributing to this project as easy and transparent as possible, whether it's:

- Reporting a bug
- Discussing the current state of the code
- Submitting a fix
- Proposing new features
- Becoming a maintainer

Pull requests are the best way to propose changes to the codebase (we
use [Github Flow](https://docs.github.com/en/get-started/quickstart/github-flow)). We actively welcome your pull
requests:

1. Fork the repo and create your branch from `main`.
2. Download the development dependencies with `pip install -e '.[dev]'`.
2. If you've added code that should be tested (including any tracker), add tests.
3. If you've changed APIs, update the documentation.
4. Ensure the test suite passes by running `pytest skellytracker/tests`.
5. Make sure your code lints.
6. Make that pull request!
19 changes: 14 additions & 5 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,24 @@ keywords = [
dependencies = [
"opencv-contrib-python==4.8.*",
"pydantic==2.*",
"mediapipe==0.10.9",
"ultralytics~=8.0.202",
"numpy<2",
"tqdm==4.*",
]
requires-python = ">=3.9,<3.12"
requires-python = ">=3.9,<3.13"

dynamic = ["version", "description"]

[project.optional-dependencies]
dev = ["black", "bumpver", "isort", "pip-tools", "pytest"]
dev = ["black", "bumpver", "isort", "pip-tools", "pytest", "ruff"]
mediapipe = ["mediapipe==0.10.14"]
yolo = ["ultralytics~=8.0.202"]
all = ["ultralytics~=8.0.202", "mediapipe==0.10.14"]

[project.urls]
Homepage = "https://github.com/freemocap/skellytracker"

[tool.bumpver]
current_version = "v2024.03.1013"
current_version = "v2024.06.1016"

version_pattern = "vYYYY.0M.BUILD[-TAG]"
commit_message = "Bump version {old_version} -> {new_version}"
Expand All @@ -82,6 +85,12 @@ push = true
[tool.bumpver.file_patterns]
"skellytracker/__init__.py" = ["{version}"]

[tool.ruff.lint.per-file-ignores]
"*/tests/*" = ["S101"]

[tool.ruff.lint]
extend-select = ["B", "S", "C4", "ISC", "PERF"]

[project.scripts]
skellytracker = "skellytracker.__main__:cli_main"

Expand Down
40 changes: 27 additions & 13 deletions skellytracker/RUN_ME.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,44 @@
import cv2


from skellytracker.trackers.bright_point_tracker.brightest_point_tracker import (
BrightestPointTracker,
)
from skellytracker.trackers.charuco_tracker.charuco_tracker import CharucoTracker
from skellytracker.trackers.mediapipe_tracker.mediapipe_holistic_tracker import (
MediapipeHolisticTracker,
)
from skellytracker.trackers.segment_anything_tracker.segment_anything_tracker import (
SAMTracker,
)
from skellytracker.trackers.yolo_tracker.yolo_tracker import YOLOPoseTracker
from skellytracker.trackers.yolo_object_tracker.yolo_object_tracker import (
YOLOObjectTracker,
)

try:
from skellytracker.trackers.mediapipe_tracker.mediapipe_holistic_tracker import (
MediapipeHolisticTracker,
)
except ModuleNotFoundError:
print("To use mediapipe_holistic_tracker, install skellytracker[mediapipe]")
try:
from skellytracker.trackers.yolo_tracker.yolo_tracker import YOLOPoseTracker
from skellytracker.trackers.yolo_object_tracker.yolo_object_tracker import (
YOLOObjectTracker,
)
from skellytracker.trackers.segment_anything_tracker.segment_anything_tracker import (
SAMTracker,
)
except ModuleNotFoundError:
print("To use yolo_tracker, install skellytracker[yolo]")


def main(demo_tracker: str = "mediapipe_holistic_tracker"):

if demo_tracker == "brightest_point_tracker":
BrightestPointTracker().demo()
BrightestPointTracker(num_points=2).demo()

elif demo_tracker == "charuco_tracker":
charuco_squares_x = 7
charuco_squares_y = 5
number_of_charuco_markers = (charuco_squares_x - 1) * (charuco_squares_y - 1)
charuco_ids = [str(index) for index in range(number_of_charuco_markers)]

CharucoTracker(
squaresX=7,
squaresY=5,
tracked_object_names=charuco_ids,
squares_x=charuco_squares_x,
squares_y=charuco_squares_y,
dictionary=cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_4X4_250),
).demo()

Expand Down
48 changes: 35 additions & 13 deletions skellytracker/SINGLE_IMAGE_RUN.py
Original file line number Diff line number Diff line change
@@ -1,29 +1,51 @@
import cv2
from pathlib import Path

from skellytracker.trackers.bright_point_tracker.brightest_point_tracker import BrightestPointTracker
from skellytracker.trackers.bright_point_tracker.brightest_point_tracker import (
BrightestPointTracker,
)
from skellytracker.trackers.charuco_tracker.charuco_tracker import CharucoTracker
from skellytracker.trackers.mediapipe_tracker.mediapipe_holistic_tracker import MediapipeHolisticTracker
from skellytracker.trackers.yolo_tracker.yolo_tracker import YOLOPoseTracker

try:
from skellytracker.trackers.mediapipe_tracker.mediapipe_holistic_tracker import (
MediapipeHolisticTracker,
)
except ModuleNotFoundError:
print("\n\nTo use mediapipe_holistic_tracker, install skellytracker[mediapipe]\n\n")
try:
from skellytracker.trackers.yolo_tracker.yolo_tracker import YOLOPoseTracker
except ModuleNotFoundError:
print("\n\nTo use yolo_tracker, install skellytracker[yolo]\n\n")


if __name__ == "__main__":
demo_tracker = "brightest_point_tracker"
image_path = Path("/Path/To/Your/Image.jpg")

if demo_tracker == "brightest_point_tracker":
BrightestPointTracker().image_demo(image_path=image_path)
BrightestPointTracker(num_points=2).image_demo(image_path=image_path)

elif demo_tracker == "charuco_tracker":
CharucoTracker(squaresX=7,
squaresY=5,
dictionary=cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_4X4_250)).image_demo(image_path=image_path)
charuco_squares_x = 7
charuco_squares_y = 5
number_of_charuco_markers = (charuco_squares_x - 1) * (charuco_squares_y - 1)
charuco_ids = [str(index) for index in range(number_of_charuco_markers)]

CharucoTracker(
tracked_object_names=charuco_ids,
squares_x=charuco_squares_x,
squares_y=charuco_squares_y,
dictionary=cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_4X4_250),
).image_demo(image_path=image_path)

elif demo_tracker == "mediapipe_holistic_tracker":
MediapipeHolisticTracker(model_complexity=2,
min_detection_confidence=0.5,
min_tracking_confidence=0.5,
static_image_mode=False,
smooth_landmarks=True).image_demo(image_path=image_path)
MediapipeHolisticTracker(
model_complexity=2,
min_detection_confidence=0.5,
min_tracking_confidence=0.5,
static_image_mode=False,
smooth_landmarks=True,
).image_demo(image_path=image_path)

elif demo_tracker == "yolo_tracker":
YOLOPoseTracker(model_size="high_res").image_demo(image_path=image_path)
YOLOPoseTracker(model_size="high_res").image_demo(image_path=image_path)
40 changes: 31 additions & 9 deletions skellytracker/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
"""Top-level package for skellytracker"""

__package_name__ = "skellytracker"
__version__ = "v2024.03.1013"
__version__ = "v2024.06.1016"

__author__ = """Skelly FreeMoCap"""
__email__ = "info@freemocap.org"
__repo_owner_github_user_name__ = "freemocap"
__repo_url__ = f"https://github.com/{__repo_owner_github_user_name__}/{__package_name__}"
__repo_url__ = (
f"https://github.com/{__repo_owner_github_user_name__}/{__package_name__}"
)
__repo_issues_url__ = f"{__repo_url__}/issues"

# ruff: noqa: F401, E402

import sys
from pathlib import Path

Expand All @@ -23,10 +27,28 @@
from skellytracker.system.default_paths import get_log_file_path
from skellytracker.system.logging_configuration import configure_logging

from skellytracker.trackers.mediapipe_tracker.mediapipe_holistic_tracker import MediapipeHolisticTracker
from skellytracker.trackers.yolo_tracker.yolo_tracker import YOLOPoseTracker
from skellytracker.trackers.yolo_mediapipe_combo_tracker.yolo_mediapipe_combo_tracker import YOLOMediapipeComboTracker



configure_logging(log_file_path=get_log_file_path())
try:
from skellytracker.trackers.mediapipe_tracker.mediapipe_holistic_tracker import (
MediapipeHolisticTracker,
)
from skellytracker.trackers.mediapipe_tracker.mediapipe_model_info import (
MediapipeModelInfo,
)
except ModuleNotFoundError:
print("To use mediapipe_holistic_tracker, install skellytracker[mediapipe]")
try:
from skellytracker.trackers.yolo_tracker.yolo_tracker import YOLOPoseTracker
from skellytracker.trackers.yolo_tracker.yolo_model_info import YOLOModelInfo
except ModuleNotFoundError:
print("To use yolo_tracker, install skellytracker[yolo]")
try:
from skellytracker.trackers.yolo_mediapipe_combo_tracker.yolo_mediapipe_combo_tracker import (
YOLOMediapipeComboTracker,
)
except ModuleNotFoundError:
print(
"To use yolo_mediapipe_combo_tracker, install skellytracker[mediapipe, yolo] or skellytracker[all]"
)


configure_logging(log_file_path=str(get_log_file_path()))
11 changes: 6 additions & 5 deletions skellytracker/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,21 @@
print(f"adding base_package_path: {base_package_path} : to sys.path")
sys.path.insert(0, str(base_package_path)) # add parent directory to sys.path

import logging
import logging # noqa: E402

logger = logging.getLogger(__name__)
from skellytracker.RUN_ME import main # noqa: E402

from skellytracker.RUN_ME import main
logger = logging.getLogger(__name__)


def cli_main():
logger.info(f"Running as a script")
logger.info("Running as a script")
if len(sys.argv) > 1:
demo_tracker = str(sys.argv[1])
else:
demo_tracker = "mediapipe_holistic_tracker"
main(demo_tracker=demo_tracker)


if __name__ == "__main__":
cli_main()
cli_main()
Loading

0 comments on commit 871c1d1

Please sign in to comment.