formula_enc_check/
formula_enc_check.rs1use std::time::Instant;
5
6use pagesift_infer::Tensor;
7use pagesift_ocr::Image;
8use pagesift_ocr::formula_enc::{Encoder, preprocess};
9
10fn read_ppm(path: &str) -> Image {
12 let b = std::fs::read(path).unwrap_or_else(|e| panic!("读 {path} 失败:{e}"));
13 let mut fields = Vec::new();
14 let mut i = 0;
15 while fields.len() < 4 {
16 while b[i].is_ascii_whitespace() {
17 i += 1;
18 }
19 if b[i] == b'#' {
20 while b[i] != b'\n' {
21 i += 1;
22 }
23 continue;
24 }
25 let s = i;
26 while !b[i].is_ascii_whitespace() {
27 i += 1;
28 }
29 fields.push(String::from_utf8_lossy(&b[s..i]).into_owned());
30 }
31 assert_eq!(fields[0], "P6", "{path} 不是 P6 PPM");
32 assert_eq!(fields[3], "255", "{path} 不是 8 位");
33 let (w, h): (usize, usize) = (fields[1].parse().unwrap(), fields[2].parse().unwrap());
34 let data = b[i + 1..i + 1 + w * h * 3].to_vec();
35 Image {
36 width: w,
37 height: h,
38 channels: 3,
39 data,
40 }
41}
42
43fn synthetic() -> Image {
45 let (w, h) = (400, 100);
46 let mut data = vec![255u8; w * h];
47 for y in 0..h {
48 for x in 0..w {
49 let bar = (20..380).contains(&x) && (48..52).contains(&y);
50 let stem = x % 60 < 4 && (15..85).contains(&y) && (20..380).contains(&x);
51 if bar || stem {
52 data[y * w + x] = 0;
53 }
54 }
55 }
56 Image {
57 width: w,
58 height: h,
59 channels: 1,
60 data,
61 }
62}
63
64fn stats(name: &str, t: &Tensor, ms: f64) {
65 let bad = t.data.iter().filter(|v| !v.is_finite()).count();
66 let (mut lo, mut hi, mut sum) = (f32::INFINITY, f32::NEG_INFINITY, 0f64);
67 for &v in t.data.iter().filter(|v| v.is_finite()) {
68 lo = lo.min(v);
69 hi = hi.max(v);
70 sum += f64::from(v);
71 }
72 let mean = sum / t.data.len().max(1) as f64;
73 println!(
74 "{name:<16} {:<16} min {lo:>10.4} max {hi:>10.4} mean {mean:>9.4} 非有限 {bad:<6} {ms:>8.1} ms",
75 format!("{:?}", t.shape)
76 );
77}
78
79fn main() {
80 let a: Vec<String> = std::env::args().skip(1).collect();
81 let t = Instant::now();
82 let enc = Encoder::load(std::path::Path::new(&a[0])).unwrap();
83 println!("载入 {:.0} ms", t.elapsed().as_secs_f64() * 1e3);
84 let img = a.get(1).map_or_else(synthetic, |p| read_ppm(p));
85 let t = Instant::now();
86 let x = preprocess(&img);
87 let pre_ms = t.elapsed().as_secs_f64() * 1e3;
88 stats("preprocess", &x, pre_ms);
89 let t0 = Instant::now();
90 let mut last = t0;
91 let m = enc
92 .encode_traced(&x, |name, t| {
93 stats(name, t, last.elapsed().as_secs_f64() * 1e3);
94 last = Instant::now();
95 })
96 .unwrap();
97 println!(
98 "编码合计 {:.0} ms,输出 {:?}",
99 t0.elapsed().as_secs_f64() * 1e3,
100 m.shape
101 );
102 let t = Instant::now();
104 let m2 = enc.encode(&x).unwrap();
105 println!("第二次编码 {:.0} ms", t.elapsed().as_secs_f64() * 1e3);
106 assert_eq!(m.data, m2.data, "两次编码结果应逐位相同");
107}