准备 - core:内置官方字符集(OLD/BETA)与 ModelMetadata::from_builtin_* 构造器 - ort:导出 Session、实现 Info、修正 cuda feature 接线、共享推理工具 - tract2:包名更名(原 ddddocr-tract 已被占用)并完成规范整改 - 集成测试按领域拆分(ocr / det / slide / common / api_surface) - 发布准备:Cargo.toml 元数据、workspace 版本 0.2.4、LICENSE/ NOTICE、README 模型下载说明
192 lines
5.7 KiB
Rust
192 lines
5.7 KiB
Rust
//! 分层错误类型:预处理、推理、解码三阶段的强类型错误。
|
|
|
|
use thiserror::Error;
|
|
|
|
/// 全局统一的 `Result` 别名,默认错误类型为 [`DdddError`]。
|
|
pub type Result<T, E = DdddError> = std::result::Result<T, E>;
|
|
|
|
/// 顶层错误类型,聚合本库各阶段错误。
|
|
#[derive(Error, Debug)]
|
|
pub enum DdddError {
|
|
/// 图像预处理阶段异常。
|
|
#[error("图像预处理失败: {0}")]
|
|
Preprocess(#[from] ImagePreprocessError),
|
|
|
|
/// 推理与张量操作阶段异常。
|
|
#[error("推理与模型输入/输出张量异常: {0}")]
|
|
Inference(#[from] TensorError),
|
|
|
|
/// 后处理解码阶段异常。
|
|
#[error("后处理解码错误: {0}")]
|
|
Decode(#[from] DecodeError),
|
|
|
|
/// 框架内部不可恢复的逻辑断言错误(如解析节点 Fact 失败)。
|
|
#[error("内部严重逻辑错误: {0}")]
|
|
Internal(String),
|
|
|
|
/// 用户自定义扩展错误,用于包装第三方插件产生的错误。
|
|
#[error("用户自定义扩展错误: {0}")]
|
|
Other(#[source] Box<dyn std::error::Error + Send + Sync>),
|
|
}
|
|
|
|
/// 图像预处理阶段错误类型。
|
|
#[derive(Error, Debug)]
|
|
pub enum ImagePreprocessError {
|
|
/// ndarray 基础操作失败。
|
|
#[error("图片转矩阵(ndarray)基础操作失败: {0}")]
|
|
Ndarray(#[from] ndarray::ShapeError),
|
|
|
|
/// 图像矩阵维度不合规。
|
|
#[error("图像矩阵维度不合规!预期: {expected},实际图像形状: {actual:?}")]
|
|
InvalidDimensions {
|
|
/// 期望的维度描述。
|
|
expected: String,
|
|
/// 实际的图像形状。
|
|
actual: Vec<usize>,
|
|
},
|
|
|
|
/// 图像缓冲区长度与分辨率/通道数不匹配。
|
|
#[error(
|
|
"图像缓冲区长度不匹配!预期大小: {expected},实际大小: {actual} (分辨率: {width}x{height}, 通道数: {channels})"
|
|
)]
|
|
BufferLengthMismatch {
|
|
/// 期望的缓冲区长度。
|
|
expected: usize,
|
|
/// 实际的缓冲区长度。
|
|
actual: usize,
|
|
/// 图像宽度。
|
|
width: u32,
|
|
/// 图像高度。
|
|
height: u32,
|
|
/// 图像通道数。
|
|
channels: usize,
|
|
},
|
|
|
|
/// 不支持的图像通道数。
|
|
#[error("不支持的图像通道数: {0} (仅支持单通道灰度L、3通道RGB、4通道RGBA)")]
|
|
UnsupportedChannels(usize),
|
|
|
|
/// HSV 颜色区间参数非法。
|
|
#[error("HSV 颜色区间参数非法: {0}")]
|
|
InvalidHsvRange(String),
|
|
|
|
/// 未知的颜色预设名称。
|
|
#[error("不支持的颜色预设名称: {0}")]
|
|
UnknownColorPreset(String),
|
|
|
|
/// 颜色过滤器配置无效。
|
|
#[error("颜色过滤器配置无效或初始化失败: {0}")]
|
|
FilterConfigInvalid(String),
|
|
|
|
/// 图像维度不匹配。
|
|
#[error("图像维度不匹配!{0}")]
|
|
MismatchDimensions(String),
|
|
|
|
/// 滑块模板尺寸大于背景图。
|
|
#[error("滑块模板尺寸 [{target_w}x{target_h}] 大于背景图 [{bg_w}x{bg_h}]")]
|
|
TargetExceedsBackground {
|
|
/// 滑块模板宽度。
|
|
target_w: usize,
|
|
/// 滑块模板高度。
|
|
target_h: usize,
|
|
/// 背景图宽度。
|
|
bg_w: usize,
|
|
/// 背景图高度。
|
|
bg_h: usize,
|
|
},
|
|
}
|
|
|
|
/// 推理与张量操作阶段错误类型。
|
|
#[derive(Error, Debug)]
|
|
pub enum TensorError {
|
|
/// 推理引擎内部异常。
|
|
#[error("推理引擎内部发生异常: {0}")]
|
|
Engine(String),
|
|
|
|
/// 模型张量维度不匹配。
|
|
#[error("模型张量维度不匹配!预期: {expected},实际 Tensor 形状: {actual:?}")]
|
|
DimensionMismatch {
|
|
/// 期望的维度描述。
|
|
expected: String,
|
|
/// 实际的 Tensor 形状。
|
|
actual: Vec<usize>,
|
|
},
|
|
|
|
/// OCR Logits 矩阵变形失败。
|
|
#[error("OCR Logits 矩阵变形失败: {0}")]
|
|
LogitsDimensionMismatch(#[from] ndarray::ShapeError),
|
|
|
|
/// 张量内存不连续。
|
|
#[error("内存不连续,无法执行零拷贝操作")]
|
|
NonContiguousMemory,
|
|
|
|
/// 未知的模型输出格式。
|
|
#[error("未知的模型输出格式")]
|
|
UnknownOutputFormat,
|
|
}
|
|
|
|
/// 算法解码阶段错误类型。
|
|
#[derive(Error, Debug)]
|
|
pub enum DecodeError {
|
|
/// CTC 解码异常。
|
|
#[error("CTC 解码异常: {0}")]
|
|
Ctc(String),
|
|
}
|
|
|
|
impl DdddError {
|
|
/// 手动包装任意第三方错误为 [`DdddError::Other`]。
|
|
pub fn new<E>(error: E) -> Self
|
|
where
|
|
E: Into<Box<dyn std::error::Error + Send + Sync>>,
|
|
{
|
|
DdddError::Other(error.into())
|
|
}
|
|
|
|
/// 是否为图片维度不合规错误。
|
|
pub fn is_invalid_dimensions(&self) -> bool {
|
|
matches!(
|
|
self,
|
|
DdddError::Preprocess(ImagePreprocessError::InvalidDimensions { .. })
|
|
)
|
|
}
|
|
|
|
/// 是否因通道数不合规而失败。
|
|
pub fn is_unsupported_channels(&self) -> bool {
|
|
matches!(
|
|
self,
|
|
DdddError::Preprocess(ImagePreprocessError::UnsupportedChannels(_))
|
|
)
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn new_wraps_third_party_error() {
|
|
let io_err = std::io::Error::other("boom");
|
|
let err = DdddError::new(io_err);
|
|
assert!(matches!(err, DdddError::Other(_)));
|
|
}
|
|
|
|
#[test]
|
|
fn preprocess_conversion_and_predicates() {
|
|
let e: DdddError = ImagePreprocessError::UnsupportedChannels(2).into();
|
|
assert!(e.is_unsupported_channels());
|
|
|
|
let e2: DdddError = ImagePreprocessError::InvalidDimensions {
|
|
expected: "x".into(),
|
|
actual: vec![0],
|
|
}
|
|
.into();
|
|
assert!(e2.is_invalid_dimensions());
|
|
}
|
|
|
|
#[test]
|
|
fn decode_conversion() {
|
|
let e: DdddError = DecodeError::Ctc("bad".into()).into();
|
|
assert!(matches!(e, DdddError::Decode(_)));
|
|
}
|
|
}
|