Skip to content

Commit a399365

Browse files
committed
feat(ocr): 结构图过滤规则修正——Text区域同过图结构门控+形状约束
1 parent 5052940 commit a399365

2 files changed

Lines changed: 40 additions & 11 deletions

File tree

‎app/src-tauri/src/structure_detect.rs‎

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,12 @@ pub fn diagram_likeness(grid: &FrameGrid, x0: u32, y0: u32, x1: u32, y1: u32) ->
4747
if w < 2 || h < 2 {
4848
return 0.0;
4949
}
50+
// 形状约束(实现校准):标题细条/单行词条不可能是图结构——区域必须
51+
// 是"块状"(高 ≥3 格、宽 ≥6 格)。真实流程图页密度高被判 Text,
52+
// 行带可能是框线连成的大块;长标题是 1-2 格高的细条,借此拒绝。
53+
if h < 3 || w < 6 {
54+
return 0.0;
55+
}
5056
// ① 长直线特征:行/列最长连续墨迹段 + 含长段行数
5157
let mut max_h_run = 0u32;
5258
let mut line_rows = 0u32;
@@ -169,9 +175,11 @@ pub fn pick_sharpest(candidates: &[(u64, FrameGrid)]) -> Option<usize> {
169175

170176
/// 结构图候选过滤(纯函数):版面区域 → 值得持久化的子集。
171177
///
172-
/// @ai-context: table/formula/code 直收(is_structural);Image 过
173-
/// diagram_likeness 阈值;text/unknown 跳过。输入输出均为
174-
/// 网格坐标(编排层随后 regions_to_frame 换算帧坐标裁剪)。
178+
/// @ai-context: table/formula/code 直收(is_structural);Image/Text 均过
179+
/// diagram_likeness 阈值(实现校准:真实流程图页密度高被判
180+
/// Text——长直线+形状约束天然拒纯文字/标题,故 Text 同门控);
181+
/// unknown 跳过(归 V1.0 AI 补缝)。输入输出均为网格坐标
182+
/// (编排层随后 regions_to_frame 换算帧坐标裁剪)。
175183
pub fn filter_structure_regions(
176184
regions: &[LayoutRegion],
177185
grid: &FrameGrid,
@@ -180,11 +188,11 @@ pub fn filter_structure_regions(
180188
.iter()
181189
.filter(|r| match r.kind {
182190
RegionKind::Table | RegionKind::Formula | RegionKind::Code => true,
183-
RegionKind::Image => {
191+
RegionKind::Image | RegionKind::Text => {
184192
diagram_likeness(grid, r.x, r.y, r.x + r.w - 1, r.y + r.h - 1)
185193
>= DIAGRAM_LIKENESS_THRESHOLD
186194
}
187-
RegionKind::Text | RegionKind::Unknown => false,
195+
RegionKind::Unknown => false,
188196
})
189197
.cloned()
190198
.collect()

‎app/src-tauri/src/structure_detect_tests.rs‎

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,19 @@ fn diagram_text_line_rejected() {
123123
assert!(score < crate::structure_detect::DIAGRAM_LIKENESS_THRESHOLD);
124124
}
125125

126+
#[test]
127+
fn diagram_title_strip_rejected_by_shape() {
128+
// Arrange:长标题细条(高 1-2 格、长词连续段占比高——形状约束拒绝)
129+
let mut g = blank(32, 18, 255);
130+
paint(&mut g, 2, 6, 25, 6); // 24 格长段、单行
131+
132+
// Act:区域 h=1(细条)
133+
let score = diagram_likeness(&g, 2, 6, 25, 6);
134+
135+
// Assert:形状约束(h<3)→ 0 分——长标题不误收
136+
assert_eq!(score, 0.0);
137+
}
138+
126139
#[test]
127140
fn diagram_out_of_bounds_and_tiny_region_zero() {
128141
// Arrange:全屏空白 + 越界/过小区域
@@ -197,26 +210,34 @@ fn pick_sharpest_skips_zero_energy_frames() {
197210

198211
#[test]
199212
fn filter_structure_kinds_direct_and_image_gated() {
200-
// Arrange:流程图样网格 + 混合区域列表
213+
// Arrange:流程图样网格 + 混合区域列表(含"被判 Text 的流程图区域"——
214+
// 实现校准:真实流程图密度高被判 Text,同过图结构门控)
201215
let g = flowchart_like();
202216
let regions = vec![
203217
region(RegionKind::Table, 0, 0, 5, 3),
204218
region(RegionKind::Formula, 0, 4, 5, 3),
205219
region(RegionKind::Code, 0, 8, 5, 3),
206-
region(RegionKind::Image, 4, 3, 20, 8), // 流程图区域(应过阈值)
220+
region(RegionKind::Text, 4, 3, 20, 8), // 流程图区域被判 Text(应过门控)
221+
region(RegionKind::Image, 4, 3, 20, 8), // 同区域 Image(应过门控)
207222
region(RegionKind::Image, 0, 12, 8, 4), // 空白区域(应拒)
208-
region(RegionKind::Text, 26, 0, 5, 3),
223+
region(RegionKind::Text, 26, 0, 5, 3), // 小文字区域(形状约束拒)
209224
region(RegionKind::Unknown, 26, 5, 5, 3),
210225
];
211226

212227
// Act
213228
let kept = filter_structure_regions(&regions, &g);
214229

215-
// Assert:结构三类直收 + Image 阈值门控;text/unknown 跳过
230+
// Assert:结构三类直收 + Text/Image 过图结构门控;小文字/空白/unknown 跳过
216231
let kinds: Vec<RegionKind> = kept.iter().map(|r| r.kind).collect();
217232
assert_eq!(
218233
kinds,
219-
vec![RegionKind::Table, RegionKind::Formula, RegionKind::Code, RegionKind::Image]
234+
vec![
235+
RegionKind::Table,
236+
RegionKind::Formula,
237+
RegionKind::Code,
238+
RegionKind::Text,
239+
RegionKind::Image
240+
]
220241
);
221-
assert_eq!(kept.last().unwrap().x, 4); // 保留的是流程图区域而非空白区域
242+
assert_eq!(kept[3].x, 4); // Text 流程图区域保留
222243
}

0 commit comments

Comments
 (0)