Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 76 additions & 0 deletions .github/workflows/cpu-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Pull Request for Multiple Platform with CPU

on:
pull_request:
branches: [main]
paths-ignore:
- "doc/**"
- "**.md"

jobs:
ci:
name: CI
strategy:
fail-fast: false
matrix:
python-version: ["3.10", "3.12"]
os: ["ubuntu-latest", "macos-13", "macos-latest"] # "ubuntu-24.04-arm" unsupported

runs-on: ${{ matrix.os }}

steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
lfs: true

- name: Install Prerequisites for Linux
if: ${{ matrix.os == 'ubuntu-latest' || matrix.os == 'ubuntu-24.04-arm' }}
run:
sudo apt update && sudo apt install -y libturbojpeg exiftool ffmpeg libheif-dev poppler-utils

- name: Install Prerequisites for MacOS
if: ${{ matrix.os == 'macos-13' || matrix.os == 'macos-latest' }}
run:
brew install libjpeg exiftool ffmpeg libheif poppler

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
check-latest: true

- name: Install Dependencies
run: |
python -m pip install -U pip wheel "numpy>=2" "cython>=3.0.12" "setuptools>=69"
python setup.py build_ext --inplace
python -m pip install .

- name: Lint with Pylint
run: |
python -m pip install pylint
python -m pylint capybara --rcfile=.github/workflows/.pylintrc

- name: Run Tests with Pytest
run: |
mkdir -p tests/coverage
python -m pip install pytest pytest-cov typeguard
python -m pytest tests --ignore tests/onnxruntime/test_engine_io_binding.py --junitxml=tests/coverage/cov-junitxml.xml --cov=capybara

- name: Surface failing tests
uses: pmeier/pytest-results-action@main
with:
path: tests/coverage/cov-junitxml.xml
summary: true
display-options: fEX
fail-on-empty: true
title: Test results

- name: Clean artifacts
run:
rm -rf dist wheelhouse build *.egg-info

- name: Clean workspace when fail
if: failure()
run:
rm -rf ${{ github.workspace }}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
name: Pull Request
name: Pull Request for Ubuntu with GPU

on:
pull_request:
Expand Down Expand Up @@ -53,22 +53,30 @@ jobs:
strategy:
matrix:
python-version:
- "3.10"
- "3.10.16"
container:
image: ${{ needs.build_docker_image.outputs.image }}
options: --user ${{ needs.get_runner_and_uid.outputs.uid }} --gpus all

steps:
- name: Checkout Repository
uses: actions/checkout@v4
with:
lfs: true

- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
check-latest: true

- name: Install Dependencies
run: |
python3 -m pip install pytest wheel pylint pylint-flask pytest-cov typeguard

- name: Build and Install Package
run: |
python3 setup.py bdist_wheel && \
python3 setup.py bdist_wheel --universal && \
wheel_file=$(ls dist/*.whl 2>/dev/null || echo '') && \
if [ -z "$wheel_file" ]; then
echo 'Error: No wheel file found in dist directory.' && exit 1
Expand All @@ -77,20 +85,28 @@ jobs:

- name: Lint with Pylint
run: |
python3 -m pylint capybara \
--rcfile=.github/workflows/.pylintrc \
--load-plugins pylint_flask
python3 -m pylint capybara --rcfile=.github/workflows/.pylintrc --load-plugins pylint_flask

- name: Run Tests with Pytest
- name: Run tests with pytest
run: |
mkdir -p tests/coverage && \
python3 -m pytest tests --junitxml=tests/coverage/cov-junitxml.xml \
--cov=capybara | tee tests/coverage/cov.txt
mkdir -p tests/coverage
python -m pip install pytest pytest-cov typeguard
python -m pytest tests --junitxml=tests/coverage/cov-junitxml.xml --cov=capybara

- name: Pytest Coverage Comment
id: coverageComment
uses: MishaKav/pytest-coverage-comment@main
- name: Surface failing tests
uses: pmeier/pytest-results-action@main
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
pytest-coverage-path: tests/coverage/cov.txt
junitxml-path: tests/coverage/cov-junitxml.xml
path: tests/coverage/cov-junitxml.xml
summary: true
display-options: fEX
fail-on-empty: true
title: Test results

- name: Clean artifacts
run:
rm -rf dist wheelhouse build *.egg-info

- name: Clean workspace when fail
if: failure()
run:
rm -rf ${{ github.workspace }}
11 changes: 4 additions & 7 deletions capybara/onnxengine/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
from .engine import Backend, ONNXEngine
from .engine import ONNXEngine
from .engine_io_binding import ONNXEngineIOBinding
from .metadata import (
get_onnx_metadata,
parse_metadata_from_onnx,
write_metadata_into_onnx,
)
from .tools import get_onnx_input_infos, get_onnx_output_infos, make_onnx_dynamic_axes
from .enum import Backend
from .metadata import get_onnx_metadata, parse_metadata_from_onnx, write_metadata_into_onnx
from .tools import get_onnx_input_infos, get_onnx_output_infos, get_recommended_backend, make_onnx_dynamic_axes

# 暫時無法使用
# from .quantize import quantize, quantize_static
9 changes: 1 addition & 8 deletions capybara/onnxengine/engine.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
from enum import Enum
from pathlib import Path
from typing import Any, Dict, Union

import colored
import numpy as np
import onnxruntime as ort

from ..enums import EnumCheckMixin
from .enum import Backend
from .metadata import parse_metadata_from_onnx
from .tools import get_onnx_input_infos, get_onnx_output_infos


class Backend(EnumCheckMixin, Enum):
cpu = 0
cuda = 1
coreml = 2


class ONNXEngine:
def __init__(
self,
Expand Down
23 changes: 6 additions & 17 deletions capybara/onnxengine/engine_io_binding.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def __init__(
providers=providers,
provider_options=provider_options,
)
self.device = "cuda" if "CUDAExecutionProvider" in self.sess.get_providers() else "cpu"

# setting onnxruntime session info
self.model_path = model_path
Expand All @@ -62,9 +63,7 @@ def __init__(

input_infos, output_infos = self._init_io_infos(model_path, input_initializer)

io_binding, x_ortvalues, y_ortvalues = self._setup_io_binding(
input_infos, output_infos
)
io_binding, x_ortvalues, y_ortvalues = self._setup_io_binding(input_infos, output_infos)
self.io_binding = io_binding
self.x_ortvalues = x_ortvalues
self.y_ortvalues = y_ortvalues
Expand Down Expand Up @@ -121,14 +120,10 @@ def _setup_io_binding(self, input_infos, output_infos):
y_ortvalues = {}
for k, v in input_infos.items():
m = np.zeros(**v)
x_ortvalues[k] = ort.OrtValue.ortvalue_from_numpy(
m, device_type="cuda", device_id=self.device_id
)
x_ortvalues[k] = ort.OrtValue.ortvalue_from_numpy(m, device_type=self.device, device_id=self.device_id)
for k, v in output_infos.items():
m = np.zeros(**v)
y_ortvalues[k] = ort.OrtValue.ortvalue_from_numpy(
m, device_type="cuda", device_id=self.device_id
)
y_ortvalues[k] = ort.OrtValue.ortvalue_from_numpy(m, device_type=self.device, device_id=self.device_id)

io_binding = self.sess.io_binding()
for k, v in x_ortvalues.items():
Expand Down Expand Up @@ -158,11 +153,7 @@ def format_nested_dict(dict_data, indent=0):
if isinstance(value, dict):
info.append(f"{prefix}{key}:")
info.append(format_nested_dict(value, indent + 1))
elif (
isinstance(value, str)
and value.startswith("{")
and value.endswith("}")
):
elif isinstance(value, str) and value.startswith("{") and value.endswith("}"):
try:
nested_dict = eval(value)
if isinstance(nested_dict, dict):
Expand All @@ -179,9 +170,7 @@ def format_nested_dict(dict_data, indent=0):
title = "DOCSAID X ONNXRUNTIME"
divider_length = 50
divider = f"+{'-' * divider_length}+"
styled_title = colored.stylize(
title, [colored.fg("blue"), colored.attr("bold")]
)
styled_title = colored.stylize(title, [colored.fg("blue"), colored.attr("bold")])

def center_text(text, width):
"""Center text within a fixed width, handling ANSI escape codes."""
Expand Down
9 changes: 9 additions & 0 deletions capybara/onnxengine/enum.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
from enum import Enum

from ..enums import EnumCheckMixin


class Backend(EnumCheckMixin, Enum):
cpu = 0
cuda = 1
coreml = 2
19 changes: 17 additions & 2 deletions capybara/onnxengine/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@
from typing import Dict, List, Optional, Union

import onnx
import onnxsim
import onnxruntime as ort
import onnxslim
from onnx.helper import make_graph, make_model, make_opsetid, tensor_dtype_to_np_dtype

from .enum import Backend

__all__ = [
"get_onnx_input_infos",
"get_onnx_output_infos",
"make_onnx_dynamic_axes",
"get_recommended_backend",
]


Expand Down Expand Up @@ -75,5 +79,16 @@ def make_onnx_dynamic_axes(
if x.op_type == "Reshape":
raise ValueError("Reshape cannot be trasformed to dynamic axes")

new_model, _ = onnxsim.simplify(new_model)
new_model = onnxslim.slim(new_model)
Comment thread
kunkunlin1221 marked this conversation as resolved.
onnx.save(new_model, output_fpath)


def get_recommended_backend() -> Backend:
providers = ort.get_available_providers()
device = ort.get_device()
if "CUDAExecutionProvider" in providers and device == "GPU":
Comment thread
kunkunlin1221 marked this conversation as resolved.
return Backend.cuda
elif "CoreMLExecutionProvider" in providers:
return Backend.coreml
else:
return Backend.cpu
1 change: 1 addition & 0 deletions capybara/vision/videotools/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .video2frames import *
from .video2frames_v2 import *
Loading
Loading