Metadata-Version: 2.2
Name: serron
Version: 0.1.1
Summary:  Mathematical Morphology module for PyTorch (CUDA), providing differentiable operators and learnable network layers.
Keywords: cuda,pytorch,morphology
Author-Email: Vedran Hrabar <vedran.hrabar@outlook.com>
License: MIT
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Environment :: GPU
Classifier: Environment :: GPU :: NVIDIA CUDA
Classifier: Environment :: GPU :: NVIDIA CUDA :: 13
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: POSIX :: Linux
Classifier: Operating System :: Microsoft :: Windows
Classifier: Programming Language :: C++
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Scientific/Engineering :: Image Recognition
Classifier: Topic :: Scientific/Engineering :: Mathematics
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Project-URL: repository, https://github.com/vhrabar/serron
Project-URL: documentation, https://github.com/vhrabar/serron/wiki
Project-URL: Bug Tracker, https://github.com/vhrabar/serron/issues
Requires-Python: >=3.12
Requires-Dist: torch>=2.12
Provides-Extra: cpu
Requires-Dist: torch>=2.12; extra == "cpu"
Provides-Extra: cu132
Requires-Dist: torch>=2.12; extra == "cu132"
Description-Content-Type: text/markdown

# Serron

Mathematical Morphology module for PyTorch (CUDA), providing differentiable operators and learnable network layers.
## Install

Prebuilt wheels are published for CPython 3.12–3.14 on Linux (x86_64, aarch64) and
Windows (x86_64). A working CUDA-enabled PyTorch (`torch >= 2.12`) must already
be installed in the environment.

```bash
pip install serron
```

## Usage

> **Alpha:** the CUDA kernels are not wired up yet, so the operators below currently
> raise `NotImplementedError`.

Serron works on standard PyTorch tensors laid out as `(N, C, H, W)` and living on a CUDA
device.

### Functional operators

Stateless operators live in `serron.functional` and are re-exported at the top level.
Each takes an input tensor, a structuring element, and an optional `border` mode:

```python
import torch
import serron
from serron import BorderMode
from serron import structuring_element as se

x = torch.rand(1, 1, 256, 256, device="cuda")
kernel = se.disk(3, device="cuda")

eroded = serron.erosion(x, kernel)
dilated = serron.dilatation(x, kernel)
opened = serron.opening(x, kernel)
closed = serron.closing(x, kernel)

# Derived operators
grad = serron.gradient(x, kernel)  # dilate(x) - erode(x)
white = serron.top_hat(x, kernel)  # x - open(x)
black = serron.black_hat(x, kernel)  # close(x) - x

# Control border handling
eroded_reflect = serron.erosion(x, kernel, border=BorderMode.REFLECT)
```

Available operators: `erosion`, `dilatation`, `opening`, `closing`, `gradient`,
`top_hat`, `black_hat`.

### Structuring elements

`serron.structuring_element` builds common SE shapes on the requested device:

```python
from serron import structuring_element as se

se.square(5, device="cuda")  # (5, 5) full square
se.cross(5, device="cuda")  # (5, 5) plus shape
se.disk(3, device="cuda")  # (7, 7) disk, radius 3
se.diamond(3, device="cuda")  # (7, 7) diamond, radius 3
se.from_tensor(my_weights)  # wrap an arbitrary 2-D tensor as a grayscale SE
```

### Border modes

`BorderMode` controls how out-of-bounds neighbors are handled:

| Mode | Behavior |
| --- | --- |
| `BorderMode.REPLICATE` | Repeat the edge value (default) |
| `BorderMode.REFLECT` | Mirror across the edge |
| `BorderMode.CONSTANT` | Pad with a constant |

### Learnable layers

`serron` also exposes `torch.nn.Module` layers with a learnable structuring element,
so morphology can be trained end-to-end inside a network. Each layer takes the number
of `channels` and a `kernel_size`:

```python
import torch
from serron import Erosion2d, Dilation2d, Opening2d, Closing2d
from serron import BorderMode

layer = Erosion2d(channels=3, kernel_size=5, border=BorderMode.REPLICATE).cuda()

x = torch.rand(8, 3, 64, 64, device="cuda")
y = layer(x)  # forward pass; layer.weight is a trainable (C, k, k) SE
y.sum().backward()  # gradients flow into layer.weight
```

Available layers: `Erosion2d`, `Dilation2d`, `Opening2d`, `Closing2d`.

## Building from source

### Clone repo
```bash
git clone git@github.com:vhrabar/serron.git
cd serron
```

### Choosing a torch build

`torch` is pulled from a specific wheel index via mutually-exclusive extras. Pick the
one matching your machine — plain `uv sync` (no extra) falls back to the default
CUDA-enabled wheel from PyPI:

```bash
uv sync --extra cu132   # CUDA build
uv sync --extra cpu     # CPU-only build
```

### Building the wheel

Building the CUDA extension from source needs the CUDA 13.X toolkit (`nvcc`):

```bash
uv sync --package serron --no-dev --group build --extra cu132
uv build --package serron --wheel --no-build-isolation
```

On a GPU-less machine, sync the CPU torch build instead, the extension then builds
C++ only (no `nvcc` required):

```bash
uv sync --package serron --no-dev --group build --extra cpu
uv build --package serron --wheel --no-build-isolation
```

## License

MIT

Copyright © 2026 Vedran Hrabar.
