docorient 0.3.1__tar.gz → 0.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- docorient-0.3.2/CHANGELOG.md +44 -0
- {docorient-0.3.1 → docorient-0.3.2}/PKG-INFO +5 -4
- {docorient-0.3.1 → docorient-0.3.2}/docs/architecture.md +52 -19
- {docorient-0.3.1 → docorient-0.3.2}/docs/contributing.md +1 -2
- {docorient-0.3.1 → docorient-0.3.2}/pyproject.toml +5 -4
- docorient-0.3.2/src/docorient/_version.py +1 -0
- docorient-0.3.1/CHANGELOG.md +0 -22
- docorient-0.3.1/src/docorient/_version.py +0 -1
- {docorient-0.3.1 → docorient-0.3.2}/.github/workflows/publish.yml +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/.gitignore +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/LICENSE +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/README.md +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/__init__.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/_imaging.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/batch/__init__.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/batch/processor.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/batch/scanner.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/batch/worker.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/cli.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/config.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/correction.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/detection/__init__.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/detection/base.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/detection/engine.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/detection/primary.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/detection/secondary.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/exceptions.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/rotation.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/types.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/src/docorient/voting.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/tests/__init__.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/tests/conftest.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/tests/test_batch.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/tests/test_cli.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/tests/test_correction.py +0 -0
- {docorient-0.3.1 → docorient-0.3.2}/tests/test_detection.py +0 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.3.2 (2026-02-27)
|
|
4
|
+
|
|
5
|
+
- Fix: update project URLs to correct GitHub repository
|
|
6
|
+
- Add changelog link to PyPI metadata
|
|
7
|
+
|
|
8
|
+
## 0.3.1 (2026-02-27)
|
|
9
|
+
|
|
10
|
+
- Fix: author metadata corrected to Lucas Gabriel Vaz
|
|
11
|
+
- Remove `tesseract` from PyPI keywords
|
|
12
|
+
|
|
13
|
+
## 0.3.0 (2026-02-27)
|
|
14
|
+
|
|
15
|
+
- **Breaking:** detection engines refactored to class-based architecture with `DetectionEngine` Protocol
|
|
16
|
+
- Introduce `DetectionPipeline` for extensible engine orchestration
|
|
17
|
+
- Introduce `PrimaryEngine` and `SecondaryEngine` classes
|
|
18
|
+
- Extract `rotation.py` and `voting.py` as standalone modules
|
|
19
|
+
- Encapsulate worker state in `WorkerContext` dataclass
|
|
20
|
+
- Transform `_imaging.py` functions into `ImageIO` class
|
|
21
|
+
- Decompose `process_directory` into focused sub-functions
|
|
22
|
+
- Apply custom exceptions (`DetectionError`, `CorrectionError`, `BatchProcessingError`) throughout codebase
|
|
23
|
+
- Export `DetectionEngine`, `DetectionPipeline`, `PrimaryEngine`, `SecondaryEngine` in public API
|
|
24
|
+
|
|
25
|
+
## 0.2.0 (2026-02-26)
|
|
26
|
+
|
|
27
|
+
- **Breaking:** renamed config params `osd_confidence_threshold` → `secondary_confidence_threshold`, `max_osd_dimension` → `secondary_max_dimension`, `projection_target_dimension` → `primary_max_dimension`
|
|
28
|
+
- **Breaking:** renamed CLI flag `--no-ocr` → `--no-secondary`
|
|
29
|
+
- Internal engines renamed to `primary` and `secondary`
|
|
30
|
+
- Updated `OrientationResult.method` trace strings
|
|
31
|
+
|
|
32
|
+
## 0.1.1 (2026-02-26)
|
|
33
|
+
|
|
34
|
+
- Docs: added `if __name__ == "__main__":` note for `process_directory` on macOS/Windows
|
|
35
|
+
|
|
36
|
+
## 0.1.0 (2026-02-25)
|
|
37
|
+
|
|
38
|
+
- Initial release
|
|
39
|
+
- Primary engine for 90°/270° detection
|
|
40
|
+
- Optional secondary engine for 180° detection
|
|
41
|
+
- Single image and batch directory processing
|
|
42
|
+
- Multi-page majority voting
|
|
43
|
+
- Resumable batch processing
|
|
44
|
+
- CLI interface
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: docorient
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: Document image orientation detection and correction.
|
|
5
|
-
Project-URL: Homepage, https://github.com/
|
|
6
|
-
Project-URL: Repository, https://github.com/
|
|
7
|
-
Project-URL: Issues, https://github.com/
|
|
5
|
+
Project-URL: Homepage, https://github.com/lucasleirbag/DocOrient
|
|
6
|
+
Project-URL: Repository, https://github.com/lucasleirbag/DocOrient
|
|
7
|
+
Project-URL: Issues, https://github.com/lucasleirbag/DocOrient/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/lucasleirbag/DocOrient/blob/main/CHANGELOG.md
|
|
8
9
|
Author: Lucas Gabriel Vaz
|
|
9
10
|
License-Expression: MIT
|
|
10
11
|
License-File: LICENSE
|
|
@@ -6,21 +6,24 @@
|
|
|
6
6
|
src/docorient/
|
|
7
7
|
├── __init__.py Public API re-exports
|
|
8
8
|
├── _version.py Version string
|
|
9
|
-
├── _imaging.py
|
|
9
|
+
├── _imaging.py ImageIO class for image operations
|
|
10
10
|
├── config.py OrientationConfig dataclass
|
|
11
11
|
├── types.py Result dataclasses
|
|
12
12
|
├── exceptions.py Exception hierarchy
|
|
13
|
+
├── rotation.py Image rotation utility
|
|
14
|
+
├── voting.py Majority voting logic
|
|
13
15
|
├── correction.py correct_image, correct_document_pages
|
|
14
16
|
├── cli.py CLI entry point
|
|
15
17
|
├── detection/
|
|
16
|
-
│ ├── __init__.py Re-exports
|
|
17
|
-
│ ├──
|
|
18
|
-
│ ├──
|
|
19
|
-
│
|
|
18
|
+
│ ├── __init__.py Re-exports detection API
|
|
19
|
+
│ ├── base.py DetectionEngine Protocol
|
|
20
|
+
│ ├── engine.py DetectionPipeline orchestrator
|
|
21
|
+
│ ├── primary.py PrimaryEngine (90°/270°)
|
|
22
|
+
│ └── secondary.py SecondaryEngine (180°)
|
|
20
23
|
└── batch/
|
|
21
24
|
├── __init__.py Re-exports process_directory
|
|
22
25
|
├── scanner.py Directory scanning and grouping
|
|
23
|
-
├── worker.py
|
|
26
|
+
├── worker.py WorkerContext and multiprocessing logic
|
|
24
27
|
└── processor.py Batch orchestrator with resume and progress
|
|
25
28
|
```
|
|
26
29
|
|
|
@@ -30,17 +33,22 @@ src/docorient/
|
|
|
30
33
|
detect_orientation()
|
|
31
34
|
│
|
|
32
35
|
▼
|
|
33
|
-
|
|
36
|
+
DetectionPipeline.run()
|
|
37
|
+
Iterates through list[DetectionEngine]
|
|
38
|
+
│
|
|
39
|
+
▼
|
|
40
|
+
PrimaryEngine.detect()
|
|
34
41
|
Analyzes pixel density distribution to determine text alignment.
|
|
35
42
|
│
|
|
36
43
|
├── angle ∈ {90, 270} ──► Return result immediately
|
|
37
44
|
│
|
|
38
|
-
└── angle = 0 (aligned) ──►
|
|
45
|
+
└── angle = 0 (aligned) ──► SecondaryEngine.detect()
|
|
46
|
+
│
|
|
47
|
+
is_available()?
|
|
39
48
|
│
|
|
40
49
|
Yes ─────────┴───────── No
|
|
41
50
|
▼ ▼
|
|
42
|
-
|
|
43
|
-
(detection/secondary.py)
|
|
51
|
+
Runs secondary analysis Return 0° (no change)
|
|
44
52
|
Checks for 180° inversion
|
|
45
53
|
with confidence scoring
|
|
46
54
|
│
|
|
@@ -51,27 +59,52 @@ Analyzes pixel density distribution to determine text alignment.
|
|
|
51
59
|
Return 180° Return 0°
|
|
52
60
|
```
|
|
53
61
|
|
|
62
|
+
## Engine Architecture
|
|
63
|
+
|
|
64
|
+
The detection system is built on a `DetectionEngine` Protocol:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
DetectionEngine (Protocol)
|
|
68
|
+
├── name: str
|
|
69
|
+
└── detect(image, config) → OrientationResult | None
|
|
70
|
+
|
|
71
|
+
PrimaryEngine implements DetectionEngine
|
|
72
|
+
├── Always returns OrientationResult (never None)
|
|
73
|
+
└── Detects 0°, 90°, 270° via energy analysis
|
|
74
|
+
|
|
75
|
+
SecondaryEngine implements DetectionEngine
|
|
76
|
+
├── Returns None when unavailable or low confidence
|
|
77
|
+
└── Detects 180° via optional OCR dependency
|
|
78
|
+
|
|
79
|
+
DetectionPipeline
|
|
80
|
+
├── Holds list[DetectionEngine] (default: [PrimaryEngine(), SecondaryEngine()])
|
|
81
|
+
└── Executes engines in sequence with short-circuit logic
|
|
82
|
+
```
|
|
83
|
+
|
|
54
84
|
## Batch Processing Pipeline
|
|
55
85
|
|
|
56
86
|
```
|
|
57
87
|
process_directory()
|
|
58
88
|
│
|
|
59
89
|
▼
|
|
90
|
+
_resolve_output_directory()
|
|
91
|
+
Resolves explicit path or generates UUID
|
|
92
|
+
│
|
|
93
|
+
▼
|
|
60
94
|
scan_directory() ← scanner.py
|
|
61
95
|
Groups images by
|
|
62
96
|
source document name
|
|
63
97
|
│
|
|
64
98
|
▼
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
│
|
|
68
|
-
▼
|
|
69
|
-
Distribute pending
|
|
70
|
-
sources into N batches ← N = effective_workers
|
|
99
|
+
_filter_pending_sources()
|
|
100
|
+
Loads resume log, skips completed
|
|
71
101
|
│
|
|
72
102
|
▼
|
|
73
|
-
|
|
103
|
+
_run_parallel_processing()
|
|
74
104
|
┌─────────────────────────────────────┐
|
|
105
|
+
│ multiprocessing.Pool │
|
|
106
|
+
│ WorkerContext encapsulates state │
|
|
107
|
+
│ │
|
|
75
108
|
│ For each source in batch: │
|
|
76
109
|
│ 1. Run detection per page │
|
|
77
110
|
│ 2. Apply majority voting │
|
|
@@ -93,12 +126,12 @@ Majority voting resolves this:
|
|
|
93
126
|
2. Find the most common angle (`Counter.most_common`)
|
|
94
127
|
3. Override any unreliable detection that differs from the majority
|
|
95
128
|
|
|
96
|
-
Implemented in `
|
|
129
|
+
Implemented in `voting.apply_majority_voting()`, reused by both
|
|
97
130
|
`correct_document_pages()` and `batch/worker._process_single_source()`.
|
|
98
131
|
|
|
99
132
|
## Multiprocessing Design
|
|
100
133
|
|
|
101
|
-
- **
|
|
134
|
+
- **WorkerContext dataclass** encapsulates all shared state in a single object
|
|
102
135
|
- **Progress tracking** via `multiprocessing.Value` + `multiprocessing.Lock`
|
|
103
136
|
- **Resume log** written atomically per source file, protected by the shared lock
|
|
104
137
|
- **`maxtasksperchild=1`** prevents memory accumulation in long jobs
|
|
@@ -28,9 +28,8 @@ ruff check src/ tests/ --fix
|
|
|
28
28
|
- No comments — code must be self-explanatory through naming
|
|
29
29
|
- Descriptive variable names — never single-letter variables in non-trivial scopes
|
|
30
30
|
- Full type hints on all function signatures
|
|
31
|
-
- Docstrings only on public API functions
|
|
32
31
|
- Functions must do exactly one thing, max ~30 lines of logic
|
|
33
|
-
-
|
|
32
|
+
- Configuration is always passed as a parameter
|
|
34
33
|
|
|
35
34
|
## Publishing a New Version
|
|
36
35
|
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "docorient"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.2"
|
|
8
8
|
description = "Document image orientation detection and correction."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -37,9 +37,10 @@ dev = ["pytest >= 8.0", "pytest-cov", "ruff >= 0.4", "build", "twine"]
|
|
|
37
37
|
docorient = "docorient.cli:main"
|
|
38
38
|
|
|
39
39
|
[project.urls]
|
|
40
|
-
Homepage = "https://github.com/
|
|
41
|
-
Repository = "https://github.com/
|
|
42
|
-
Issues = "https://github.com/
|
|
40
|
+
Homepage = "https://github.com/lucasleirbag/DocOrient"
|
|
41
|
+
Repository = "https://github.com/lucasleirbag/DocOrient"
|
|
42
|
+
Issues = "https://github.com/lucasleirbag/DocOrient/issues"
|
|
43
|
+
Changelog = "https://github.com/lucasleirbag/DocOrient/blob/main/CHANGELOG.md"
|
|
43
44
|
|
|
44
45
|
[tool.hatch.build.targets.wheel]
|
|
45
46
|
packages = ["src/docorient"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.3.2"
|
docorient-0.3.1/CHANGELOG.md
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
## 0.2.0 (2026-02-26)
|
|
4
|
-
|
|
5
|
-
- **Breaking:** renamed config params `osd_confidence_threshold` → `secondary_confidence_threshold`, `max_osd_dimension` → `secondary_max_dimension`, `projection_target_dimension` → `primary_max_dimension`
|
|
6
|
-
- **Breaking:** renamed CLI flag `--no-ocr` → `--no-secondary`
|
|
7
|
-
- Internal engines renamed to `primary` and `secondary` — no external algorithm references
|
|
8
|
-
- Updated `OrientationResult.method` trace strings to `primary(...)` and `secondary(...)`
|
|
9
|
-
|
|
10
|
-
## 0.1.1 (2026-02-26)
|
|
11
|
-
|
|
12
|
-
- Docs: added `if __name__ == "__main__":` note for `process_directory` on macOS/Windows
|
|
13
|
-
|
|
14
|
-
## 0.1.0 (2026-02-25)
|
|
15
|
-
|
|
16
|
-
- Initial release
|
|
17
|
-
- Projection profile engine for 90°/270° detection
|
|
18
|
-
- Optional Tesseract OSD engine for 180° detection
|
|
19
|
-
- Single image and batch directory processing
|
|
20
|
-
- Multi-page majority voting
|
|
21
|
-
- Resumable batch processing
|
|
22
|
-
- CLI interface
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.3.1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|