Detect and confirm page orientation during automatic splitting

Bundle the trained heatmap/image orientation model and run it after provisional
blank-page and split analysis. Confirm candidates with Gemini using low thinking;
resolve mixed A3 sheet ordering with the complete statement and medium thinking.
Keep A4 scans independent and export paired A3 scans in booklet reading order.

Reanalyse uniformly inverted source sheets, validate ordering permutations, and
preserve source provenance, corrected rotations and reading slots in manual review.
Document the experiments, rejected approaches, calibration and runtime limits.

Validation: focused splitting/orientation regression suites pass; bundled model
checksum and wheel assets verified. Full Interro07 offline run: 44.26 seconds,
eight candidates, mocked upright confirmations, source hashes and geometry intact.
This commit is contained in:
sebastien committed 2026-11-04 21:07:20 +01:00
1 parent 78f3e4b2f0
commit 0a4f4a80d0
21 files changed
+1574 -51

No files matched your search

@@ -0,0 +1,139 @@
{
"profiles": {
"balanced": {
"threshold": 0.17323015873015868,
"calibration_false_alarm_target": 0.02,
"selection": "frozen before holdout",
"metrics": {
"Interro04": {
"tp": 373,
"fp": 19,
"pages": 373
},
"Interro07": {
"tp": 346,
"fp": 16,
"pages": 347
}
}
},
"conservative": {
"threshold": 0.3044920634920634,
"calibration_false_alarm_target": 0.01,
"selection": "fallback policy evaluated after balanced holdout result; numeric threshold determined solely from Interro06",
"metrics": {
"Interro04": {
"tp": 371,
"fp": 11,
"pages": 373
},
"Interro07": {
"tp": 345,
"fp": 6,
"pages": 347
}
}
}
},
"training": {
"design": {
"training": [
"Interro01",
"Interro02",
"Interro03",
"Interro05"
],
"calibration": [
"Interro06"
],
"holdout": [
"Interro04"
],
"secondary": [
"Interro07"
],
"architecture": "RBF SVM C=3 multi-heatmaps + ExtraTrees 200 trees, min_samples_leaf=5, seed514; neural four views; fusion learns leave-one-training-exam-out heat scores",
"calibration_false_alarm_target": 0.02
},
"threshold": 0.17323015873015868,
"heatmap_threshold": -0.1468564601978186,
"training_pages": 1652,
"calibration_pages": 390,
"cross_fit": {
"Interro01": {
"fit_pages": 1260,
"heldout_pages": 392
},
"Interro02": {
"fit_pages": 1229,
"heldout_pages": 423
},
"Interro03": {
"fit_pages": 1221,
"heldout_pages": 431
},
"Interro05": {
"fit_pages": 1246,
"heldout_pages": 406
}
},
"training_seconds": 20.764557278016582,
"model_sha256": "24b1174480856a4b74111b8e13f0354ce039a1317ac6fe8168465731d105991b",
"feature_sha256": "c6163df45ca7e6daa9e78e303a91199c6cc03e6c51f3bd177e07e723de767c89"
},
"input": "75 dpi, RGB uint8, uncropped logical A4 page after respecting PDF rotation",
"confirmation": "Confirm flagged pages before rotating; blank or unreadable pages can remain unresolved.",
"direct_rotation_validation": {
"metrics": {
"balanced": {
"Interro04": {
"tp": 373,
"fp": 19,
"pages": 373
},
"Interro07": {
"tp": 346,
"fp": 16,
"pages": 347
}
},
"conservative": {
"Interro04": {
"tp": 372,
"fp": 11,
"pages": 373
},
"Interro07": {
"tp": 345,
"fp": 6,
"pages": 347
}
}
},
"timings": {
"Interro04": {
"rotated_screen_seconds": 15.020227690052707,
"load_and_rotate_seconds": 1.9645465558278374,
"pages": 373
},
"Interro07": {
"rotated_screen_seconds": 13.592888371145818,
"load_and_rotate_seconds": 3.4222886104835197,
"pages": 347
}
}
},
"integrated_validation": {
"balanced": {
"tp": 346,
"fp": 22,
"pages": 347
},
"conservative": {
"tp": 345,
"fp": 8,
"pages": 347
}
},
"full_split_seconds": 50.92064940801356
}