Add double-page spread detection to frontend pipeline
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 36s
CI / test-go-edu-search (push) Successful in 34s
CI / test-python-klausur (push) Failing after 2m0s
CI / test-python-agent-core (push) Successful in 17s
CI / test-nodejs-website (push) Successful in 18s

After orientation detection, the frontend now automatically calls the
page-split endpoint. When a double-page book spread is detected, two
sub-sessions are created and each goes through the full pipeline
(deskew/dewarp/crop) independently — essential because each page of a
spread tilts differently due to the spine.

Frontend changes:
- StepOrientation: calls POST /page-split after orientation, shows
  split info ("Doppelseite erkannt"), notifies parent of sub-sessions
- page.tsx: distinguishes page-split sub-sessions (current_step < 5)
  from crop-based sub-sessions (current_step >= 5). Page-split subs
  only skip orientation, not deskew/dewarp/crop.
- page.tsx: handleOrientationComplete opens first sub-session when
  page-split was detected

Backend changes (orientation_crop_api.py):
- page-split endpoint falls back to original image when orientation
  rotated a landscape spread to portrait
- start_step parameter: 1 if split from original, 2 if from oriented

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Benjamin Admin
2026-03-24 11:09:44 +01:00
parent 40815dafd1
commit 247b79674d
3 changed files with 115 additions and 19 deletions

View File

@@ -92,15 +92,24 @@ export default function OcrPipelinePage() {
let uiStep = Math.max(0, dbStep - 1)
const skipSteps = [...(savedDocType?.skip_steps || [])]
// Sub-sessions: image is already cropped, skip pre-processing steps
// Jump directly to columns (UI step 4) unless already further ahead
// Sub-session handling depends on how they were created:
// - Crop-based (current_step >= 5): image already cropped, skip all pre-processing
// - Page-split (current_step 2): orientation done on parent, skip only orientation
// - Page-split from original (current_step 1): needs full pipeline
const isSubSession = !!data.parent_session_id
const SUB_SESSION_SKIP = ['orientation', 'deskew', 'dewarp', 'crop']
if (isSubSession) {
for (const s of SUB_SESSION_SKIP) {
if (!skipSteps.includes(s)) skipSteps.push(s)
if (dbStep >= 5) {
// Crop-based sub-sessions: image already cropped
const SUB_SESSION_SKIP = ['orientation', 'deskew', 'dewarp', 'crop']
for (const s of SUB_SESSION_SKIP) {
if (!skipSteps.includes(s)) skipSteps.push(s)
}
if (uiStep < 4) uiStep = 4 // columns step (index 4)
} else if (dbStep >= 2) {
// Page-split sub-session: parent orientation applied, skip only orientation
if (!skipSteps.includes('orientation')) skipSteps.push('orientation')
}
if (uiStep < 4) uiStep = 4 // columns step (index 4)
// dbStep === 1: page-split from original image, needs full pipeline
}
setSteps(
@@ -245,6 +254,13 @@ export default function OcrPipelinePage() {
setSessionId(sid)
// Reload session list to show the new session
loadSessions()
// If page-split created sub-sessions, open the first one
if (subSessions.length > 0) {
openSession(subSessions[0].id, true)
return
}
handleNext()
}
@@ -365,7 +381,7 @@ export default function OcrPipelinePage() {
const renderStep = () => {
switch (currentStep) {
case 0:
return <StepOrientation sessionId={sessionId} onNext={handleOrientationComplete} />
return <StepOrientation sessionId={sessionId} onNext={handleOrientationComplete} onSubSessionsCreated={handleBoxSessionsCreated} />
case 1:
return <StepDeskew sessionId={sessionId} onNext={handleNext} />
case 2: