Skip to main content

pagesift_ocr/
lib.rs

1//! 扫描页 OCR:PP-OCRv6 的文字检测(DB)和文字识别(SVTR + CTC),纯 Rust,CPU 或 N 卡上跑
2//! (设备见 [`device`],GPU 不可用时自动退回 CPU 并报告原因)。
3//! 权重是 PaddlePaddle 在 Hugging Face 上发布的 safetensors(Apache-2.0),首次使用时下载
4//! (见 [`models`]),不随本仓库分发。
5//!
6//! 流程:整页图 → [`det::Det::detect`] 得到文字行的四边形 → 逐行裁出、拉正 →
7//! [`rec::Rec::recognize`] 得到文字和置信度。
8
9pub mod det;
10pub mod device;
11pub mod formula;
12pub mod formula_enc;
13mod gpu_run;
14pub mod layout;
15pub mod lcnet;
16pub mod math;
17pub mod models;
18pub mod pdf;
19pub mod pipeline;
20pub mod rec;
21mod script;
22
23pub use device::{Device, DeviceStatus, ModelChoice, Quality, select_models};
24pub use gpu_run::GpuStats;
25
26/// 一张 8 位图:灰度(1 通道)或 RGB(3 通道),按行存放、无行间填充。
27#[derive(Debug, Clone)]
28pub struct Image {
29    pub width: usize,
30    pub height: usize,
31    pub channels: usize,
32    pub data: Vec<u8>,
33}
34
35impl Image {
36    /// 取 (x, y) 处第 c 个通道;灰度图三个通道都返回同一个值。
37    #[inline]
38    pub fn at(&self, x: usize, y: usize, c: usize) -> u8 {
39        let c = if self.channels == 1 { 0 } else { c };
40        self.data[(y * self.width + x) * self.channels + c]
41    }
42}
43
44/// 图上的四边形:左上、右上、右下、左下四个角(像素坐标)。
45pub type Quad = [(f32, f32); 4];
46
47/// 识别出的一行字。
48#[derive(Debug, Clone)]
49pub struct Line {
50    pub quad: Quad,
51    pub text: String,
52    /// 识别置信度(CTC 各字的概率平均),0–1。
53    pub score: f32,
54    /// 行间公式:`text` 是 `$$…$$`。
55    pub formula: bool,
56}
57
58/// 读模型目录下的 config.json。
59pub(crate) fn read_json(dir: &std::path::Path, name: &str) -> Result<serde_json::Value, String> {
60    let p = dir.join(name);
61    let s = std::fs::read(&p).map_err(|e| format!("reading {}: {e}", p.display()))?;
62    serde_json::from_slice(&s).map_err(|e| format!("{} is not valid JSON: {e}", p.display()))
63}
64
65/// 读模型目录下的 model.safetensors。
66pub(crate) fn read_weights(dir: &std::path::Path) -> Result<pagesift_infer::Weights, String> {
67    let p = dir.join("model.safetensors");
68    let b = std::fs::read(&p).map_err(|e| format!("reading {}: {e}", p.display()))?;
69    pagesift_infer::Weights::from_bytes(&b)
70}