Skip to main content

doritex

Finds the words in an image and the direction each one reads, for text rotated at any angle. Runs on netcl, on an OpenCL GPU or on the CPU. The model weights are included.

pip install doritex

Example

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

Metadata

Release files for doritex 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for doritex 0.1.0
File Size Uploaded
doritex-0.1.0.tar.gz 4.1 MB Details

Built distribution (wheel)

Table of built distributions (wheels) for doritex 0.1.0
File Interpreter ABI Platform
doritex-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 8.2 MB

Release files / doritex-0.1.0.tar.gz

Download URL doritex-0.1.0.tar.gz
Size 4.1 MB
Tags Source
SHA-256 checksum
How to use checksums
d100830dc87f5c04f91817e4bb6ecfa0404f82207594a1e049cc7f5316b8784e
BLAKE2b-256 checksum
How to use checksums
3d0c523a0310df93e83959dc190c676629c97be19f0f572ff1ae253c22ba13e1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release files / doritex-0.1.0-py3-none-any.whl

Download URL doritex-0.1.0-py3-none-any.whl
Size 4.1 MB
Tags Python 3
SHA-256 checksum
How to use checksums
3ee043d251986d7f2b7fb2f210df09b4246e9ebdf8e83d416b23be884706520d
BLAKE2b-256 checksum
How to use checksums
1db4ce66146ab61bfa07e03c4c12fa9d2bff91cfecce2558cadca9e5c825f037
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.3

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page