feat: iterative projection-profile deskew (2-phase variance optimization)
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 25s
CI / test-go-edu-search (push) Successful in 27s
CI / test-python-klausur (push) Failing after 1m53s
CI / test-python-agent-core (push) Successful in 18s
CI / test-nodejs-website (push) Successful in 17s
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 25s
CI / test-go-edu-search (push) Successful in 27s
CI / test-python-klausur (push) Failing after 1m53s
CI / test-python-agent-core (push) Successful in 18s
CI / test-nodejs-website (push) Successful in 17s
Adds deskew_image_iterative() as 3rd deskew method that directly optimizes for projection-profile sharpness instead of proxy signals (Hough/word alignment). Coarse sweep on horizontal profile, fine sweep on vertical profile. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -52,6 +52,7 @@ from cv_vocab_pipeline import (
|
||||
create_ocr_image,
|
||||
deskew_image,
|
||||
deskew_image_by_word_alignment,
|
||||
deskew_image_iterative,
|
||||
detect_column_geometry,
|
||||
detect_document_type,
|
||||
detect_row_geometry,
|
||||
@@ -485,10 +486,23 @@ async def auto_deskew(session_id: str):
|
||||
logger.warning(f"Word alignment deskew failed: {e}")
|
||||
deskewed_wa_bytes, angle_wa = orig_bytes, 0.0
|
||||
|
||||
# Method 3: Iterative Projection-Profile
|
||||
angle_iterative = 0.0
|
||||
iterative_debug = {}
|
||||
try:
|
||||
deskewed_iter, angle_iterative, iterative_debug = deskew_image_iterative(img_bgr.copy())
|
||||
except Exception as e:
|
||||
logger.warning(f"Iterative deskew failed: {e}")
|
||||
deskewed_iter = img_bgr
|
||||
|
||||
duration = time.time() - t0
|
||||
|
||||
# Pick best method
|
||||
if abs(angle_wa) >= abs(angle_hough) or abs(angle_hough) < 0.1:
|
||||
# Pick best method — prefer iterative when it found a non-zero angle
|
||||
if abs(angle_iterative) >= 0.05:
|
||||
method_used = "iterative"
|
||||
angle_applied = angle_iterative
|
||||
deskewed_bgr = deskewed_iter
|
||||
elif abs(angle_wa) >= abs(angle_hough) or abs(angle_hough) < 0.1:
|
||||
method_used = "word_alignment"
|
||||
angle_applied = angle_wa
|
||||
wa_array = np.frombuffer(deskewed_wa_bytes, dtype=np.uint8)
|
||||
@@ -520,6 +534,7 @@ async def auto_deskew(session_id: str):
|
||||
deskew_result = {
|
||||
"angle_hough": round(angle_hough, 3),
|
||||
"angle_word_alignment": round(angle_wa, 3),
|
||||
"angle_iterative": round(angle_iterative, 3),
|
||||
"angle_applied": round(angle_applied, 3),
|
||||
"method_used": method_used,
|
||||
"confidence": round(confidence, 2),
|
||||
@@ -542,7 +557,8 @@ async def auto_deskew(session_id: str):
|
||||
await update_session_db(session_id, **db_update)
|
||||
|
||||
logger.info(f"OCR Pipeline: deskew session {session_id}: "
|
||||
f"hough={angle_hough:.2f} wa={angle_wa:.2f} -> {method_used} {angle_applied:.2f}")
|
||||
f"hough={angle_hough:.2f} wa={angle_wa:.2f} iter={angle_iterative:.2f} "
|
||||
f"-> {method_used} {angle_applied:.2f}")
|
||||
|
||||
await _append_pipeline_log(session_id, "deskew", {
|
||||
"angle_applied": round(angle_applied, 3),
|
||||
|
||||
Reference in New Issue
Block a user