Metadata-Version: 2.4
Name: doritex
Version: 0.1.0
Summary: Word detection with reading direction for arbitrarily rotated text, on netcl (OpenCL)
Author: doritex contributors
License: MIT
Keywords: text detection,reading direction,orientation,OpenCL,netcl
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Topic :: Scientific/Engineering :: Image Recognition
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Requires-Dist: netcl>=0.3.2
Requires-Dist: numpy>=1.23
Requires-Dist: Pillow>=9.0
Provides-Extra: test
Requires-Dist: pytest; extra == "test"

# doritex

Finds the words in an image and the direction each one reads, for text rotated at any angle. Runs on
[netcl](https://pypi.org/project/netcl/), on an OpenCL GPU or on the CPU. The model weights are included.

```bash
pip install doritex
```

## Example

```python
from PIL import Image, ImageDraw, ImageFont
import doritex

# "Hello World", upside down
img = Image.new("RGB", (640, 200), "white")
ImageDraw.Draw(img).text((40, 60), "Hello World", fill="black", font=ImageFont.load_default(size=40))
img = img.rotate(180)

det = doritex.load()
words = det.detect(img)
for w in words:
    print(f"angle {w.angle360:5.1f}°  score {w.score:.2f}  direction {w.direction_confidence:.2f}  starts at {w.quad[0].round()}")

upright = img.rotate(words[0].rotation_to_upright, expand=True)   # now reads left to right
doritex.draw(img, words).save("words.png")                        # boxes + arrows along the reading direction
print(det.crop(img, words[0]).shape)                              # first word cut out upright
```

Output:

```
angle 180.1°  score 0.85  direction 1.00  starts at [602.  83.]
angle 181.4°  score 0.81  direction 0.99  starts at [500.  83.]
(64, 95, 3)
```

Both words were found upside down (about 180°). They are listed most confident first. Each starts where its first
letter is: "Hello" at the right, "World" further left.

## Reading direction and angles

The reading direction runs from a word's first letter to its last. doritex reports it on every word:

- `quad[0] → quad[1]` points along the reading direction (start → end of the baseline).
- `angle360` gives that direction as a total angle, counter-clockwise from normal text: `0°` reads left to right,
  `90°` bottom to top, `180°` upside down, `270°` top to bottom. Text tilted on a disc or a photo gets an
  in-between value. `angle` is the same rotation in the range −180…180.
- `rotation_to_upright` is how far to rotate the image so that the word reads normally. It uses the convention of
  `PIL.Image.rotate`: `img.rotate(word.rotation_to_upright, expand=True)`.
- `direction_confidence` (0.5–1) says how sure the model is that the word is not actually reversed, i.e. rotated by
  180°. Values near 0.5 mean the glyphs did not show it. This happens with tiny text, and with tokens that also read
  upside down (`SOS`, `6`/`9`).

## API

**`doritex.load(weights=None, device="auto", input_size=1024) -> Detector`**
Loads the bundled model. `device` is `"auto"` (an OpenCL GPU if present) or `"cpu"`. Images larger than
`input_size` on their long side are scaled down; smaller images are used at full resolution.

**`Detector.detect(image, input_size=None, score_threshold=0.3, nms_iou=0.4) -> list[Word]`**
`image` can be a file path, a `PIL.Image` or a numpy array (RGB, RGBA or grayscale; `uint8`, or float in 0–1).
Coordinates are in pixels of that image.

**`Detector.crop(image, word, height=64) -> np.ndarray`**
Cuts the word out and turns it upright (RGB `uint8`), for example as input for OCR.

**`doritex.draw(image, words) -> PIL.Image`**
Draws each box and an arrow along the reading direction: green when the direction is confident, orange when it is
not.

**`Word`**

| attribute | meaning |
|---|---|
| `quad` | 4 corners `(4, 2)`: start of the baseline, end of the baseline, end of the top line, start of the top line |
| `angle360`, `angle` | reading direction as an angle, counter-clockwise: 0…360 and −180…180 |
| `direction` | unit vector of the reading direction (image coordinates, y points down) |
| `rotation_to_upright` | degrees to pass to `PIL.Image.rotate` to make the word upright |
| `score` | detection confidence, 0–1 |
| `direction_confidence` | confidence in the reading direction, 0.5–1 |
| `center`, `width`, `height`, `bbox` | centre, length along and across the text, axis-aligned box `(x0, y0, x1, y1)` |

## Notes

Words are found best at about 7–70 px height. Lower `input_size` for images with very large text.

## License

MIT
