Skip to content

Commit 5417ae6

Browse files
authored
version to 0.0.19 (#41)
* version to 0.0.19 * Updated CI * Fi in CI * Mypy fix * Fix
1 parent 1279734 commit 5417ae6

File tree

8 files changed

+112
-79
lines changed

8 files changed

+112
-79
lines changed

.github/workflows/ci.yml

+33-25
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,9 @@ on:
44
branches:
55
- main
66
paths-ignore:
7-
- 'CONTRIBUTORS.md'
8-
- 'README.md'
9-
- 'benchmarks/results/**'
10-
7+
- 'benchmarks/albucore_benchmark/results/**'
8+
- '**.md' # Ignore all markdown files
9+
- 'docs/**' # Ignore documentation changes
1110
jobs:
1211
test_and_lint:
1312
name: Test and lint
@@ -24,13 +23,18 @@ jobs:
2423
- operating-system: macos-13
2524
path: ~/Library/Caches/pip
2625
fail-fast: true
26+
2727
steps:
2828
- name: Checkout
2929
uses: actions/checkout@v4
30-
- name: Set up Python
30+
- name: Set up Python ${{ matrix.python-version }}
3131
uses: actions/setup-python@v5
3232
with:
3333
python-version: ${{ matrix.python-version }}
34+
cache: 'pip'
35+
cache-dependency-path: |
36+
requirements-dev.txt
37+
setup.py
3438
3539
- name: Cache Python packages
3640
uses: actions/cache@v4
@@ -41,29 +45,25 @@ jobs:
4145
${{ runner.os }}-pip-${{ matrix.python-version }}-
4246
${{ runner.os }}-pip-
4347
44-
- name: Update pip
45-
run: python -m pip install --upgrade pip
46-
- name: Install wheel
47-
run: python -m pip install --upgrade wheel
48-
- name: Install dev requirements
49-
run: pip install -r requirements-dev.txt
48+
- name: Install uv
49+
run: pip install uv
50+
5051
- name: Install dependencies
5152
run: |
52-
python -m ensurepip --upgrade
53-
pip install .
54-
- name: Cleanup the build directory
55-
uses: JesseTG/[email protected]
56-
with:
57-
path: build
58-
- name: Run PyTest
59-
run: pytest --cov .
53+
uv pip install --system --upgrade pip wheel
54+
uv pip install --system -r requirements-dev.txt
55+
uv pip install --system .
56+
57+
- name: Run PyTest with coverage
58+
run: pytest --cov . --cov-report=xml
6059

6160
- name: Upload coverage reports to Codecov
62-
if: matrix.operating-system == 'ubuntu-latest' && matrix.python-version == '3.8'
61+
if: matrix.operating-system == 'ubuntu-latest' && matrix.python-version == '3.12'
6362
uses: codecov/[email protected]
6463
with:
6564
token: ${{ secrets.CODECOV_TOKEN }}
6665
slug: albumentations-team/albucore
66+
files: ./coverage.xml
6767

6868
check_code_formatting_types:
6969
name: Check code formatting with ruff and mypy
@@ -75,15 +75,23 @@ jobs:
7575
steps:
7676
- name: Checkout
7777
uses: actions/checkout@v4
78-
- name: Set up Python
78+
- name: Set up Python ${{ matrix.python-version }}
7979
uses: actions/setup-python@v5
8080
with:
8181
python-version: ${{ matrix.python-version }}
82+
cache: 'pip'
83+
cache-dependency-path: |
84+
requirements-dev.txt
85+
setup.py
86+
87+
- name: Install uv
88+
run: pip install uv
89+
8290
- name: Install requirements
8391
run: |
84-
python -m pip install --upgrade pip uv
92+
uv pip install --system --upgrade pip
93+
uv pip install --system -r requirements-dev.txt
8594
uv pip install --system .
86-
- name: Install dev requirements
87-
run: uv pip install --system -r requirements-dev.txt
95+
8896
- name: Run checks
89-
run: pre-commit run
97+
run: pre-commit run --all-files

.pre-commit-config.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ repos:
6868
# Run the formatter.
6969
- id: ruff-format
7070
- repo: https://github.com/pre-commit/mirrors-mypy
71-
rev: v1.12.1
71+
rev: v1.13.0
7272
hooks:
7373
- id: mypy
7474
files: ^(albucore|benchmark)/

albucore/__init__.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,14 @@
1-
__version__ = "0.0.18"
1+
from importlib.metadata import metadata
2+
3+
try:
4+
_metadata = metadata("albucore")
5+
__version__ = _metadata["Version"]
6+
__author__ = _metadata["Author"]
7+
__maintainer__ = _metadata["Maintainer"]
8+
except Exception: # noqa: BLE001
9+
__version__ = "unknown"
10+
__author__ = "Vladimir Iglovikov"
11+
__maintainer__ = "Vladimir Iglovikov"
212

313
from .decorators import *
414
from .functions import *

albucore/functions.py

+41-23
Original file line numberDiff line numberDiff line change
@@ -72,31 +72,49 @@ def apply_lut(
7272

7373

7474
def prepare_value_opencv(
75-
img: np.ndarray, value: np.ndarray | float, operation: Literal["add", "multiply"]
75+
img: np.ndarray,
76+
value: np.ndarray | float,
77+
operation: Literal["add", "multiply"],
7678
) -> np.ndarray:
77-
if isinstance(value, (int, float)):
78-
if operation == "add" and img.dtype == np.uint8:
79-
value = int(value)
80-
num_channels = get_num_channels(img)
81-
if num_channels > MAX_OPENCV_WORKING_CHANNELS:
82-
if operation == "add":
83-
# Cast to float32 if value is negative to handle potential underflow issues
84-
cast_type = np.float32 if value < 0 else img.dtype
85-
value = np.full(img.shape, value, dtype=cast_type)
86-
elif operation == "multiply":
87-
value = np.full(img.shape, value, dtype=np.float32)
88-
elif isinstance(value, np.ndarray):
89-
if value.dtype == np.float64:
90-
value = value.astype(np.float32)
91-
if value.ndim == 1:
92-
value = value.reshape(1, 1, -1)
93-
value = np.broadcast_to(value, img.shape)
94-
if operation == "add" and img.dtype == np.uint8:
95-
if np.all(value >= 0):
96-
return clip(value, np.uint8)
97-
98-
value = np.trunc(value).astype(np.float32)
79+
return (
80+
_prepare_scalar_value(img, value, operation)
81+
if isinstance(value, (int, float))
82+
else _prepare_array_value(img, value, operation)
83+
)
9984

85+
86+
def _prepare_scalar_value(
87+
img: np.ndarray,
88+
value: float,
89+
operation: Literal["add", "multiply"],
90+
) -> np.ndarray | float:
91+
if operation == "add" and img.dtype == np.uint8:
92+
value = int(value)
93+
num_channels = get_num_channels(img)
94+
if num_channels > MAX_OPENCV_WORKING_CHANNELS:
95+
if operation == "add":
96+
# Cast to float32 if value is negative to handle potential underflow issues
97+
cast_type = np.float32 if value < 0 else img.dtype
98+
return np.full(img.shape, value, dtype=cast_type)
99+
if operation == "multiply":
100+
return np.full(img.shape, value, dtype=np.float32)
101+
return value
102+
103+
104+
def _prepare_array_value(
105+
img: np.ndarray,
106+
value: np.ndarray,
107+
operation: Literal["add", "multiply"],
108+
) -> np.ndarray:
109+
if value.dtype == np.float64:
110+
value = value.astype(np.float32)
111+
if value.ndim == 1:
112+
value = value.reshape(1, 1, -1)
113+
value = np.broadcast_to(value, img.shape)
114+
if operation == "add" and img.dtype == np.uint8:
115+
if np.all(value >= 0):
116+
return clip(value, np.uint8)
117+
return np.trunc(value).astype(np.float32)
100118
return value
101119

102120

albucore/utils.py

+13-7
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@
5555

5656

5757
def maybe_process_in_chunks(
58-
process_fn: Callable[Concatenate[np.ndarray, P], np.ndarray], **kwargs: Any
58+
process_fn: Callable[Concatenate[np.ndarray, P], np.ndarray],
59+
*args: P.args,
60+
**kwargs: P.kwargs,
5961
) -> Callable[[np.ndarray], np.ndarray]:
6062
"""Wrap OpenCV function to enable processing images with more than 4 channels.
6163
@@ -64,15 +66,19 @@ def maybe_process_in_chunks(
6466
6567
Args:
6668
process_fn: Transform function (e.g cv2.resize).
67-
kwargs: Additional parameters.
69+
args: Additional positional arguments.
70+
kwargs: Additional keyword arguments.
6871
6972
Returns:
7073
np.ndarray: Transformed image.
71-
7274
"""
7375

7476
@wraps(process_fn)
75-
def __process_fn(img: np.ndarray) -> np.ndarray:
77+
def __process_fn(img: np.ndarray, *process_args: P.args, **process_kwargs: P.kwargs) -> np.ndarray:
78+
# Merge args and kwargs
79+
all_args = (*args, *process_args)
80+
all_kwargs: P.kwargs = {**kwargs, **process_kwargs}
81+
7682
num_channels = get_num_channels(img)
7783
if num_channels > MAX_OPENCV_WORKING_CHANNELS:
7884
chunks = []
@@ -81,16 +87,16 @@ def __process_fn(img: np.ndarray) -> np.ndarray:
8187
# Many OpenCV functions cannot work with 2-channel images
8288
for i in range(2):
8389
chunk = img[:, :, index + i : index + i + 1]
84-
chunk = process_fn(chunk, **kwargs)
90+
chunk = process_fn(chunk, *all_args, **all_kwargs)
8591
chunk = np.expand_dims(chunk, -1)
8692
chunks.append(chunk)
8793
else:
8894
chunk = img[:, :, index : index + 4]
89-
chunk = process_fn(chunk, **kwargs)
95+
chunk = process_fn(chunk, *all_args, **all_kwargs)
9096
chunks.append(chunk)
9197
return np.dstack(chunks)
9298

93-
return process_fn(img, **kwargs)
99+
return process_fn(img, *all_args, **all_kwargs)
94100

95101
return __process_fn
96102

benchmark/albucore_benchmark/benchmark.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ def opencv_transform(self, img: np.ndarray) -> np.ndarray | None:
173173
return albucore.multiply_opencv(img, self.multiplier)
174174

175175
def lut_transform(self, img: np.ndarray) -> np.ndarray:
176-
return albucore.multiply_lut(img, self.multiplier)
176+
return albucore.multiply_lut(img, self.multiplier, inplace=False)
177177

178178
def torchvision_transform(self, img: torch.Tensor) -> torch.Tensor:
179179
return torch.mul(img, self.multiplier)
@@ -195,7 +195,7 @@ def opencv_transform(self, img: np.ndarray) -> np.ndarray:
195195
return albucore.multiply_opencv(img, self.multiplier)
196196

197197
def lut_transform(self, img: np.ndarray) -> np.ndarray:
198-
return albucore.multiply_lut(img, self.multiplier)
198+
return albucore.multiply_lut(img, self.multiplier, inplace=False)
199199

200200
def torchvision_transform(self, img: torch.Tensor) -> torch.Tensor:
201201
return torch.mul(img, self.torch_multiplier)
@@ -239,7 +239,7 @@ def opencv_transform(self, img: np.ndarray) -> np.ndarray | None:
239239
return albucore.add_opencv(img, self.value)
240240

241241
def lut_transform(self, img: np.ndarray) -> np.ndarray:
242-
return albucore.add_lut(img, self.value)
242+
return albucore.add_lut(img, self.value, inplace=False)
243243

244244
def torchvision_transform(self, img: torch.Tensor) -> torch.Tensor:
245245
return torch.add(img, self.value)
@@ -261,7 +261,7 @@ def opencv_transform(self, img: np.ndarray) -> np.ndarray:
261261
return albucore.add_opencv(img, self.value)
262262

263263
def lut_transform(self, img: np.ndarray) -> np.ndarray:
264-
return albucore.add_lut(img, self.value)
264+
return albucore.add_lut(img, self.value, inplace=False)
265265

266266
def torchvision_transform(self, img: torch.Tensor) -> torch.Tensor:
267267
return torch.add(img, self.torch_value)
@@ -472,7 +472,7 @@ def opencv_transform(self, img: np.ndarray) -> np.ndarray:
472472

473473
def lut_transform(self, img: np.ndarray) -> np.ndarray:
474474
value = MAX_VALUES_BY_DTYPE[img.dtype] / 10.0
475-
return albucore.multiply_add_lut(img, self.factor, value)
475+
return albucore.multiply_add_lut(img, self.factor, value, inplace=False)
476476

477477
def torchvision_transform(self, img: torch.Tensor) -> torch.Tensor:
478478
return img * self.factor + 13

pyproject.toml

+6-2
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@ requires = [ "setuptools>=45", "wheel" ]
55

66
[project]
77
name = "albucore"
8+
version = "0.0.19"
9+
810
description = "High-performance image processing functions for deep learning and computer vision."
911
readme = "README.md"
1012
keywords = [ "deep learning", "image processing" ]
1113
license = { file = "LICENSE" }
12-
authors = [ { name = "Vladimir I. Iglovikov" } ]
14+
maintainers = [ { name = "Vladimir Iglovikov" } ]
15+
16+
authors = [ { name = "Vladimir Iglovikov" } ]
1317
requires-python = ">=3.9"
1418

1519
classifiers = [
@@ -31,7 +35,7 @@ classifiers = [
3135
"Topic :: Software Development :: Libraries :: Python Modules",
3236
"Typing :: Typed",
3337
]
34-
dynamic = [ "dependencies", "version" ]
38+
dynamic = [ "dependencies" ]
3539

3640
[tool.setuptools]
3741
packages = { find = { include = [

setup.py

+2-15
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import re
2-
from typing import List, Tuple
3-
import os
42

53
from pkg_resources import DistributionNotFound, get_distribution
64
from setuptools import setup, find_packages
@@ -21,17 +19,7 @@
2119
),
2220
]
2321

24-
def get_version():
25-
version_file = os.path.join(os.path.dirname(__file__), 'albucore', '__init__.py')
26-
with open(version_file, 'r') as f:
27-
version_line = f.read().strip()
28-
version_regex = r"^__version__ = ['\"]([^'\"]*)['\"]"
29-
match = re.match(version_regex, version_line, re.M)
30-
if match:
31-
return match.group(1)
32-
raise RuntimeError("Unable to find version string.")
33-
34-
def choose_requirement(mains: Tuple[str, ...], secondary: str) -> str:
22+
def choose_requirement(mains: tuple[str, ...], secondary: str) -> str:
3523
chosen = secondary
3624
for main in mains:
3725
try:
@@ -43,13 +31,12 @@ def choose_requirement(mains: Tuple[str, ...], secondary: str) -> str:
4331
pass
4432
return chosen
4533

46-
def get_install_requirements(install_requires: List[str], choose_install_requires: List[Tuple[Tuple[str, ...], str]]) -> List[str]:
34+
def get_install_requirements(install_requires: list[str], choose_install_requires: list[tuple[tuple[str, ...], str]]) -> list[str]:
4735
for mains, secondary in choose_install_requires:
4836
install_requires.append(choose_requirement(mains, secondary))
4937
return install_requires
5038

5139
setup(
52-
version=get_version(),
5340
packages=find_packages(exclude=["tests", "benchmark"], include=['albucore*']),
5441
install_requires=get_install_requirements(INSTALL_REQUIRES, CHOOSE_INSTALL_REQUIRES),
5542
)

0 commit comments

Comments
 (0)