pub struct TableFormer { /* private fields */ }Implementations§
Source§impl TableFormer
impl TableFormer
Sourcepub fn load() -> Option<Self>
pub fn load() -> Option<Self>
Load the exported encoder/decoder/bbox ONNX graphs (env overrides, else
models/tableformer/{encoder,decoder,bbox}.onnx). Returns None if any is
absent, so the pipeline falls back to geometric reconstruction.
Examples found in repository?
24fn main() {
25 let path = std::env::args().nth(1).expect("usage: tf_otsl <pdf>");
26 let bytes = std::fs::read(&path).expect("read");
27 let doc = PdfDocument::open(&bytes, None).expect("open");
28 let mut layout = LayoutModel::load().expect("layout");
29 let mut tf = TableFormer::load().expect("tableformer models missing");
30 for (pi, page) in doc.pages.iter().enumerate() {
31 let regions = layout
32 .predict(&page.image, page.width, page.height)
33 .expect("layout");
34 // docling resizes the whole page to 1024px height (cv2.INTER_AREA), then
35 // crops the table bbox out of *that*. Replicate exactly.
36 let sf = 1024.0 / page.image.height() as f32;
37 let pw1024 = (page.image.width() as f32 * sf) as u32; // docling: int(w*r)
38 let page1024 = fleischwolf_pdf::resample::inter_area(&page.image, pw1024, 1024);
39 for r in regions.iter().filter(|r| r.label == "table") {
40 // bbox (points) → 1024px-page coords: scale*sf = 1024/page_h_pt;
41 // docling rounds the crop edges.
42 let k = 1024.0 / page.height;
43 let x = (r.l * k).round().max(0.0) as u32;
44 let y = (r.t * k).round().max(0.0) as u32;
45 let x2 = (r.r * k).round() as u32;
46 let y2 = (r.b * k).round() as u32;
47 let (w, h) = (x2 - x, y2 - y);
48 let crop = imageops::crop_imm(&page1024, x, y, w, h).to_image();
49 let cells = tf.predict_table_structure(&crop).expect("predict");
50 println!(
51 "page {} table {}x{}px -> {} cells",
52 pi + 1,
53 w,
54 h,
55 cells.len()
56 );
57 for c in &cells {
58 println!(
59 " r{} c{} {}x{} {} | cxcywh {:.4} {:.4} {:.4} {:.4}",
60 c.row,
61 c.col,
62 c.colspan,
63 c.rowspan,
64 name(c.tag),
65 c.cx,
66 c.cy,
67 c.w,
68 c.h
69 );
70 }
71 }
72 }
73}Sourcepub fn load_with(intra: usize) -> Option<Self>
pub fn load_with(intra: usize) -> Option<Self>
Like load but with an explicit intra-op thread count, so a
parallel page-worker pool can run each table model on fewer threads (the
throughput comes from running pages concurrently, not from one fat model).
Sourcepub fn predict_otsl(&mut self, img: &RgbImage) -> Result<Vec<i64>, String>
pub fn predict_otsl(&mut self, img: &RgbImage) -> Result<Vec<i64>, String>
Predict the OTSL structure-token sequence for a table-region image.
Sourcepub fn predict_table_structure(
&mut self,
img: &RgbImage,
) -> Result<Vec<TableCell>, String>
pub fn predict_table_structure( &mut self, img: &RgbImage, ) -> Result<Vec<TableCell>, String>
Full structure prediction: OTSL grid cells with per-cell boxes (in the 448 image, normalized cxcywh). Collects per-cell decoder hidden states using docling’s exact bbox bookkeeping (skip-after-row-break, first-lcel of a horizontal span), runs the bbox decoder, merges span boxes, then lays the cells onto the OTSL grid with row/col spans.
Examples found in repository?
24fn main() {
25 let path = std::env::args().nth(1).expect("usage: tf_otsl <pdf>");
26 let bytes = std::fs::read(&path).expect("read");
27 let doc = PdfDocument::open(&bytes, None).expect("open");
28 let mut layout = LayoutModel::load().expect("layout");
29 let mut tf = TableFormer::load().expect("tableformer models missing");
30 for (pi, page) in doc.pages.iter().enumerate() {
31 let regions = layout
32 .predict(&page.image, page.width, page.height)
33 .expect("layout");
34 // docling resizes the whole page to 1024px height (cv2.INTER_AREA), then
35 // crops the table bbox out of *that*. Replicate exactly.
36 let sf = 1024.0 / page.image.height() as f32;
37 let pw1024 = (page.image.width() as f32 * sf) as u32; // docling: int(w*r)
38 let page1024 = fleischwolf_pdf::resample::inter_area(&page.image, pw1024, 1024);
39 for r in regions.iter().filter(|r| r.label == "table") {
40 // bbox (points) → 1024px-page coords: scale*sf = 1024/page_h_pt;
41 // docling rounds the crop edges.
42 let k = 1024.0 / page.height;
43 let x = (r.l * k).round().max(0.0) as u32;
44 let y = (r.t * k).round().max(0.0) as u32;
45 let x2 = (r.r * k).round() as u32;
46 let y2 = (r.b * k).round() as u32;
47 let (w, h) = (x2 - x, y2 - y);
48 let crop = imageops::crop_imm(&page1024, x, y, w, h).to_image();
49 let cells = tf.predict_table_structure(&crop).expect("predict");
50 println!(
51 "page {} table {}x{}px -> {} cells",
52 pi + 1,
53 w,
54 h,
55 cells.len()
56 );
57 for c in &cells {
58 println!(
59 " r{} c{} {}x{} {} | cxcywh {:.4} {:.4} {:.4} {:.4}",
60 c.row,
61 c.col,
62 c.colspan,
63 c.rowspan,
64 name(c.tag),
65 c.cx,
66 c.cy,
67 c.w,
68 c.h
69 );
70 }
71 }
72 }
73}Sourcepub fn predict_table_rows(
&mut self,
page_image: &RgbImage,
page_h: f32,
region: [f32; 4],
words: &[TextCell],
) -> Option<Vec<Vec<String>>>
pub fn predict_table_rows( &mut self, page_image: &RgbImage, page_h: f32, region: [f32; 4], words: &[TextCell], ) -> Option<Vec<Vec<String>>>
Predict a table region’s Markdown grid: crop the region (docling’s
page→1024px box-average then bbox crop), run the structure model, map each
cell box back to page points, match the page’s word cells into cells by
intersection-over-word-area, and expand spans into a dense rows × cols
grid. region is (l, t, r, b) in page points (top-left). Returns None
if no structure is predicted.
Auto Trait Implementations§
impl !RefUnwindSafe for TableFormer
impl !UnwindSafe for TableFormer
impl Freeze for TableFormer
impl Send for TableFormer
impl Sync for TableFormer
impl Unpin for TableFormer
impl UnsafeUnpin for TableFormer
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more