Skip to content

Commit 1e8e89c

Browse files
authored
Add PP-Doclayout-V3 (#233)
1 parent ad07c2c commit 1e8e89c

6 files changed

Lines changed: 98 additions & 4 deletions

File tree

docs/model-zoo/ocr.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ hide:
1818
| [DocLayout-YOLO](https://github.com/opendatalab/DocLayout-YOLO) | Object Detection | [demo](https://github.com/jamjamjon/usls/tree/main/examples/ocr) ||||||||
1919
| [PP-DocLayout-v1-Plus-L](https://huggingface.co/PaddlePaddle/PP-DocLayout_plus-L) | Object Detection | [demo](https://github.com/jamjamjon/usls/tree/main/examples/ocr) ||||||||
2020
| [PP-DocLayout-v2](https://huggingface.co/PaddlePaddle/PP-DocLayoutV2) | Object Detection | [demo](https://github.com/jamjamjon/usls/tree/main/examples/ocr) ||||||||
21+
| [PP-DocLayout-v3](https://huggingface.co/PaddlePaddle/PP-DocLayoutV3) | Object Detection | [demo](https://github.com/jamjamjon/usls/tree/main/examples/ocr) ||||||||

examples/ocr/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ cargo run -F cuda-full -F vlm --example ocr -- picodet-layout --device cuda:0 --
3636

3737
## PP-DocLayout v1/v2
3838
cargo run -F cuda-full -F vlm --example ocr -- pp-doclayout --device cuda:0 --processor-device cuda:0 --source images/academic.jpg --ver 1 --dtype fp32
39+
40+
41+
## PP-DocLayout v3
42+
cargo run -F cuda-full -F vlm --example ocr -- pp-doclayout --device cuda:0 --processor-device cuda:0 --source images/vl1.58.png --ver 3 --dtype fp32
3943
```
4044

4145
### Table structure recognition
@@ -53,3 +57,4 @@ cargo run -F cuda-full -F vlm --example ocr -- slanet --device cuda:0 --processo
5357
![](https://github.com/jamjamjon/assets/releases/download/db/demo-table-ch.png)
5458
![](https://github.com/jamjamjon/assets/releases/download/db/demo-sign.png)
5559
![](https://github.com/jamjamjon/assets/releases/download/yolo/demo-doclayout-yolo.png)
60+
![](https://github.com/jamjamjon/assets/releases/download/pp-doclayout/demo-v3.jpg)

examples/ocr/main.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,21 @@ fn main() -> Result<()> {
214214
}
215215
Commands::PpDoclayout(args) => {
216216
let config = pp_doclayout::config(args)?.commit()?;
217-
let annotator = Annotator::default();
217+
let annotator = match args.ver.0 {
218+
3 => Annotator::default()
219+
.with_hbb_style(
220+
usls::HbbStyle::default()
221+
.with_visible(false)
222+
.with_text_visible(false),
223+
)
224+
.with_mask_style(
225+
usls::MaskStyle::default()
226+
.with_visible(false)
227+
.with_cutout(true)
228+
.with_draw_obbs(true),
229+
),
230+
_ => Annotator::default(),
231+
};
218232
run::<PPDocLayout>(config, &cli.source, &annotator, RUN_DOC_LAYOUT)
219233
}
220234
}?;

examples/ocr/pp_doclayout.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ pub fn config(args: &PPDoclayoutArgs) -> Result<Config> {
4141
let config = match args.ver {
4242
Version(1, _, _) => Config::pp_doclayout_v1_plus_l(),
4343
Version(2, _, _) => Config::pp_doclayout_v2(),
44+
Version(3, _, _) => Config::pp_doclayout_v3(),
4445
_ => anyhow::bail!("Unsupported version"),
4546
}
4647
.with_dtype_all(args.dtype)

src/models/vision/pp_doclayout/config.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
/// >
77
/// > # Paper & Code
88
/// >
9+
/// > - **v3 Model**: https://huggingface.co/PaddlePaddle/PP-DocLayoutV3
910
/// > - **v2 Model**: https://huggingface.co/PaddlePaddle/PP-DocLayoutV2
1011
/// > - **v1 Model**: https://huggingface.co/PaddlePaddle/PP-DocLayout_plus-L
1112
/// > - **GitHub**: [PaddlePaddle/PaddleOCR](https://github.com/PaddlePaddle/PaddleOCR)
@@ -28,7 +29,7 @@ impl crate::Config {
2829
.with_model_ixx(1, 2, 800)
2930
.with_model_ixx(1, 3, 800)
3031
.with_model_ixx(2, 1, 2) // scale factors
31-
.with_class_confs(&[0.5])
32+
.with_class_confs(&[0.35])
3233
.with_resize_alg(crate::ResizeAlg::Interpolation(
3334
crate::ResizeFilter::Bilinear,
3435
))
@@ -50,4 +51,14 @@ impl crate::Config {
5051
.with_class_names(&crate::NAMES_PP_DOC_LAYOUT_V2_25)
5152
.with_model_file("v2.onnx")
5253
}
54+
55+
/// PP-DocLayoutV3 configuration (25 classes with reading order)
56+
/// PP-DocLayoutV3 is specifically engineered to handle non-planar document images.
57+
/// It can directly predict multi-point bounding boxes for layout elements—as opposed to standard two-point boxes—and determine logical reading orders for skewed and curved surfaces within a single forward pass, significantly reducing cascading errors.
58+
pub fn pp_doclayout_v3() -> Self {
59+
Self::pp_doclayout()
60+
.with_version(3.into())
61+
.with_class_names(&crate::NAMES_PP_DOC_LAYOUT_V2_25)
62+
.with_model_file("v3.onnx")
63+
}
5364
}

src/models/vision/pp_doclayout/impl.rs

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ use rayon::prelude::*;
55

66
use crate::{
77
elapsed_module, inputs, Config, DynConf, Engine, Engines, FromConfig, Hbb, Image,
8-
ImageProcessor, Model, Module, Version, Xs, X, Y,
8+
ImageProcessor, Mask, Model, Module, Ops, Version, Xs, X, Y,
99
};
1010

11-
/// RT-DETR: Real-Time Detection Transformer
11+
/// PP-DocLayoutsss-v1/v2/v3
1212
#[derive(Debug, Builder)]
1313
pub struct PPDocLayout {
1414
pub height: usize,
@@ -158,6 +158,68 @@ impl PPDocLayout {
158158

159159
Ok(ys)
160160
}
161+
Version(3, _, _) => {
162+
// preds: [batch * max_det, 7],[label_index, score, xmin, ymin, xmax, ymax, reading_order]
163+
let preds_reshaped = preds.to_shape([self.batch, self.max_det, 7])?;
164+
let preds_masks = xs
165+
.get::<f32>(2)
166+
.ok_or_else(|| anyhow::anyhow!("Failed to get masks"))?;
167+
let preds_masks = preds_masks.to_shape([self.batch, self.max_det, 200, 200])?;
168+
169+
let ys: Vec<Y> = preds_reshaped
170+
.axis_iter(Axis(0))
171+
.into_par_iter()
172+
.zip(preds_masks.axis_iter(Axis(0)).into_par_iter())
173+
.enumerate()
174+
.filter_map(|(idx, (preds, preds_masks))| {
175+
let info = &self.processor.images_transform_info[idx];
176+
let (image_height, image_width) = (info.height_src, info.width_src);
177+
178+
let mut items: Vec<(Hbb, Mask, usize)> = preds
179+
.outer_iter()
180+
.zip(preds_masks.outer_iter())
181+
.filter_map(|(pred_slice, pred_mask)| {
182+
let slice = pred_slice.as_slice()?;
183+
let hbb = f(slice)?;
184+
let order = slice[6] as usize;
185+
let (mh, mw) = (pred_mask.shape()[0], pred_mask.shape()[1]);
186+
let (ih, iw) = (image_height, image_width);
187+
let mask_f32: Vec<f32> =
188+
pred_mask.iter().map(|&x| 1. / (1. + (-x).exp())).collect();
189+
let mask_f32: Vec<f32> = Ops::interpolate_1d(
190+
&mask_f32, mw as _, mh as _, iw as _, ih as _, false,
191+
)
192+
.ok()?;
193+
let mask_u8: Vec<u8> = mask_f32
194+
.into_iter()
195+
.map(|x| if x <= 0.5 { 0 } else { 1 })
196+
.collect();
197+
198+
let mut mask = Mask::new(&mask_u8, iw as _, ih as _).ok()?;
199+
200+
if let Some(id) = hbb.id() {
201+
mask = mask.with_id(id);
202+
}
203+
if let Some(name) = hbb.name() {
204+
mask = mask.with_name(name);
205+
}
206+
if let Some(confidence) = hbb.confidence() {
207+
mask = mask.with_confidence(confidence);
208+
}
209+
210+
Some((hbb, mask, order))
211+
})
212+
.collect();
213+
214+
items.sort_by(|a, b| a.2.cmp(&b.2));
215+
let hbbs: Vec<Hbb> = items.iter().map(|(h, _, _)| h.clone()).collect();
216+
let masks: Vec<Mask> = items.into_iter().map(|(_, m, _)| m).collect();
217+
Some(Y::default().with_hbbs(&hbbs).with_masks(&masks))
218+
})
219+
.collect();
220+
221+
Ok(ys)
222+
}
161223
_ => anyhow::bail!("Unsupported version"),
162224
}
163225
}

0 commit comments

Comments
 (0)