rlx_florence2/
postprocess.rs1use crate::config::task_post_processing_type;
25use crate::tokenizer::{Florence2Tokenizer, NUM_LOC_BINS};
26use anyhow::Result;
27
28#[derive(Debug, Clone, PartialEq)]
30pub struct BBoxInstance {
31 pub bbox: [f64; 4],
32 pub label: String,
33}
34
35#[derive(Debug, Clone, PartialEq)]
37pub struct QuadInstance {
38 pub quad_box: [f64; 8],
39 pub text: String,
40}
41
42#[derive(Debug, Clone, PartialEq)]
44pub struct PolygonInstance {
45 pub polygons: Vec<Vec<f64>>,
46 pub label: String,
47}
48
49#[derive(Debug, Clone, PartialEq)]
51pub enum Florence2Result {
52 PureText(String),
53 BBoxes(Vec<BBoxInstance>),
54 Ocr(Vec<QuadInstance>),
55 Polygons(Vec<PolygonInstance>),
56}
57
58fn dequant(n: usize, size: f64) -> f64 {
60 let per_bin = size / NUM_LOC_BINS as f64;
61 (n as f64 + 0.5) * per_bin
62}
63
64struct Segment {
66 label: String,
67 locs: Vec<usize>,
68}
69
70fn segment(ids: &[u32], tk: &Florence2Tokenizer) -> Result<Vec<Segment>> {
72 let mut segs: Vec<Segment> = Vec::new();
73 let mut text_buf: Vec<u32> = Vec::new();
74 let mut i = 0;
75 while i < ids.len() {
76 if tk.loc_index(ids[i]).is_some() {
77 let mut locs = Vec::new();
79 while i < ids.len() {
80 if let Some(b) = tk.loc_index(ids[i]) {
81 locs.push(b);
82 i += 1;
83 } else {
84 break;
85 }
86 }
87 let label = tk.decode(&text_buf)?.trim().to_string();
88 text_buf.clear();
89 segs.push(Segment { label, locs });
90 } else {
91 text_buf.push(ids[i]);
92 i += 1;
93 }
94 }
95 Ok(segs)
96}
97
98pub fn post_process(
100 task: &str,
101 ids: &[u32],
102 tk: &Florence2Tokenizer,
103 image_size: (f64, f64),
104) -> Result<Florence2Result> {
105 match task_post_processing_type(task) {
106 "pure_text" => Ok(Florence2Result::PureText(clean_text(ids, tk)?)),
107 "description_with_bboxes" | "bboxes" | "phrase_grounding" => {
108 Ok(Florence2Result::BBoxes(parse_bboxes(ids, tk, image_size)?))
109 }
110 "ocr" => Ok(Florence2Result::Ocr(parse_ocr(ids, tk, image_size)?)),
111 "polygons" => Ok(Florence2Result::Polygons(parse_polygons(
112 ids, tk, image_size,
113 )?)),
114 "description_with_bboxes_or_polygons" => {
115 let has_poly = ids.iter().any(|&t| {
117 tk.decode_keep_special(&[t])
118 .map(|s| s.contains("<poly>"))
119 .unwrap_or(false)
120 });
121 if has_poly {
122 Ok(Florence2Result::Polygons(parse_polygons(
123 ids, tk, image_size,
124 )?))
125 } else {
126 Ok(Florence2Result::BBoxes(parse_bboxes(ids, tk, image_size)?))
127 }
128 }
129 _ => Ok(Florence2Result::PureText(clean_text(ids, tk)?)),
130 }
131}
132
133fn clean_text(ids: &[u32], tk: &Florence2Tokenizer) -> Result<String> {
134 Ok(tk.decode(ids)?.trim().to_string())
135}
136
137fn parse_bboxes(
139 ids: &[u32],
140 tk: &Florence2Tokenizer,
141 image_size: (f64, f64),
142) -> Result<Vec<BBoxInstance>> {
143 let (w, h) = image_size;
144 let mut out = Vec::new();
145 for seg in segment(ids, tk)? {
146 for chunk in seg.locs.chunks_exact(4) {
147 out.push(BBoxInstance {
148 bbox: [
149 dequant(chunk[0], w),
150 dequant(chunk[1], h),
151 dequant(chunk[2], w),
152 dequant(chunk[3], h),
153 ],
154 label: seg.label.clone(),
155 });
156 }
157 }
158 Ok(out)
159}
160
161fn parse_ocr(
163 ids: &[u32],
164 tk: &Florence2Tokenizer,
165 image_size: (f64, f64),
166) -> Result<Vec<QuadInstance>> {
167 let (w, h) = image_size;
168 let mut out = Vec::new();
169 for seg in segment(ids, tk)? {
170 for chunk in seg.locs.chunks_exact(8) {
171 let mut quad = [0f64; 8];
172 for p in 0..4 {
173 quad[p * 2] = dequant(chunk[p * 2], w);
174 quad[p * 2 + 1] = dequant(chunk[p * 2 + 1], h);
175 }
176 out.push(QuadInstance {
177 quad_box: quad,
178 text: seg.label.clone(),
179 });
180 }
181 }
182 Ok(out)
183}
184
185fn parse_polygons(
188 ids: &[u32],
189 tk: &Florence2Tokenizer,
190 image_size: (f64, f64),
191) -> Result<Vec<PolygonInstance>> {
192 let (w, h) = image_size;
193 let mut out = Vec::new();
194 for seg in segment(ids, tk)? {
195 if seg.locs.is_empty() {
196 continue;
197 }
198 let mut poly = Vec::new();
199 for pair in seg.locs.chunks_exact(2) {
200 poly.push(dequant(pair[0], w));
201 poly.push(dequant(pair[1], h));
202 }
203 out.push(PolygonInstance {
204 polygons: vec![poly],
205 label: seg.label.clone(),
206 });
207 }
208 Ok(out)
209}