fastbbox 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fastbbox-0.1.0/.github/workflows/build.yml +122 -0
- fastbbox-0.1.0/.gitignore +157 -0
- fastbbox-0.1.0/CMakeLists.txt +34 -0
- fastbbox-0.1.0/MANIFEST.in +6 -0
- fastbbox-0.1.0/PKG-INFO +214 -0
- fastbbox-0.1.0/README.md +185 -0
- fastbbox-0.1.0/benchmark_fastbbox.py +473 -0
- fastbbox-0.1.0/pyproject.toml +69 -0
- fastbbox-0.1.0/src/fastbbox/__init__.py +9 -0
- fastbbox-0.1.0/src/fastbbox/bbox_nb.cpp +505 -0
- fastbbox-0.1.0/src/fastbbox/obb_bbox_nb.cpp +283 -0
- fastbbox-0.1.0/test_fastbbox.py +579 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
name: Build and Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
tags:
|
|
7
|
+
- 'v*' # release: v1.2.3 → publish to PyPI
|
|
8
|
+
- 'v*-rc*' # candidate: v1.2.3-rc1 → publish to TestPyPI
|
|
9
|
+
pull_request:
|
|
10
|
+
branches: [ main ]
|
|
11
|
+
workflow_dispatch: # allow manual trigger from the Actions UI
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
build_wheels:
|
|
15
|
+
name: Build wheels on ${{ matrix.os }}
|
|
16
|
+
runs-on: ${{ matrix.os }}
|
|
17
|
+
timeout-minutes: 30
|
|
18
|
+
strategy:
|
|
19
|
+
matrix:
|
|
20
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
21
|
+
|
|
22
|
+
steps:
|
|
23
|
+
- uses: actions/checkout@v6
|
|
24
|
+
|
|
25
|
+
- name: Set up Python
|
|
26
|
+
uses: actions/setup-python@v5
|
|
27
|
+
with:
|
|
28
|
+
python-version: '3.11'
|
|
29
|
+
|
|
30
|
+
- name: Build wheels
|
|
31
|
+
uses: pypa/cibuildwheel@v2.21.0
|
|
32
|
+
env:
|
|
33
|
+
CIBW_BUILD: cp39-* cp310-* cp311-* cp312-*
|
|
34
|
+
# Skip 32-bit, PyPy, and musl builds
|
|
35
|
+
CIBW_SKIP: "*-win32 *-manylinux_i686 *-musllinux_* pp*"
|
|
36
|
+
# Use modern manylinux_2_28
|
|
37
|
+
CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28
|
|
38
|
+
CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_28
|
|
39
|
+
# Install build dependencies
|
|
40
|
+
CIBW_BEFORE_BUILD: pip install nanobind scikit-build-core cmake ninja numpy
|
|
41
|
+
# Linux: Install C++ compiler and CMake
|
|
42
|
+
CIBW_BEFORE_ALL_LINUX: |
|
|
43
|
+
if command -v dnf >/dev/null; then
|
|
44
|
+
dnf install -y gcc-c++ cmake ninja-build
|
|
45
|
+
else
|
|
46
|
+
yum install -y gcc-c++ cmake ninja-build
|
|
47
|
+
fi
|
|
48
|
+
# Windows: Use delvewheel for repair
|
|
49
|
+
CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: pip install delvewheel && delvewheel repair -w {dest_dir} {wheel}
|
|
50
|
+
# Smoke test
|
|
51
|
+
CIBW_TEST_COMMAND: >-
|
|
52
|
+
python -c "from fastbbox import bbox_overlaps; import numpy as np;
|
|
53
|
+
boxes = np.array([[0,0,10,10]], dtype=np.float32);
|
|
54
|
+
result = bbox_overlaps(boxes, boxes);
|
|
55
|
+
assert result[0,0] > 0.99, 'IoU test failed';
|
|
56
|
+
print('fastbbox import OK')"
|
|
57
|
+
# nanobind requires macos 10.13 or higher
|
|
58
|
+
CIBW_ENVIRONMENT_MACOS: MACOSX_DEPLOYMENT_TARGET=10.13
|
|
59
|
+
|
|
60
|
+
- uses: actions/upload-artifact@v4
|
|
61
|
+
with:
|
|
62
|
+
name: wheels-${{ matrix.os }}
|
|
63
|
+
path: ./wheelhouse/*.whl
|
|
64
|
+
|
|
65
|
+
build_sdist:
|
|
66
|
+
name: Build source distribution
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
timeout-minutes: 15
|
|
69
|
+
steps:
|
|
70
|
+
- uses: actions/checkout@v4
|
|
71
|
+
|
|
72
|
+
- name: Build sdist
|
|
73
|
+
run: pipx run build --sdist
|
|
74
|
+
|
|
75
|
+
- uses: actions/upload-artifact@v4
|
|
76
|
+
with:
|
|
77
|
+
name: sdist
|
|
78
|
+
path: dist/*.tar.gz
|
|
79
|
+
|
|
80
|
+
upload_testpypi:
|
|
81
|
+
needs: [build_wheels, build_sdist]
|
|
82
|
+
runs-on: ubuntu-latest
|
|
83
|
+
timeout-minutes: 15
|
|
84
|
+
# Only on release-candidate tags: v1.2.3-rc1, v1.2.3-rc2, etc.
|
|
85
|
+
if: github.event_name == 'push' && contains(github.ref, '-rc')
|
|
86
|
+
environment:
|
|
87
|
+
name: testpypi
|
|
88
|
+
url: https://test.pypi.org/p/fastbbox
|
|
89
|
+
steps:
|
|
90
|
+
- name: Download all artifacts
|
|
91
|
+
uses: actions/download-artifact@v8
|
|
92
|
+
with:
|
|
93
|
+
path: dist
|
|
94
|
+
merge-multiple: true
|
|
95
|
+
|
|
96
|
+
- name: Publish to TestPyPI
|
|
97
|
+
run: |
|
|
98
|
+
pip install twine
|
|
99
|
+
twine upload --repository testpypi dist/*
|
|
100
|
+
env:
|
|
101
|
+
TWINE_USERNAME: __token__
|
|
102
|
+
TWINE_PASSWORD: ${{ secrets.TEST_PYPI_API_TOKEN }}
|
|
103
|
+
|
|
104
|
+
upload_pypi:
|
|
105
|
+
needs: [build_wheels, build_sdist]
|
|
106
|
+
runs-on: ubuntu-latest
|
|
107
|
+
timeout-minutes: 15
|
|
108
|
+
if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v')
|
|
109
|
+
environment:
|
|
110
|
+
name: pypi
|
|
111
|
+
url: https://pypi.org/p/fastbbox
|
|
112
|
+
permissions:
|
|
113
|
+
id-token: write
|
|
114
|
+
steps:
|
|
115
|
+
- name: Download all artifacts
|
|
116
|
+
uses: actions/download-artifact@v8
|
|
117
|
+
with:
|
|
118
|
+
path: dist
|
|
119
|
+
merge-multiple: true
|
|
120
|
+
|
|
121
|
+
- name: Publish to PyPI
|
|
122
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
*.pyd
|
|
9
|
+
|
|
10
|
+
# Distribution / packaging
|
|
11
|
+
.Python
|
|
12
|
+
build/
|
|
13
|
+
develop-eggs/
|
|
14
|
+
dist/
|
|
15
|
+
downloads/
|
|
16
|
+
eggs/
|
|
17
|
+
.eggs/
|
|
18
|
+
lib/
|
|
19
|
+
lib64/
|
|
20
|
+
parts/
|
|
21
|
+
sdist/
|
|
22
|
+
var/
|
|
23
|
+
wheels/
|
|
24
|
+
pip-wheel-metadata/
|
|
25
|
+
share/python-wheels/
|
|
26
|
+
*.egg-info/
|
|
27
|
+
.installed.cfg
|
|
28
|
+
*.egg
|
|
29
|
+
MANIFEST
|
|
30
|
+
|
|
31
|
+
# PyInstaller
|
|
32
|
+
# Usually these files are written by a python script from a template
|
|
33
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
34
|
+
*.manifest
|
|
35
|
+
*.spec
|
|
36
|
+
|
|
37
|
+
# Installer logs
|
|
38
|
+
pip-log.txt
|
|
39
|
+
pip-delete-this-directory.txt
|
|
40
|
+
|
|
41
|
+
# Unit test / coverage reports
|
|
42
|
+
htmlcov/
|
|
43
|
+
.tox/
|
|
44
|
+
.nox/
|
|
45
|
+
.coverage
|
|
46
|
+
.coverage.*
|
|
47
|
+
.cache
|
|
48
|
+
nosetests.xml
|
|
49
|
+
coverage.xml
|
|
50
|
+
*.cover
|
|
51
|
+
*.py,cover
|
|
52
|
+
.hypothesis/
|
|
53
|
+
.pytest_cache/
|
|
54
|
+
|
|
55
|
+
# Translations
|
|
56
|
+
*.mo
|
|
57
|
+
*.pot
|
|
58
|
+
|
|
59
|
+
# Django stuff:
|
|
60
|
+
*.log
|
|
61
|
+
local_settings.py
|
|
62
|
+
db.sqlite3
|
|
63
|
+
db.sqlite3-journal
|
|
64
|
+
|
|
65
|
+
# Flask stuff:
|
|
66
|
+
instance/
|
|
67
|
+
.webassets-cache
|
|
68
|
+
|
|
69
|
+
# Scrapy stuff:
|
|
70
|
+
.scrapy
|
|
71
|
+
|
|
72
|
+
# Sphinx documentation
|
|
73
|
+
docs/_build/
|
|
74
|
+
|
|
75
|
+
# PyBuilder
|
|
76
|
+
target/
|
|
77
|
+
|
|
78
|
+
# Jupyter Notebook
|
|
79
|
+
.ipynb_checkpoints
|
|
80
|
+
|
|
81
|
+
# IPython
|
|
82
|
+
profile_default/
|
|
83
|
+
ipython_config.py
|
|
84
|
+
|
|
85
|
+
# pyenv
|
|
86
|
+
.python-version
|
|
87
|
+
|
|
88
|
+
# pipenv
|
|
89
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
90
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
91
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
92
|
+
# install all needed dependencies.
|
|
93
|
+
#Pipfile.lock
|
|
94
|
+
|
|
95
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
|
96
|
+
__pypackages__/
|
|
97
|
+
|
|
98
|
+
# Celery stuff
|
|
99
|
+
celerybeat-schedule
|
|
100
|
+
celerybeat.pid
|
|
101
|
+
|
|
102
|
+
# SageMath parsed files
|
|
103
|
+
*.sage.py
|
|
104
|
+
|
|
105
|
+
# Environments
|
|
106
|
+
.env
|
|
107
|
+
.venv
|
|
108
|
+
env/
|
|
109
|
+
venv/
|
|
110
|
+
ENV/
|
|
111
|
+
env.bak/
|
|
112
|
+
venv.bak/
|
|
113
|
+
|
|
114
|
+
# Spyder project settings
|
|
115
|
+
.spyderproject
|
|
116
|
+
.spyproject
|
|
117
|
+
|
|
118
|
+
# Rope project settings
|
|
119
|
+
.ropeproject
|
|
120
|
+
|
|
121
|
+
# mkdocs documentation
|
|
122
|
+
/site
|
|
123
|
+
|
|
124
|
+
# mypy
|
|
125
|
+
.mypy_cache/
|
|
126
|
+
.dmypy.json
|
|
127
|
+
dmypy.json
|
|
128
|
+
|
|
129
|
+
# Pyre type checker
|
|
130
|
+
.pyre/
|
|
131
|
+
|
|
132
|
+
# Exclude auto-generated C/C++ files
|
|
133
|
+
*.c
|
|
134
|
+
*.cpp
|
|
135
|
+
*.html
|
|
136
|
+
# Track nanobind C++ sources (intentional committed sources, not generated)
|
|
137
|
+
!src/fastbbox/*_nb.cpp
|
|
138
|
+
|
|
139
|
+
# IDE files
|
|
140
|
+
.vscode/
|
|
141
|
+
.idea/
|
|
142
|
+
*.swp
|
|
143
|
+
*.swo
|
|
144
|
+
*~
|
|
145
|
+
|
|
146
|
+
# OS files
|
|
147
|
+
.DS_Store
|
|
148
|
+
.DS_Store?
|
|
149
|
+
._*
|
|
150
|
+
.Spotlight-V100
|
|
151
|
+
.Trashes
|
|
152
|
+
ehthumbs.db
|
|
153
|
+
Thumbs.db
|
|
154
|
+
|
|
155
|
+
# Temporary files
|
|
156
|
+
*.tmp
|
|
157
|
+
*.temp
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
cmake_minimum_required(VERSION 3.15...3.27)
|
|
2
|
+
project(fastbbox_nanobind LANGUAGES CXX)
|
|
3
|
+
|
|
4
|
+
# Detect Python with Development.Module component
|
|
5
|
+
if (CMAKE_VERSION VERSION_LESS 3.18)
|
|
6
|
+
set(DEV_MODULE Development)
|
|
7
|
+
else()
|
|
8
|
+
set(DEV_MODULE Development.Module)
|
|
9
|
+
endif()
|
|
10
|
+
|
|
11
|
+
find_package(Python 3.9 COMPONENTS Interpreter ${DEV_MODULE} REQUIRED)
|
|
12
|
+
|
|
13
|
+
# Configure optimized release build by default
|
|
14
|
+
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
|
15
|
+
set(CMAKE_BUILD_TYPE Release CACHE STRING "Choose the type of build." FORCE)
|
|
16
|
+
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
|
|
17
|
+
endif()
|
|
18
|
+
|
|
19
|
+
# Detect the installed nanobind package and import it into CMake
|
|
20
|
+
execute_process(
|
|
21
|
+
COMMAND "${Python_EXECUTABLE}" -m nanobind --cmake_dir
|
|
22
|
+
OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE nanobind_ROOT)
|
|
23
|
+
find_package(nanobind CONFIG REQUIRED)
|
|
24
|
+
|
|
25
|
+
# Build bbox module
|
|
26
|
+
# Use NOMINSIZE since our binding layer contains significant computational logic
|
|
27
|
+
# that benefits from speed optimization rather than size optimization
|
|
28
|
+
nanobind_add_module(bbox NOMINSIZE ${CMAKE_CURRENT_SOURCE_DIR}/src/fastbbox/bbox_nb.cpp)
|
|
29
|
+
|
|
30
|
+
# Build obb_bbox module
|
|
31
|
+
nanobind_add_module(obb_bbox NOMINSIZE ${CMAKE_CURRENT_SOURCE_DIR}/src/fastbbox/obb_bbox_nb.cpp)
|
|
32
|
+
|
|
33
|
+
# Install the modules
|
|
34
|
+
install(TARGETS bbox obb_bbox LIBRARY DESTINATION fastbbox)
|
fastbbox-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: fastbbox
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Fast IoU/overlap computations for bounding boxes
|
|
5
|
+
Author-Email: Gerry Lim <gerrylimwk@gmail.com>
|
|
6
|
+
License: MIT
|
|
7
|
+
Classifier: Development Status :: 4 - Beta
|
|
8
|
+
Classifier: Intended Audience :: Developers
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: C++
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering
|
|
17
|
+
Project-URL: Homepage, https://github.com/gerrylwk/fastbbox
|
|
18
|
+
Project-URL: Repository, https://github.com/gerrylwk/fastbbox
|
|
19
|
+
Project-URL: Issues, https://github.com/gerrylwk/fastbbox/issues
|
|
20
|
+
Requires-Python: >=3.9
|
|
21
|
+
Requires-Dist: numpy>=1.19.0
|
|
22
|
+
Provides-Extra: dev
|
|
23
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
24
|
+
Requires-Dist: build>=0.10; extra == "dev"
|
|
25
|
+
Requires-Dist: scikit-build-core>=0.5.0; extra == "dev"
|
|
26
|
+
Requires-Dist: nanobind>=1.0.0; extra == "dev"
|
|
27
|
+
Requires-Dist: cmake>=3.15; extra == "dev"
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# FastBBox
|
|
31
|
+
|
|
32
|
+
Fast IoU/overlap computations for axis-aligned and oriented bounding boxes, powered by nanobind C++ extensions.
|
|
33
|
+
|
|
34
|
+
## Benchmark
|
|
35
|
+
```
|
|
36
|
+
Function Python (ms) FastBBox (ms) Speedup
|
|
37
|
+
--------------------------------------------------
|
|
38
|
+
IoU 1994.19 4.19 475.7x
|
|
39
|
+
GIoU 3028.40 5.99 505.8x
|
|
40
|
+
DIoU 4104.21 6.21 661.3x
|
|
41
|
+
CIoU 6436.51 17.55 366.7x
|
|
42
|
+
EIoU 5211.51 7.04 740.5x
|
|
43
|
+
NWD 2427.36 13.31 182.4x
|
|
44
|
+
OBB 21729.42 31.29 694.5x
|
|
45
|
+
--------------------------------------------------
|
|
46
|
+
TOTAL 44931.61 85.58 525.1x
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install fastbbox
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Building from Source
|
|
56
|
+
|
|
57
|
+
Requires CMake 3.15+ and a C++17 compiler.
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
git clone https://github.com/gerrylwk/fastbbox
|
|
61
|
+
cd fastbbox
|
|
62
|
+
pip install .
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Usage
|
|
66
|
+
|
|
67
|
+
### Axis-Aligned Bounding Boxes
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
import numpy as np
|
|
71
|
+
from fastbbox import (bbox_overlaps, generalized_iou, distance_iou,
|
|
72
|
+
complete_iou, efficient_iou, normalized_wasserstein_distance)
|
|
73
|
+
|
|
74
|
+
# Bounding boxes in [x1, y1, x2, y2] format
|
|
75
|
+
boxes = np.array([
|
|
76
|
+
[0, 0, 10, 10],
|
|
77
|
+
[5, 5, 15, 15],
|
|
78
|
+
[20, 20, 30, 30]
|
|
79
|
+
], dtype=np.float32)
|
|
80
|
+
|
|
81
|
+
query_boxes = np.array([
|
|
82
|
+
[0, 0, 10, 10],
|
|
83
|
+
[12, 12, 22, 22]
|
|
84
|
+
], dtype=np.float32)
|
|
85
|
+
|
|
86
|
+
iou = bbox_overlaps(boxes, query_boxes)
|
|
87
|
+
giou = generalized_iou(boxes, query_boxes)
|
|
88
|
+
diou = distance_iou(boxes, query_boxes)
|
|
89
|
+
ciou = complete_iou(boxes, query_boxes)
|
|
90
|
+
eiou = efficient_iou(boxes, query_boxes)
|
|
91
|
+
nwd = normalized_wasserstein_distance(boxes, query_boxes)
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
### Oriented Bounding Boxes (OBB)
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
import numpy as np
|
|
98
|
+
import math
|
|
99
|
+
from fastbbox import bbox_overlaps_obb
|
|
100
|
+
|
|
101
|
+
# Oriented bounding boxes in [center_x, center_y, width, height, angle_radians] format
|
|
102
|
+
obb_boxes = np.array([
|
|
103
|
+
[0, 0, 4, 2, 0],
|
|
104
|
+
[1, 0, 4, 2, math.pi/4],
|
|
105
|
+
[0, 0, 2, 2, math.pi/6],
|
|
106
|
+
], dtype=np.float32)
|
|
107
|
+
|
|
108
|
+
obb_query_boxes = np.array([
|
|
109
|
+
[0, 0, 4, 2, 0],
|
|
110
|
+
[2, 2, 2, 2, 0],
|
|
111
|
+
], dtype=np.float32)
|
|
112
|
+
|
|
113
|
+
obb_iou = bbox_overlaps_obb(obb_boxes, obb_query_boxes)
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Features
|
|
117
|
+
|
|
118
|
+
### Axis-Aligned Bounding Box IoU Variants
|
|
119
|
+
|
|
120
|
+
All variants accept boxes in `[x1, y1, x2, y2]` top-left-bottom-right format:
|
|
121
|
+
|
|
122
|
+
- **Standard IoU**: Classic Intersection over Union
|
|
123
|
+
- **Generalized IoU (GIoU)**: Considers enclosing area; values in `[-1, 1]`
|
|
124
|
+
- Reference: [Generalized Intersection over Union](https://arxiv.org/abs/1902.09630)
|
|
125
|
+
- **Distance IoU (DIoU)**: Penalizes center point distance
|
|
126
|
+
- Reference: [Distance-IoU Loss](https://arxiv.org/abs/1911.08287)
|
|
127
|
+
- **Complete IoU (CIoU)**: Adds aspect ratio consistency penalty to DIoU
|
|
128
|
+
- Reference: [Distance-IoU Loss](https://arxiv.org/abs/1911.08287)
|
|
129
|
+
- **Efficient IoU (EIoU)**: Separate width/height penalties for faster convergence
|
|
130
|
+
- Reference: [Focal and Efficient IOU Loss](https://arxiv.org/abs/2101.08158)
|
|
131
|
+
- **Normalized Wasserstein Distance (NWD)**: Optimal transport-based similarity, values in `[0, 1]`
|
|
132
|
+
- Effective for tiny object detection
|
|
133
|
+
- Reference: [Normalized Gaussian Wasserstein Distance](https://arxiv.org/abs/2110.13389)
|
|
134
|
+
|
|
135
|
+
### Oriented Bounding Box (OBB) IoU
|
|
136
|
+
|
|
137
|
+
Accepts boxes in `[center_x, center_y, width, height, angle_radians]` format:
|
|
138
|
+
|
|
139
|
+
- Exact calculation for axis-aligned boxes (angle = 0)
|
|
140
|
+
- Approximation-based calculation for rotated boxes using AABB intersection with angle-based scaling
|
|
141
|
+
- Batch processing support
|
|
142
|
+
|
|
143
|
+
## Performance
|
|
144
|
+
|
|
145
|
+
FastBBox provides significant speedup over pure Python implementations, especially for large numbers of bounding boxes.
|
|
146
|
+
|
|
147
|
+
Run `python benchmark_fastbbox.py` to benchmark on your system.
|
|
148
|
+
|
|
149
|
+
### When to Use Each Variant
|
|
150
|
+
|
|
151
|
+
- **IoU**: Standard evaluation, NMS (Non-Maximum Suppression)
|
|
152
|
+
- **GIoU**: Training loss for non-overlapping boxes
|
|
153
|
+
- **DIoU**: Object detection training where center distance matters
|
|
154
|
+
- **CIoU**: Bounding box regression with aspect ratio consistency
|
|
155
|
+
- **EIoU**: Fast convergence with separate width/height penalties
|
|
156
|
+
- **NWD**: Tiny object detection
|
|
157
|
+
- **OBB IoU**: Rotated object detection, text detection, aerial imagery
|
|
158
|
+
|
|
159
|
+
## OBB Implementation Details
|
|
160
|
+
|
|
161
|
+
The OBB IoU implementation uses different strategies based on box orientations:
|
|
162
|
+
|
|
163
|
+
1. **Axis-Aligned Boxes** (angle = 0): Exact intersection calculation
|
|
164
|
+
2. **Rotated Boxes**: AABB intersection with scaling factor `cos(|angle1|) * cos(|angle2|)`, minimum 50% retention
|
|
165
|
+
|
|
166
|
+
For exact rotated box IoU, consider implementing Sutherland-Hodgman clipping or the Separating Axes Theorem (SAT).
|
|
167
|
+
|
|
168
|
+
## Development
|
|
169
|
+
|
|
170
|
+
### Building Locally
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
pip install build scikit-build-core cmake nanobind
|
|
174
|
+
python -m build
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Testing Your Build
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
# Correctness tests (compares fastbbox against Python reference implementations)
|
|
181
|
+
python test_fastbbox.py # Summary output
|
|
182
|
+
python test_fastbbox.py --verbose # Detailed output with values
|
|
183
|
+
python test_fastbbox.py -f iou giou # Test specific functions
|
|
184
|
+
|
|
185
|
+
# Performance benchmarks
|
|
186
|
+
python benchmark_fastbbox.py # Summary output
|
|
187
|
+
python benchmark_fastbbox.py --verbose # Detailed timing per run
|
|
188
|
+
python benchmark_fastbbox.py --size 1000 # Test with 1000 boxes
|
|
189
|
+
python benchmark_fastbbox.py --runs 10 # 10 iterations
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
#### Test File Options
|
|
193
|
+
|
|
194
|
+
**test_fastbbox.py** - Correctness validation:
|
|
195
|
+
- `--verbose, -v`: Show detailed output with expected/actual values
|
|
196
|
+
- `--function, -f`: Test specific functions (iou, giou, diou, ciou, eiou, nwd, obb)
|
|
197
|
+
- `--tolerance, -t`: Tolerance threshold (default: 1e-5)
|
|
198
|
+
- `--obb-tolerance`: OBB-specific tolerance (default: 1e-3)
|
|
199
|
+
- `--size, -s`: Number of test boxes (default: 100)
|
|
200
|
+
|
|
201
|
+
**benchmark_fastbbox.py** - Performance benchmarks:
|
|
202
|
+
- `--verbose, -v`: Show individual run times and statistics
|
|
203
|
+
- `--function, -f`: Benchmark specific functions
|
|
204
|
+
- `--size, -s`: Number of boxes (default: 500)
|
|
205
|
+
- `--runs, -r`: Number of iterations (default: 5)
|
|
206
|
+
|
|
207
|
+
## Requirements
|
|
208
|
+
|
|
209
|
+
- Python 3.9+
|
|
210
|
+
- NumPy >= 1.19.0
|
|
211
|
+
|
|
212
|
+
## License
|
|
213
|
+
|
|
214
|
+
MIT License - see LICENSE file for details.
|