pub mod engine;
pub mod error;
pub(crate) mod inference_timings;
mod model_manager;
pub mod models;
pub mod postprocessing;
pub mod preprocessing;
pub mod session;
pub mod types;
pub use engine::{CustomModelVariant, DetectTimings, LayoutEngine, LayoutEngineConfig, LayoutPreset, ModelBackend};
pub use error::LayoutError;
pub use model_manager::LayoutModelManager;
pub use models::LayoutModel;
pub use models::rtdetr::RtDetrModel;
pub use models::yolo::{YoloModel, YoloVariant};
pub use types::{BBox, DetectionResult, LayoutClass, LayoutDetection};
use std::sync::OnceLock;
use crate::core::config::layout::LayoutDetectionConfig;
use crate::model_cache::ModelCache;
static CACHED_ENGINE: ModelCache<LayoutEngine> = ModelCache::new();
static CACHED_TATR: ModelCache<models::tatr::TatrModel> = ModelCache::new();
static TATR_TRIED: OnceLock<bool> = OnceLock::new();
pub fn config_from_extraction(layout_config: &LayoutDetectionConfig) -> LayoutEngineConfig {
let preset: LayoutPreset = layout_config.preset.parse().unwrap_or_else(|_| {
tracing::warn!(
preset = %layout_config.preset,
"unrecognized layout preset, falling back to 'accurate'"
);
LayoutPreset::Accurate
});
let mut engine_config = LayoutEngineConfig::from_preset(preset);
engine_config.confidence_threshold = layout_config.confidence_threshold;
engine_config.apply_heuristics = layout_config.apply_heuristics;
engine_config
}
pub fn create_engine(layout_config: &LayoutDetectionConfig) -> Result<LayoutEngine, LayoutError> {
crate::ort_discovery::ensure_ort_available();
let config = config_from_extraction(layout_config);
LayoutEngine::from_config(config)
}
pub fn take_or_create_engine(layout_config: &LayoutDetectionConfig) -> Result<LayoutEngine, LayoutError> {
CACHED_ENGINE.take_or_create(|| create_engine(layout_config))
}
pub fn return_engine(engine: LayoutEngine) {
CACHED_ENGINE.put(engine);
}
pub fn take_or_create_tatr() -> Option<models::tatr::TatrModel> {
if let Some(&false) = TATR_TRIED.get() {
return None;
}
let result = CACHED_TATR.take_or_create(|| {
crate::ort_discovery::ensure_ort_available();
let manager = LayoutModelManager::new(None);
let model_path = manager.ensure_tatr_model()?;
models::tatr::TatrModel::from_file(&model_path.to_string_lossy())
});
match result {
Ok(model) => {
TATR_TRIED.get_or_init(|| true);
Some(model)
}
Err(e) => {
TATR_TRIED.get_or_init(|| {
tracing::warn!("TATR table structure model unavailable, table structure recognition disabled: {e}");
false
});
None
}
}
}
pub fn return_tatr(model: models::tatr::TatrModel) {
CACHED_TATR.put(model);
}