Skip to content

Commit 85de96a

Browse files
committed
Fix OpenVino/ONNX verification
1 parent 0f894d2 commit 85de96a

2 files changed

Lines changed: 91 additions & 41 deletions

File tree

src/bigocrpdf/services/rapidocr_service/backend.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,8 @@ def _init_engine(self):
289289
"Rec.model_path": str(rec_model) if rec_model else None,
290290
"Rec.rec_keys_path": str(rec_keys) if rec_keys else None,
291291
"Rec.rec_batch_num": 8, # Batch more recognition requests for throughput
292+
# === Classifier settings (use same engine even if disabled) ===
293+
"Cls.engine_type": effective_engine_type,
292294
# === Global settings ===
293295
"Global.font_path": str(font_path) if font_path else None,
294296
"Global.use_cls": False, # Disable classifier (causes alignment issues)

src/bigocrpdf/services/rapidocr_service/ocr_worker.py

Lines changed: 89 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ def run_ocr_batch(
6868
if use_openvino:
6969
params["Det.engine_type"] = EngineType.OPENVINO
7070
params["Rec.engine_type"] = EngineType.OPENVINO
71+
params["Cls.engine_type"] = EngineType.OPENVINO
7172

7273
rapid = RapidOCR(params=params)
7374

@@ -189,6 +190,8 @@ def run_ocr_full(
189190
"Rec.lang_type": lang_rec,
190191
"Rec.ocr_version": OCRVersion.PPOCRV5,
191192
"Rec.rec_batch_num": 8,
193+
# Classifier settings (use same engine even if disabled)
194+
"Cls.engine_type": engine_type,
192195
# Global settings
193196
"Global.use_cls": False,
194197
"Global.text_score": text_score,
@@ -255,10 +258,13 @@ def _create_ocr_engine(
255258
font_path: str = "",
256259
threads: int = 4,
257260
) -> object:
258-
"""Create a RapidOCR engine with full parameters.
261+
"""Create a RapidOCR engine with full parameters and fallback support.
259262
260263
This factory is shared by all OCR modes (single, batch, persistent)
261264
to ensure consistent parameter handling.
265+
266+
Includes fallback logic: if the primary engine fails to initialize,
267+
it will try the alternative engine (OpenVINO ↔ ONNX Runtime).
262268
"""
263269
try:
264270
from rapidocr import EngineType, LangRec, OCRVersion, RapidOCR
@@ -281,51 +287,93 @@ def _create_ocr_engine(
281287
}
282288
lang_rec = lang_map.get(language, LangRec.LATIN)
283289

284-
engine_type = EngineType.OPENVINO if use_openvino else EngineType.ONNXRUNTIME
290+
def _build_params(engine_type, use_openvino_threads: bool):
291+
"""Build parameter dict for the given engine type."""
292+
p = {
293+
"Det.engine_type": engine_type,
294+
"Det.box_thresh": box_thresh,
295+
"Det.unclip_ratio": unclip_ratio,
296+
"Det.score_mode": score_mode,
297+
"Det.limit_side_len": limit_side_len,
298+
"Det.limit_type": "max",
299+
"Rec.engine_type": engine_type,
300+
"Rec.lang_type": lang_rec,
301+
"Rec.ocr_version": OCRVersion.PPOCRV5,
302+
"Rec.rec_batch_num": 8,
303+
# Classifier settings (use same engine even if disabled)
304+
"Cls.engine_type": engine_type,
305+
"Global.use_cls": False,
306+
"Global.text_score": text_score,
307+
"Global.max_side_len": limit_side_len,
308+
}
285309

286-
params = {
287-
"Det.engine_type": engine_type,
288-
"Det.box_thresh": box_thresh,
289-
"Det.unclip_ratio": unclip_ratio,
290-
"Det.score_mode": score_mode,
291-
"Det.limit_side_len": limit_side_len,
292-
"Det.limit_type": "max",
293-
"Rec.engine_type": engine_type,
294-
"Rec.lang_type": lang_rec,
295-
"Rec.ocr_version": OCRVersion.PPOCRV5,
296-
"Rec.rec_batch_num": 8,
297-
"Global.use_cls": False,
298-
"Global.text_score": text_score,
299-
"Global.max_side_len": limit_side_len,
300-
}
310+
if use_openvino_threads:
311+
p.update(
312+
{
313+
"Det.engine_cfg.inference_num_threads": threads,
314+
"Rec.engine_cfg.inference_num_threads": threads,
315+
}
316+
)
317+
else:
318+
p.update(
319+
{
320+
"Det.engine_cfg.intra_op_num_threads": threads,
321+
"Det.engine_cfg.inter_op_num_threads": 2,
322+
"Rec.engine_cfg.intra_op_num_threads": threads,
323+
"Rec.engine_cfg.inter_op_num_threads": 2,
324+
}
325+
)
301326

327+
if rec_model_path:
328+
p["Rec.model_path"] = rec_model_path
329+
if rec_keys_path:
330+
p["Rec.rec_keys_path"] = rec_keys_path
331+
if det_model_path:
332+
p["Det.model_path"] = det_model_path
333+
if font_path and os.path.exists(font_path):
334+
p["Global.font_path"] = font_path
335+
336+
return p
337+
338+
# Determine primary and fallback engine types
302339
if use_openvino:
303-
params.update(
304-
{
305-
"Det.engine_cfg.inference_num_threads": threads,
306-
"Rec.engine_cfg.inference_num_threads": threads,
307-
}
308-
)
340+
primary_engine = EngineType.OPENVINO
341+
fallback_engine = EngineType.ONNXRUNTIME
342+
primary_name = "OpenVINO"
343+
fallback_name = "ONNX Runtime"
309344
else:
310-
params.update(
311-
{
312-
"Det.engine_cfg.intra_op_num_threads": threads,
313-
"Det.engine_cfg.inter_op_num_threads": 2,
314-
"Rec.engine_cfg.intra_op_num_threads": threads,
315-
"Rec.engine_cfg.inter_op_num_threads": 2,
316-
}
317-
)
318-
319-
if rec_model_path:
320-
params["Rec.model_path"] = rec_model_path
321-
if rec_keys_path:
322-
params["Rec.rec_keys_path"] = rec_keys_path
323-
if det_model_path:
324-
params["Det.model_path"] = det_model_path
325-
if font_path and os.path.exists(font_path):
326-
params["Global.font_path"] = font_path
345+
primary_engine = EngineType.ONNXRUNTIME
346+
fallback_engine = EngineType.OPENVINO
347+
primary_name = "ONNX Runtime"
348+
fallback_name = "OpenVINO"
327349

328-
return RapidOCR(params=params)
350+
# Try primary engine first
351+
try:
352+
params = _build_params(primary_engine, use_openvino)
353+
return RapidOCR(params=params)
354+
except Exception as primary_err:
355+
primary_msg = str(primary_err).lower()
356+
# Check if this is a "not installed" error that warrants fallback
357+
if "not installed" in primary_msg or "no module" in primary_msg or "import" in primary_msg:
358+
import sys
359+
360+
print(f"[OCR Worker] {primary_name} failed: {primary_err}", file=sys.stderr)
361+
print(f"[OCR Worker] Trying fallback to {fallback_name}...", file=sys.stderr)
362+
363+
# Try fallback engine
364+
try:
365+
params = _build_params(fallback_engine, not use_openvino)
366+
return RapidOCR(params=params)
367+
except Exception as fallback_err:
368+
# Both engines failed
369+
raise RuntimeError(
370+
f"Both OCR engines failed.\n"
371+
f"{primary_name}: {primary_err}\n"
372+
f"{fallback_name}: {fallback_err}"
373+
) from fallback_err
374+
else:
375+
# Not an installation error, re-raise
376+
raise
329377

330378

331379
def _ocr_single_image(

0 commit comments

Comments
 (0)