Metadata-Version: 2.4
Name: annular-text-rectifier
Version: 0.1.0
Summary: Training-free polar rectification of text printed along circular arcs
Author: Shreejit Gautam, Pranav Subedi
License-Expression: MIT
Keywords: ocr,curved-text,circular-text,image-rectification,computer-vision
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Scientific/Engineering :: Image Processing
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: numpy>=1.23
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == "dev"
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: ruff>=0.6; extra == "dev"
Requires-Dist: twine>=5; extra == "dev"
Dynamic: license-file

# annular-text-rectifier

[![CI](https://github.com/Shreejit-gautam/annular-text-rectifier/actions/workflows/workflow.yml/badge.svg)](https://github.com/Shreejit-gautam/annular-text-rectifier/actions/workflows/workflow.yml)

`annular-text-rectifier` straightens text printed along a circular arc into a rectangular image suitable for OCR. It uses deterministic inverse polar mapping, requires no trained model, and depends only on NumPy.

It is intended for text on seals, stamps, bottle caps, coins, bearings, rings, gauges, and circular labels. It does **not** claim to rectify arbitrary free-form curves.

## Installation

```bash
pip install annular-text-rectifier
```

For local development:

```bash
python -m pip install -e ".[dev]"
```

## Basic usage

```python
import numpy as np
from annular_text_rectifier import rectify_annular_text

image = np.asarray(...)  # (height, width) or (height, width, channels)
polygon = np.array([
    [120, 80],
    [160, 65],
    [205, 80],
    [195, 105],
    [160, 92],
    [130, 105],
])

result = rectify_annular_text(
    image,
    polygon,
    center=(160, 160),
    direction="clockwise",
    radial_order="inner-to-outer",
    output_height=48,
)

rectified = result.image
print(result.geometry.as_dict())
```

With OpenCV for file input/output (OpenCV is optional and not installed by this package):

```python
import cv2
import numpy as np
from annular_text_rectifier import rectify_annular_text

image = cv2.imread("seal.png")
polygon = np.load("seal_polygon.npy")

result = rectify_annular_text(
    image,
    polygon,
    center=(350, 380),
    direction="clockwise",
    radial_order="outer-to-inner",
    output_height=48,
)
cv2.imwrite("seal_rectified.png", result.image)
```

Supplying the circle center is recommended. For sufficiently long, well-described annular polygons, the center can be estimated:

```python
result = rectify_annular_text(image, polygon)
```

Inspect `result.geometry.normalized_fit_error` when using automatic estimation. Ambiguous estimates raise `GeometryEstimationError` rather than silently producing a misleading crop. Short arcs should use an explicit center.

## Reading direction

Image geometry cannot determine the language's natural reading order or whether glyphs point inward or outward. Configure both explicitly:

- `direction="clockwise"` or `"counterclockwise"` controls horizontal order.
- `radial_order="inner-to-outer"` or `"outer-to-inner"` controls vertical order.

An OCR orientation classifier can be applied after rectification if these properties are unknown.

## Stable integration API

The package exposes three public operations:

```python
from annular_text_rectifier import (
    build_rectification_map,
    estimate_annular_geometry,
    rectify_annular_text,
)
```

- `estimate_annular_geometry` validates a polygon and estimates its polar bounds.
- `build_rectification_map` produces reproducible source coordinate maps.
- `rectify_annular_text` estimates geometry, remaps pixels, and returns metadata.

The separation lets OCR libraries use their own tensor or GPU sampling implementation while sharing the same geometry.

## Limitations

- The text baseline must be approximately circular.
- Automatic center estimation requires at least six useful boundary points.
- A short arc usually needs a known center.
- The polygon should cover both inner and outer boundaries of the text band.
- Perspective distortion of the circular plane should be corrected before polar rectification.

## Development checks

```bash
python -m pytest
python -m ruff check .
python -m build
python -m twine check dist/*
```

## Publishing

The GitHub Actions workflow tests Python 3.9 through 3.14, builds both distributions, and uploads them as a workflow artifact. Publishing a GitHub Release additionally publishes the validated distributions to PyPI through Trusted Publishing.

Configure the PyPI trusted publisher with:

- Owner: `Shreejit-gautam`
- Repository: `annular-text-rectifier`
- Workflow: `workflow.yml`
- Environment: `pypi`

The GitHub Release tag should match the package version, for example `v0.1.0`.

## License

MIT License.

## Developers

- Shreejit Gautam
- Pranav Subedi
