Skip to main content

Document image orientation detection and correction.

Project description

docorient

PyPI version Python License: MIT

Document image orientation detection and correction.

Automatically detects and fixes rotation (0°, 90°, 180°, 270°) in scanned document images using a two-stage detection pipeline, with support for multi-page majority voting and parallel batch processing.


Installation

pip install docorient

To enable full 180° detection:

pip install docorient[ocr]

Note: The [ocr] extra requires Tesseract installed on your system.

  • macOS: brew install tesseract
  • Ubuntu/Debian: sudo apt install tesseract-ocr
  • Windows: installer

Quick Start

Detect orientation

from PIL import Image
from docorient import detect_orientation

image = Image.open("document.jpg")
result = detect_orientation(image)

print(result.angle)    # 0, 90, 180, or 270
print(result.reliable) # True

Correct a single image

from docorient import correct_image

corrected = correct_image(image)
corrected.save("fixed.jpg")

Correct with metadata

from docorient import correct_image

result = correct_image(image, return_metadata=True)
print(result.orientation.angle)
result.image.save("fixed.jpg")

Correct a multi-page document (majority voting)

from docorient import correct_document_pages
from PIL import Image

pages = [Image.open(f"page_{i}.jpg") for i in range(5)]
results = correct_document_pages(pages)

for i, result in enumerate(results):
    result.image.save(f"fixed_{i}.jpg")

Batch process a directory

macOS / Windows: process_directory uses multiprocessing internally. Always call it inside if __name__ == "__main__": when running as a script.

from docorient import process_directory, OrientationConfig

if __name__ == "__main__":
    config = OrientationConfig(workers=4, output_quality=95)
    summary = process_directory("./scans", output_dir="./fixed", config=config)

    print(f"Corrected: {summary.corrected}/{summary.total_pages}")
    print(f"Errors:    {summary.errors}")

CLI

docorient ./scans --output ./fixed
docorient ./scans --output ./fixed --workers 4 --quality 95
docorient ./scans --no-secondary --limit 100
docorient ./scans --dry-run
docorient --version

Configuration Reference

from docorient import OrientationConfig

config = OrientationConfig(
    secondary_confidence_threshold=2.0,  # Minimum confidence for secondary engine (default: 2.0)
    output_quality=92,                   # JPEG output quality 1-100 (default: 92)
    secondary_max_dimension=1200,        # Max image size for secondary engine (default: 1200)
    primary_max_dimension=800,           # Max image size for primary engine (default: 800)
    workers=4,                           # Parallel workers; None = cpu_count-2 (default: None)
    resume_enabled=True,                 # Resume interrupted batch jobs (default: True)
    supported_extensions=(               # File extensions to process
        ".jpg", ".jpeg", ".png",
        ".tiff", ".tif", ".bmp",
        ".gif", ".webp",
    ),
)

API Reference

detect_orientation(image, config=None) → OrientationResult

Detects the orientation of a document image without modifying it.

Parameter Type Description
image PIL.Image.Image Image to analyze
config OrientationConfig | None Configuration (uses defaults if None)

Returns OrientationResult:

Field Type Description
angle int Detected angle: 0, 90, 180, or 270
method str Internal detection trace
reliable bool Whether the detection is considered reliable

correct_image(image, *, config=None, return_metadata=False)

Detects and corrects the orientation of a single image.

  • return_metadata=False → returns PIL.Image.Image
  • return_metadata=True → returns CorrectionResult

CorrectionResult fields: image: PIL.Image.Image, orientation: OrientationResult


correct_document_pages(pages, *, config=None) → list[CorrectionResult]

Corrects orientation for all pages of a multi-page document with majority voting.


process_directory(input_dir, *, output_dir=None, config=None, limit=0, show_progress=True) → BatchSummary

Processes all images in a directory in parallel.

BatchSummary fields:

Field Type Description
input_directory str Resolved input path
output_directory str Resolved output path
total_files int Number of source documents
total_pages int Total images processed
already_correct int Pages at 0° (no correction needed)
corrected int Pages that were rotated
corrected_by_majority int Pages corrected via majority voting
errors int Pages that failed
pages tuple[PageResult, ...] Per-page results

Multi-page Document Grouping

process_directory automatically groups images by source document using the filename pattern <name>_p<number>.<ext>:

contrato_p1.jpg  ┐
contrato_p2.jpg  ├─► grouped as "contrato" → majority voting applied
contrato_p3.jpg  ┘

edital_p1.jpg    ┐
edital_p2.jpg    ┘─► grouped as "edital"

Files that don't match the pattern are treated as single-page documents.


Supported Formats

Any format readable by Pillow: JPEG, PNG, TIFF, BMP, GIF, WebP, and more.


Resume Support

Long batch jobs can be safely interrupted with Ctrl+C. Progress is saved to a _orientation_done.log file in the output directory. Re-running resumes from where it stopped.

To disable: OrientationConfig(resume_enabled=False)


Exceptions

from docorient import (
    DocorientError,
    DetectionError,
    CorrectionError,
    BatchProcessingError,
    TesseractNotAvailableError,
)

Development

git clone https://github.com/lucasleirbag/docorient.git
cd docorient
python -m venv .venv && source .venv/bin/activate
pip install -e ".[dev,ocr]"
pytest tests/ -v
ruff check src/ tests/

License

MIT — see LICENSE

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

docorient-0.3.2.tar.gz (17.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

docorient-0.3.2-py3-none-any.whl (18.6 kB view details)

Uploaded Python 3

File details

Details for the file docorient-0.3.2.tar.gz.

File metadata

  • Download URL: docorient-0.3.2.tar.gz
  • Upload date:
  • Size: 17.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.11

File hashes

Hashes for docorient-0.3.2.tar.gz
Algorithm Hash digest
SHA256 54c6c58a2db83836afad4dbcca2ac4e7d7eeb6ecd8d80f6aeece89165ceaa0c4
MD5 38c4940360d54bd287545e1209dc349e
BLAKE2b-256 512d97f72b8a830bd61f9a58320674a9a9159a5e2872959f5e3f2787a4f840ec

See more details on using hashes here.

File details

Details for the file docorient-0.3.2-py3-none-any.whl.

File metadata

  • Download URL: docorient-0.3.2-py3-none-any.whl
  • Upload date:
  • Size: 18.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.11

File hashes

Hashes for docorient-0.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 22013650b500fc09bb771ea86d63a6adfd7a5f309f2388a906dadf69a95b4a97
MD5 2ad2721c758422d3d02ef0f1212084ca
BLAKE2b-256 f0793a07ff1a2ccc77dd1ab7d7f2765203485f90ee9aee4fe22d6a0dc37e8b2b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page